Browse Source

Refactor, rename 'include' to 'join'

Maurits van der Schee 6 years ago
parent
commit
865a75aaff

+ 6
- 6
README.md View File

@@ -109,10 +109,10 @@ These features match features in v1 (see branch "v1"):
109 109
   - [ ] Permission system for databases, tables, columns and records
110 110
   - [ ] Multi-tenant database layouts are supported
111 111
   - [x] Multi-domain CORS support for cross-domain requests
112
-  - [x] Combined requests with support for multiple table names
112
+  - [x] Support for reading joined results from multiple tables
113 113
   - [x] Search support on multiple criteria
114 114
   - [x] Pagination, seeking, sorting and column selection
115
-  - [x] Relation detection nested results (belongsTo, hasMany and HABTM)
115
+  - [x] Relation detection with nested results (belongsTo, hasMany and HABTM)
116 116
   - [ ] ~~Relation "transforms" (of condensed JSON) for PHP and JavaScript~~
117 117
   - [x] Atomic increment support via PATCH (for counters)
118 118
   - [x] Binary fields supported with base64 encoding
@@ -215,7 +215,7 @@ Where "1" is the value of the primary key of the record that you want to read. I
215 215
         "created": "2018-03-05T20:12:56Z"
216 216
     }
217 217
 
218
-On read operations you may apply includes.
218
+On read operations you may apply joins.
219 219
 
220 220
 #### Update
221 221
 
@@ -262,7 +262,7 @@ It will return:
262 262
         ]
263 263
     }
264 264
 
265
-On list operations you may apply filters and includes.
265
+On list operations you may apply filters and joins.
266 266
 
267 267
 ### Filters
268 268
 
@@ -319,7 +319,7 @@ by adding a letter (a-f) you can create almost any reasonably complex condition
319 319
 
320 320
 NB: You can only filter on the requested table (not on it's included) and filters are only applied on list calls.
321 321
 
322
-### Includes
322
+### Joins
323 323
 
324 324
 Let's say that you have a posts table that has comments (made by users) and the posts can have tags.
325 325
 
@@ -337,7 +337,7 @@ When you want to list posts with their comments users and tags you can ask for t
337 337
 
338 338
 These paths have the same root and this request can be written in URL format as:
339 339
 
340
-    GET /records/posts?include=comments,users&include=tags
340
+    GET /records/posts?join=comments,users&join=tags
341 341
 
342 342
 Here you are allowed to leave out the intermediate table that binds posts to tags. In this example
343 343
 you see all three table relation types (hasMany, belongsTo and hasAndBelongsToMany) in effect:

+ 169
- 51
api.php View File

@@ -667,7 +667,7 @@ class DefinitionService
667 667
 
668 668
     public function updateTable(String $tableName, /* object */ $changes): bool
669 669
     {
670
-        $table = $database->get($tableName);
670
+        $table = $this->reflection->getTable($tableName);
671 671
         $newTable = ReflectedTable::fromJson((object) array_merge((array) $table->jsonSerialize(), (array) $changes));
672 672
         if ($table->getName() != $newTable->getName()) {
673 673
             if (!$this->db->definition()->renameTable($table->getName(), $newTable->getName())) {
@@ -679,7 +679,7 @@ class DefinitionService
679 679
 
680 680
     public function updateColumn(String $tableName, String $columnName, /* object */ $changes): bool
681 681
     {
682
-        $table = $database->get($tableName);
682
+        $table = $this->reflection->getTable($tableName);
683 683
         $column = $table->get($columnName);
684 684
 
685 685
         $newColumn = ReflectedColumn::fromJson((object) array_merge((array) $column->jsonSerialize(), (array) $changes));
@@ -780,7 +780,7 @@ class DefinitionService
780 780
 
781 781
     public function removeColumn(String $tableName, String $columnName)
782 782
     {
783
-        $table = $database->get($tableName);
783
+        $table = $this->reflection->getTable($tableName);
784 784
         $newColumn = $table->get($columnName);
785 785
         if ($newColumn->getPk()) {
786 786
             $newColumn->setPk(false);
@@ -816,19 +816,25 @@ class ReflectionService
816 816
         $this->db = $db;
817 817
         $this->cache = $cache;
818 818
         $this->ttl = $ttl;
819
-        $data = $this->cache->get('ReflectedDatabase');
819
+        $this->tables = $this->loadTables(true);
820
+    }
821
+
822
+    private function loadTables(bool $useCache): ReflectedDatabase
823
+    {
824
+        $data = $useCache ? $this->cache->get('ReflectedDatabase') : '';
820 825
         if ($data != '') {
821
-            $this->tables = ReflectedDatabase::fromJson(json_decode(gzuncompress($data)));
826
+            $tables = ReflectedDatabase::fromJson(json_decode(gzuncompress($data)));
822 827
         } else {
823
-            $this->refresh();
828
+            $tables = ReflectedDatabase::fromReflection($this->db->reflection());
829
+            $data = gzcompress(json_encode($tables, JSON_UNESCAPED_UNICODE));
830
+            $this->cache->set('ReflectedDatabase', $data, $this->ttl);
824 831
         }
832
+        return $tables;
825 833
     }
826 834
 
827 835
     public function refresh()
828 836
     {
829
-        $this->tables = ReflectedDatabase::fromReflection($this->db->reflection());
830
-        $data = gzcompress(json_encode($this->tables, JSON_UNESCAPED_UNICODE));
831
-        $this->cache->set('ReflectedDatabase', $data, $this->ttl);
837
+        $this->tables = $this->loadTables(false);
832 838
     }
833 839
 
834 840
     public function hasTable(String $table): bool
@@ -901,11 +907,10 @@ class ColumnController
901 907
     public function getTable(Request $request): Response
902 908
     {
903 909
         $tableName = $request->getPathSegment(2);
904
-        $database = $this->reflection->getDatabase();
905
-        if (!$database->exists($tableName)) {
910
+        if (!$this->reflection->hasTable($tableName)) {
906 911
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
907 912
         }
908
-        $table = $database->get($tableName);
913
+        $table = $this->reflection->getTable($tableName);
909 914
         return $this->responder->success($table);
910 915
     }
911 916
 
@@ -913,11 +918,10 @@ class ColumnController
913 918
     {
914 919
         $tableName = $request->getPathSegment(2);
915 920
         $columnName = $request->getPathSegment(3);
916
-        $database = $this->reflection->getDatabase();
917
-        if (!$database->exists($tableName)) {
921
+        if (!$this->reflection->hasTable($tableName)) {
918 922
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
919 923
         }
920
-        $table = $database->get($tableName);
924
+        $table = $this->reflection->getTable($tableName);
921 925
         if (!$table->exists($columnName)) {
922 926
             return $this->responder->error(ErrorCode::COLUMN_NOT_FOUND, $columnName);
923 927
         }
@@ -928,8 +932,7 @@ class ColumnController
928 932
     public function updateTable(Request $request): Response
929 933
     {
930 934
         $tableName = $request->getPathSegment(2);
931
-        $database = $this->reflection->getDatabase();
932
-        if (!$database->exists($tableName)) {
935
+        if (!$this->reflection->hasTable($tableName)) {
933 936
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
934 937
         }
935 938
         $success = $this->definition->updateTable($tableName, $request->getBody());
@@ -943,11 +946,10 @@ class ColumnController
943 946
     {
944 947
         $tableName = $request->getPathSegment(2);
945 948
         $columnName = $request->getPathSegment(3);
946
-        $database = $this->reflection->getDatabase();
947
-        if (!$database->exists($tableName)) {
949
+        if (!$this->reflection->hasTable($tableName)) {
948 950
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
949 951
         }
950
-        $table = $database->get($tableName);
952
+        $table = $this->reflection->getTable($tableName);
951 953
         if (!$table->exists($columnName)) {
952 954
             return $this->responder->error(ErrorCode::COLUMN_NOT_FOUND, $columnName);
953 955
         }
@@ -974,12 +976,11 @@ class ColumnController
974 976
     public function addColumn(Request $request): Response
975 977
     {
976 978
         $tableName = $request->getPathSegment(2);
977
-        $database = $this->reflection->getDatabase();
978
-        if (!$database->exists($tableName)) {
979
+        if (!$this->reflection->hasTable($tableName)) {
979 980
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
980 981
         }
981 982
         $columnName = $request->getBody()->name;
982
-        $table = $database->get($tableName);
983
+        $table = $this->reflection->getTable($tableName);
983 984
         if ($table->exists($columnName)) {
984 985
             return $this->responder->error(ErrorCode::COLUMN_ALREADY_EXISTS, $columnName);
985 986
         }
@@ -993,8 +994,7 @@ class ColumnController
993 994
     public function removeTable(Request $request): Response
994 995
     {
995 996
         $tableName = $request->getPathSegment(2);
996
-        $database = $this->reflection->getDatabase();
997
-        if (!$database->exists($tableName)) {
997
+        if (!$this->reflection->hasTable($tableName)) {
998 998
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
999 999
         }
1000 1000
         $success = $this->definition->removeTable($tableName);
@@ -1008,11 +1008,10 @@ class ColumnController
1008 1008
     {
1009 1009
         $tableName = $request->getPathSegment(2);
1010 1010
         $columnName = $request->getPathSegment(3);
1011
-        $database = $this->reflection->getDatabase();
1012
-        if (!$database->exists($tableName)) {
1011
+        if (!$this->reflection->hasTable($tableName)) {
1013 1012
             return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $tableName);
1014 1013
         }
1015
-        $table = $database->get($tableName);
1014
+        $table = $this->reflection->getTable($tableName);
1016 1015
         if (!$table->exists($columnName)) {
1017 1016
             return $this->responder->error(ErrorCode::COLUMN_NOT_FOUND, $columnName);
1018 1017
         }
@@ -1170,6 +1169,36 @@ class RecordController
1170 1169
         }
1171 1170
     }
1172 1171
 
1172
+    public function increment(Request $request): Response
1173
+    {
1174
+        $table = $request->getPathSegment(2);
1175
+        $id = $request->getPathSegment(3);
1176
+        $record = $request->getBody();
1177
+        if ($record === null) {
1178
+            return $this->responder->error(ErrorCode::HTTP_MESSAGE_NOT_READABLE, '');
1179
+        }
1180
+        $params = $request->getParams();
1181
+        if (!$this->service->exists($table)) {
1182
+            return $this->responder->error(ErrorCode::TABLE_NOT_FOUND, $table);
1183
+        }
1184
+        $ids = explode(',', $id);
1185
+        if (is_array($record)) {
1186
+            if (count($ids) != count($record)) {
1187
+                return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
1188
+            }
1189
+            $result = array();
1190
+            for ($i = 0; $i < count($ids); $i++) {
1191
+                $result[] = $this->service->increment($table, $ids[$i], $record[$i], $params);
1192
+            }
1193
+            return $this->responder->success($result);
1194
+        } else {
1195
+            if (count($ids) != 1) {
1196
+                return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
1197
+            }
1198
+            return $this->responder->success($this->service->increment($table, $id, $record, $params));
1199
+        }
1200
+    }
1201
+
1173 1202
 }
1174 1203
 
1175 1204
 // file: src/Tqdev/PhpCrudApi/Controller/Responder.php
@@ -1840,6 +1869,22 @@ class GenericDB
1840 1869
         return $stmt->rowCount();
1841 1870
     }
1842 1871
 
1872
+    public function incrementSingle(ReflectedTable $table, array $columnValues, String $id)
1873
+    {
1874
+        if (count($columnValues) == 0) {
1875
+            return 0;
1876
+        }
1877
+        $this->converter->convertColumnValues($table, $columnValues);
1878
+        $updateColumns = $this->columns->getIncrement($table, $columnValues);
1879
+        $tableName = $table->getName();
1880
+        $condition = new ColumnCondition($table->getPk(), 'eq', $id);
1881
+        $parameters = array_values($columnValues);
1882
+        $whereClause = $this->conditions->getWhereClause($condition, $parameters);
1883
+        $sql = 'UPDATE "' . $tableName . '" SET ' . $updateColumns . $whereClause;
1884
+        $stmt = $this->query($sql, $parameters);
1885
+        return $stmt->rowCount();
1886
+    }
1887
+
1843 1888
     private function query(String $sql, array $parameters): \PDOStatement
1844 1889
     {
1845 1890
         $stmt = $this->pdo->prepare($sql);
@@ -2662,6 +2707,51 @@ class SimpleRouter implements Router
2662 2707
     }
2663 2708
 }
2664 2709
 
2710
+// file: src/Tqdev/PhpCrudApi/Middleware/AuthorizationMiddleware.php
2711
+
2712
+class AuthorizationMiddleware extends Middleware
2713
+{
2714
+    private $reflection;
2715
+
2716
+    public function __construct(Router $router, Responder $responder, array $properties, ReflectionService $reflection)
2717
+    {
2718
+        parent::__construct($router, $responder, $properties);
2719
+        $this->reflection = $reflection;
2720
+    }
2721
+
2722
+    private function getJoins($all, $list)
2723
+    {
2724
+        $result = array_fill_keys($all, false);
2725
+        foreach ($lists as $items) {
2726
+            foreach (explode(',', $items) as $item) {
2727
+                if (isset($result[$item])) {
2728
+                    $result[$item] = true;
2729
+                }
2730
+            }
2731
+        }
2732
+        return $result;
2733
+    }
2734
+
2735
+    public function handle(Request $request): Response
2736
+    {
2737
+        $path = $request->getPathSegment(1);
2738
+        $tableName = $request->getPathSegment(2);
2739
+        $database = $this->reflection->getDatabase();
2740
+        $handler = $this->getProperty('handler', '');
2741
+        if ($handler !== '' && $path == 'records' && $database->exists($tableName)) {
2742
+            $method = $request->getMethod();
2743
+            $tableNames = $database->getTableNames();
2744
+            $params = $request->getParams();
2745
+            $joins = $this->getJoins($tableNames, $params['join']);
2746
+            $allowed = call_user_func($handler, $method, $tableName, $joins);
2747
+            if (!$allowed) {
2748
+                return $this->responder->error(ErrorCode::OPERATION_FORBIDDEN, '');
2749
+            }
2750
+        }
2751
+        return $this->next->handle($request);
2752
+    }
2753
+}
2754
+
2665 2755
 // file: src/Tqdev/PhpCrudApi/Middleware/BasicAuthMiddleware.php
2666 2756
 
2667 2757
 class BasicAuthMiddleware extends Middleware
@@ -2793,10 +2883,25 @@ class CorsMiddleware extends Middleware
2793 2883
 
2794 2884
 class FirewallMiddleware extends Middleware
2795 2885
 {
2886
+    private function ipMatch(String $ip, String $cidr): bool
2887
+    {
2888
+        if (strpos($cidr, '/') !== false) {
2889
+            list($subnet, $mask) = explode('/', trim($cidr));
2890
+            if ((ip2long($ip) & ~((1 << (32 - $mask)) - 1)) == ip2long($subnet)) {
2891
+                return true;
2892
+            }
2893
+        } else {
2894
+            if (ip2long($ip) == ip2long($cidr)) {
2895
+                return true;
2896
+            }
2897
+        }
2898
+        return false;
2899
+    }
2900
+
2796 2901
     private function isIpAllowed(String $ipAddress, String $allowedIpAddresses): bool
2797 2902
     {
2798 2903
         foreach (explode(',', $allowedIpAddresses) as $allowedIp) {
2799
-            if ($ipAddress == trim($allowedIp)) {
2904
+            if ($this->ipMatch($ipAddress, $allowedIp)) {
2800 2905
                 return true;
2801 2906
             }
2802 2907
         }
@@ -3411,6 +3516,7 @@ class ErrorCode
3411 3516
     const AUTHORIZATION_REQUIRED = 1011;
3412 3517
     const ACCESS_DENIED = 1012;
3413 3518
     const INPUT_VALIDATION_FAILED = 1013;
3519
+    const OPERATION_FORBIDDEN = 1014;
3414 3520
 
3415 3521
     private $values = [
3416 3522
         9999 => ["%s", Response::INTERNAL_SERVER_ERROR],
@@ -3428,6 +3534,7 @@ class ErrorCode
3428 3534
         1011 => ["Authorization required", Response::UNAUTHORIZED],
3429 3535
         1012 => ["Access denied for '%s'", Response::FORBIDDEN],
3430 3536
         1013 => ["Input validation failed for '%s'", Response::UNPROCESSABLE_ENTITY],
3537
+        1014 => ["Operation forbidden", Response::FORBIDDEN],
3431 3538
     ];
3432 3539
 
3433 3540
     public function __construct(int $code)
@@ -3656,7 +3763,7 @@ class RecordService
3656 3763
     private $db;
3657 3764
     private $tables;
3658 3765
     private $columns;
3659
-    private $includer;
3766
+    private $joiner;
3660 3767
     private $filters;
3661 3768
     private $ordering;
3662 3769
     private $pagination;
@@ -3666,7 +3773,7 @@ class RecordService
3666 3773
         $this->db = $db;
3667 3774
         $this->tables = $reflection->getDatabase();
3668 3775
         $this->columns = new ColumnSelector();
3669
-        $this->includer = new RelationIncluder($this->columns);
3776
+        $this->joiner = new RelationJoiner($this->columns);
3670 3777
         $this->filters = new FilterInfo();
3671 3778
         $this->ordering = new OrderingInfo();
3672 3779
         $this->pagination = new PaginationInfo();
@@ -3707,14 +3814,14 @@ class RecordService
3707 3814
     public function read(String $tableName, String $id, array $params) /*: ?object*/
3708 3815
     {
3709 3816
         $table = $this->tables->get($tableName);
3710
-        $this->includer->addMandatoryColumns($table, $this->tables, $params);
3817
+        $this->joiner->addMandatoryColumns($table, $this->tables, $params);
3711 3818
         $columnNames = $this->columns->getNames($table, true, $params);
3712 3819
         $record = $this->db->selectSingle($table, $columnNames, $id);
3713 3820
         if ($record == null) {
3714 3821
             return null;
3715 3822
         }
3716 3823
         $records = array($record);
3717
-        $this->includer->addIncludes($table, $records, $this->tables, $params, $this->db);
3824
+        $this->joiner->addJoins($table, $records, $this->tables, $params, $this->db);
3718 3825
         return $records[0];
3719 3826
     }
3720 3827
 
@@ -3732,10 +3839,18 @@ class RecordService
3732 3839
         return $this->db->deleteSingle($table, $id);
3733 3840
     }
3734 3841
 
3842
+    public function increment(String $tableName, String $id, /* object */ $record, array $params)
3843
+    {
3844
+        $this->sanitizeRecord($tableName, $record, $id);
3845
+        $table = $this->tables->get($tableName);
3846
+        $columnValues = $this->columns->getValues($table, true, $record, $params);
3847
+        return $this->db->incrementSingle($table, $columnValues, $id);
3848
+    }
3849
+
3735 3850
     public function _list(String $tableName, array $params): ListDocument
3736 3851
     {
3737 3852
         $table = $this->tables->get($tableName);
3738
-        $this->includer->addMandatoryColumns($table, $this->tables, $params);
3853
+        $this->joiner->addMandatoryColumns($table, $this->tables, $params);
3739 3854
         $columnNames = $this->columns->getNames($table, true, $params);
3740 3855
         $condition = $this->filters->getCombinedConditions($table, $params);
3741 3856
         $columnOrdering = $this->ordering->getColumnOrdering($table, $params);
@@ -3749,14 +3864,14 @@ class RecordService
3749 3864
             $count = $this->db->selectCount($table, $condition);
3750 3865
         }
3751 3866
         $records = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, $offset, $limit);
3752
-        $this->includer->addIncludes($table, $records, $this->tables, $params, $this->db);
3867
+        $this->joiner->addJoins($table, $records, $this->tables, $params, $this->db);
3753 3868
         return new ListDocument($records, $count);
3754 3869
     }
3755 3870
 }
3756 3871
 
3757
-// file: src/Tqdev/PhpCrudApi/Record/RelationIncluder.php
3872
+// file: src/Tqdev/PhpCrudApi/Record/RelationJoiner.php
3758 3873
 
3759
-class RelationIncluder
3874
+class RelationJoiner
3760 3875
 {
3761 3876
 
3762 3877
     private $columns;
@@ -3768,11 +3883,11 @@ class RelationIncluder
3768 3883
 
3769 3884
     public function addMandatoryColumns(ReflectedTable $table, ReflectedDatabase $tables, array &$params)/*: void*/
3770 3885
     {
3771
-        if (!isset($params['include']) || !isset($params['columns'])) {
3886
+        if (!isset($params['join']) || !isset($params['columns'])) {
3772 3887
             return;
3773 3888
         }
3774 3889
         $params['mandatory'] = array();
3775
-        foreach ($params['include'] as $tableNames) {
3890
+        foreach ($params['join'] as $tableNames) {
3776 3891
             $t1 = $table;
3777 3892
             foreach (explode(',', $tableNames) as $tableName) {
3778 3893
                 if (!$tables->exists($tableName)) {
@@ -3799,11 +3914,11 @@ class RelationIncluder
3799 3914
         }
3800 3915
     }
3801 3916
 
3802
-    private function getIncludesAsPathTree(ReflectedDatabase $tables, array $params): PathTree
3917
+    private function getJoinsAsPathTree(ReflectedDatabase $tables, array $params): PathTree
3803 3918
     {
3804
-        $includes = new PathTree();
3805
-        if (isset($params['include'])) {
3806
-            foreach ($params['include'] as $tableNames) {
3919
+        $joins = new PathTree();
3920
+        if (isset($params['join'])) {
3921
+            foreach ($params['join'] as $tableNames) {
3807 3922
                 $path = array();
3808 3923
                 foreach (explode(',', $tableNames) as $tableName) {
3809 3924
                     $t = $tables->get($tableName);
@@ -3811,17 +3926,17 @@ class RelationIncluder
3811 3926
                         $path[] = $t->getName();
3812 3927
                     }
3813 3928
                 }
3814
-                $includes->put($path, true);
3929
+                $joins->put($path, true);
3815 3930
             }
3816 3931
         }
3817
-        return $includes;
3932
+        return $joins;
3818 3933
     }
3819 3934
 
3820
-    public function addIncludes(ReflectedTable $table, array &$records, ReflectedDatabase $tables, array $params,
3935
+    public function addJoins(ReflectedTable $table, array &$records, ReflectedDatabase $tables, array $params,
3821 3936
         GenericDB $db)/*: void*/{
3822 3937
 
3823
-        $includes = $this->getIncludesAsPathTree($tables, $params);
3824
-        $this->addIncludesForTables($table, $includes, $records, $tables, $params, $db);
3938
+        $joins = $this->getJoinsAsPathTree($tables, $params);
3939
+        $this->addJoinsForTables($table, $joins, $records, $tables, $params, $db);
3825 3940
     }
3826 3941
 
3827 3942
     private function hasAndBelongsToMany(ReflectedTable $t1, ReflectedTable $t2, ReflectedDatabase $tables) /*: ?ReflectedTable*/
@@ -3835,10 +3950,10 @@ class RelationIncluder
3835 3950
         return null;
3836 3951
     }
3837 3952
 
3838
-    private function addIncludesForTables(ReflectedTable $t1, PathTree $includes, array &$records,
3953
+    private function addJoinsForTables(ReflectedTable $t1, PathTree $joins, array &$records,
3839 3954
         ReflectedDatabase $tables, array $params, GenericDB $db) {
3840 3955
 
3841
-        foreach ($includes->getKeys() as $t2Name) {
3956
+        foreach ($joins->getKeys() as $t2Name) {
3842 3957
 
3843 3958
             $t2 = $tables->get($t2Name);
3844 3959
 
@@ -3865,7 +3980,7 @@ class RelationIncluder
3865 3980
                 $this->addFkRecords($t2, $habtmValues->fkValues, $params, $db, $newRecords);
3866 3981
             }
3867 3982
 
3868
-            $this->addIncludesForTables($t2, $includes->get($t2Name), $newRecords, $tables, $params, $db);
3983
+            $this->addJoinsForTables($t2, $joins->get($t2Name), $newRecords, $tables, $params, $db);
3869 3984
 
3870 3985
             if ($fkValues != null) {
3871 3986
                 $this->fillFkValues($t2, $newRecords, $fkValues);
@@ -4066,6 +4181,9 @@ class Api
4066 4181
                 case 'sanitation':
4067 4182
                     new SanitationMiddleware($router, $responder, $properties, $reflection);
4068 4183
                     break;
4184
+                case 'authorization':
4185
+                    new AuthorizationMiddleware($router, $responder, $properties, $reflection);
4186
+                    break;
4069 4187
             }
4070 4188
         }
4071 4189
         $data = new RecordService($db, $reflection);

+ 3
- 3
src/Tqdev/PhpCrudApi/Middleware/AuthorizationMiddleware.php View File

@@ -19,7 +19,7 @@ class AuthorizationMiddleware extends Middleware
19 19
         $this->reflection = $reflection;
20 20
     }
21 21
 
22
-    private function getIncludes($all, $list)
22
+    private function getJoins($all, $list)
23 23
     {
24 24
         $result = array_fill_keys($all, false);
25 25
         foreach ($lists as $items) {
@@ -42,8 +42,8 @@ class AuthorizationMiddleware extends Middleware
42 42
             $method = $request->getMethod();
43 43
             $tableNames = $database->getTableNames();
44 44
             $params = $request->getParams();
45
-            $includes = $this->getIncludes($tableNames, $params['include']);
46
-            $allowed = call_user_func($handler, $method, $tableName, $includes);
45
+            $joins = $this->getJoins($tableNames, $params['join']);
46
+            $allowed = call_user_func($handler, $method, $tableName, $joins);
47 47
             if (!$allowed) {
48 48
                 return $this->responder->error(ErrorCode::OPERATION_FORBIDDEN, '');
49 49
             }

+ 6
- 6
src/Tqdev/PhpCrudApi/Record/RecordService.php View File

@@ -10,7 +10,7 @@ class RecordService
10 10
     private $db;
11 11
     private $tables;
12 12
     private $columns;
13
-    private $includer;
13
+    private $joiner;
14 14
     private $filters;
15 15
     private $ordering;
16 16
     private $pagination;
@@ -20,7 +20,7 @@ class RecordService
20 20
         $this->db = $db;
21 21
         $this->tables = $reflection->getDatabase();
22 22
         $this->columns = new ColumnSelector();
23
-        $this->includer = new RelationIncluder($this->columns);
23
+        $this->joiner = new RelationJoiner($this->columns);
24 24
         $this->filters = new FilterInfo();
25 25
         $this->ordering = new OrderingInfo();
26 26
         $this->pagination = new PaginationInfo();
@@ -61,14 +61,14 @@ class RecordService
61 61
     public function read(String $tableName, String $id, array $params) /*: ?object*/
62 62
     {
63 63
         $table = $this->tables->get($tableName);
64
-        $this->includer->addMandatoryColumns($table, $this->tables, $params);
64
+        $this->joiner->addMandatoryColumns($table, $this->tables, $params);
65 65
         $columnNames = $this->columns->getNames($table, true, $params);
66 66
         $record = $this->db->selectSingle($table, $columnNames, $id);
67 67
         if ($record == null) {
68 68
             return null;
69 69
         }
70 70
         $records = array($record);
71
-        $this->includer->addIncludes($table, $records, $this->tables, $params, $this->db);
71
+        $this->joiner->addJoins($table, $records, $this->tables, $params, $this->db);
72 72
         return $records[0];
73 73
     }
74 74
 
@@ -97,7 +97,7 @@ class RecordService
97 97
     public function _list(String $tableName, array $params): ListDocument
98 98
     {
99 99
         $table = $this->tables->get($tableName);
100
-        $this->includer->addMandatoryColumns($table, $this->tables, $params);
100
+        $this->joiner->addMandatoryColumns($table, $this->tables, $params);
101 101
         $columnNames = $this->columns->getNames($table, true, $params);
102 102
         $condition = $this->filters->getCombinedConditions($table, $params);
103 103
         $columnOrdering = $this->ordering->getColumnOrdering($table, $params);
@@ -111,7 +111,7 @@ class RecordService
111 111
             $count = $this->db->selectCount($table, $condition);
112 112
         }
113 113
         $records = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, $offset, $limit);
114
-        $this->includer->addIncludes($table, $records, $this->tables, $params, $this->db);
114
+        $this->joiner->addJoins($table, $records, $this->tables, $params, $this->db);
115 115
         return new ListDocument($records, $count);
116 116
     }
117 117
 }

src/Tqdev/PhpCrudApi/Record/RelationIncluder.php → src/Tqdev/PhpCrudApi/Record/RelationJoiner.php View File

@@ -7,7 +7,7 @@ use Tqdev\PhpCrudApi\Record\Condition\OrCondition;
7 7
 use Tqdev\PhpCrudApi\Column\Reflection\ReflectedDatabase;
8 8
 use Tqdev\PhpCrudApi\Column\Reflection\ReflectedTable;
9 9
 
10
-class RelationIncluder
10
+class RelationJoiner
11 11
 {
12 12
 
13 13
     private $columns;
@@ -19,11 +19,11 @@ class RelationIncluder
19 19
 
20 20
     public function addMandatoryColumns(ReflectedTable $table, ReflectedDatabase $tables, array &$params)/*: void*/
21 21
     {
22
-        if (!isset($params['include']) || !isset($params['columns'])) {
22
+        if (!isset($params['join']) || !isset($params['columns'])) {
23 23
             return;
24 24
         }
25 25
         $params['mandatory'] = array();
26
-        foreach ($params['include'] as $tableNames) {
26
+        foreach ($params['join'] as $tableNames) {
27 27
             $t1 = $table;
28 28
             foreach (explode(',', $tableNames) as $tableName) {
29 29
                 if (!$tables->exists($tableName)) {
@@ -50,11 +50,11 @@ class RelationIncluder
50 50
         }
51 51
     }
52 52
 
53
-    private function getIncludesAsPathTree(ReflectedDatabase $tables, array $params): PathTree
53
+    private function getJoinsAsPathTree(ReflectedDatabase $tables, array $params): PathTree
54 54
     {
55
-        $includes = new PathTree();
56
-        if (isset($params['include'])) {
57
-            foreach ($params['include'] as $tableNames) {
55
+        $joins = new PathTree();
56
+        if (isset($params['join'])) {
57
+            foreach ($params['join'] as $tableNames) {
58 58
                 $path = array();
59 59
                 foreach (explode(',', $tableNames) as $tableName) {
60 60
                     $t = $tables->get($tableName);
@@ -62,17 +62,17 @@ class RelationIncluder
62 62
                         $path[] = $t->getName();
63 63
                     }
64 64
                 }
65
-                $includes->put($path, true);
65
+                $joins->put($path, true);
66 66
             }
67 67
         }
68
-        return $includes;
68
+        return $joins;
69 69
     }
70 70
 
71
-    public function addIncludes(ReflectedTable $table, array &$records, ReflectedDatabase $tables, array $params,
71
+    public function addJoins(ReflectedTable $table, array &$records, ReflectedDatabase $tables, array $params,
72 72
         GenericDB $db)/*: void*/{
73 73
 
74
-        $includes = $this->getIncludesAsPathTree($tables, $params);
75
-        $this->addIncludesForTables($table, $includes, $records, $tables, $params, $db);
74
+        $joins = $this->getJoinsAsPathTree($tables, $params);
75
+        $this->addJoinsForTables($table, $joins, $records, $tables, $params, $db);
76 76
     }
77 77
 
78 78
     private function hasAndBelongsToMany(ReflectedTable $t1, ReflectedTable $t2, ReflectedDatabase $tables) /*: ?ReflectedTable*/
@@ -86,10 +86,10 @@ class RelationIncluder
86 86
         return null;
87 87
     }
88 88
 
89
-    private function addIncludesForTables(ReflectedTable $t1, PathTree $includes, array &$records,
89
+    private function addJoinsForTables(ReflectedTable $t1, PathTree $joins, array &$records,
90 90
         ReflectedDatabase $tables, array $params, GenericDB $db) {
91 91
 
92
-        foreach ($includes->getKeys() as $t2Name) {
92
+        foreach ($joins->getKeys() as $t2Name) {
93 93
 
94 94
             $t2 = $tables->get($t2Name);
95 95
 
@@ -116,7 +116,7 @@ class RelationIncluder
116 116
                 $this->addFkRecords($t2, $habtmValues->fkValues, $params, $db, $newRecords);
117 117
             }
118 118
 
119
-            $this->addIncludesForTables($t2, $includes->get($t2Name), $newRecords, $tables, $params, $db);
119
+            $this->addJoinsForTables($t2, $joins->get($t2Name), $newRecords, $tables, $params, $db);
120 120
 
121 121
             if ($fkValues != null) {
122 122
                 $this->fillFkValues($t2, $newRecords, $fkValues);

+ 1
- 1
tests/functional/001_records/027_list_example_from_readme_users_only.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=users&filter=id,eq,1
1
+GET /records/posts?join=users&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/028_read_example_from_readme_users_only.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts/1?include=users
1
+GET /records/posts/1?join=users
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/029_list_example_from_readme_comments_only.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=comments&filter=id,eq,1
1
+GET /records/posts?join=comments&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/030_list_example_from_readme_tags_only.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=tags&filter=id,eq,1
1
+GET /records/posts?join=tags&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

tests/functional/001_records/031_list_example_from_readme_tags_with_include_path.log → tests/functional/001_records/031_list_example_from_readme_tags_with_join_path.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=categories&include=post_tags,tags&include=comments&filter=id,eq,1
1
+GET /records/posts?join=categories&join=post_tags,tags&join=comments&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/032_list_example_from_readme.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=categories&include=tags&include=comments&filter=id,eq,1
1
+GET /records/posts?join=categories&join=tags&join=comments&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/033_list_example_from_readme_tag_name_only.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?columns=tags.name&include=categories&include=post_tags,tags&include=comments&filter=id,eq,1
1
+GET /records/posts?columns=tags.name&join=categories&join=post_tags,tags&join=comments&filter=id,eq,1
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

+ 1
- 1
tests/functional/001_records/034_list_example_from_readme_with_transform_with_exclude.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts?include=categories&include=post_tags,tags&include=comments&exclude=comments.message&filter=id,eq,1
1
+GET /records/posts?join=categories&join=post_tags,tags&join=comments&exclude=comments.message&filter=id,eq,1
2 2
 
3 3
 ===
4 4
 200

+ 1
- 1
tests/functional/001_records/061_get_post_content_with_included_tag_names.log View File

@@ -1,4 +1,4 @@
1
-GET /records/posts/1?columns=content,tags.name&include=tags
1
+GET /records/posts/1?columns=content,tags.name&join=tags
2 2
 ===
3 3
 200
4 4
 Content-Type: application/json

Loading…
Cancel
Save