|
@@ -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);
|