@@ -524,8 +524,8 @@ public function updateRecord($id, array $recordData, array $params = [])
524
524
525
525
$ statusField = $ tableSchema ->getStatusField ();
526
526
$ logEntryAction = ArrayUtils::get ($ params , 'revert ' ) === true
527
- ? DirectusActivityTableGateway::ACTION_REVERT
528
- : DirectusActivityTableGateway::ACTION_UPDATE ;
527
+ ? DirectusActivityTableGateway::ACTION_REVERT
528
+ : DirectusActivityTableGateway::ACTION_UPDATE ;
529
529
530
530
if ($ statusField && $ logEntryAction === DirectusActivityTableGateway::ACTION_UPDATE ) {
531
531
try {
@@ -592,6 +592,13 @@ public function addOrUpdateManyToOneRelationships($schema, $parentRow, &$childLo
592
592
$ primaryKey = $ foreignTableSchema ->getPrimaryKeyName ();
593
593
$ ForeignTable = new RelationalTableGateway ($ foreignTableName , $ this ->adapter , $ this ->acl );
594
594
595
+ // If a system table is joined, stop relational update here.
596
+ if (strpos ($ foreignTableName , 'directus_ ' ) === 0 ) {
597
+ // Once they're managed, remove the foreign collections from the record array
598
+ unset($ parentRow [$ fieldName ]);
599
+ continue ;
600
+ }
601
+
595
602
if ($ primaryKey && ArrayUtils::get ($ foreignRow , $ this ->deleteFlag ) === true ) {
596
603
$ Where = new Where ();
597
604
$ Where ->equalTo ($ primaryKey , $ foreignRow [$ primaryKey ]);
@@ -941,7 +948,7 @@ public function createGlobalMetadata($single, array $list = [])
941
948
*/
942
949
public function createEntriesMetadata (array $ entries , array $ list = [])
943
950
{
944
- $ allKeys = ['result_count ' , 'total_count ' , 'status ' ];
951
+ $ allKeys = ['result_count ' , 'total_count ' , 'filter_count ' , ' status ' , ' page ' ];
945
952
$ tableSchema = $ this ->getTableSchema ($ this ->table );
946
953
947
954
$ metadata = [];
@@ -969,6 +976,78 @@ public function createEntriesMetadata(array $entries, array $list = [])
969
976
$ metadata ['status_count ' ] = $ statusCount ;
970
977
}
971
978
979
+ if (in_array ('filter_count ' , $ list ) || in_array ('page ' , $ list )) {
980
+ $ metadata = $ this ->createMetadataPagination ($ metadata , $ _GET );
981
+ }
982
+
983
+ return $ metadata ;
984
+ }
985
+
986
+ /**
987
+ * Updates Metadata Object with Pagination
988
+ *
989
+ * @param $metadata - Existing metadata object
990
+ * @param $params - GET Parameters
991
+ *
992
+ * @return array
993
+ */
994
+ public function createMetadataPagination (array $ metadata = [], array $ params = [])
995
+ {
996
+ if (empty ($ params )) $ params = $ _GET ;
997
+
998
+ $ filtered = ArrayUtils::get ($ params , 'filter ' ) || ArrayUtils::get ($ params , 'q ' );
999
+
1000
+ $ limit = intval ( ArrayUtils::get ($ params , 'limit ' , 0 ) );
1001
+ $ page = intval ( ArrayUtils::get ($ params , 'page ' , 1 ) );
1002
+ $ offset = intval ( ArrayUtils::get ($ params , 'offset ' , -1 ) );
1003
+
1004
+ $ total = intval (ArrayUtils::get ($ metadata , 'Published ' ) ?: ArrayUtils::get ($ metadata , 'total_count ' ));
1005
+ $ rows = intval (ArrayUtils::get ($ metadata , 'result_count ' ));
1006
+ $ pathname = explode ('? ' , ArrayUtils::get ($ _SERVER , 'REQUEST_URI ' ));
1007
+ $ url = trim (\Directus \get_url (), '/ ' ) . reset ($ pathname );
1008
+
1009
+ if (!$ rows || !$ total ) return $ metadata ;
1010
+
1011
+ if ($ filtered ) {
1012
+ $ filteredparams = array_merge ($ params , [
1013
+ "depth " => 0 ,
1014
+ "fields " => $ this ->primaryKeyFieldName ,
1015
+ "limit " => -1
1016
+ ]);
1017
+
1018
+ $ entries = $ this ->fetchItems ($ filteredparams );
1019
+ $ total = count ($ entries );
1020
+ $ metadata ['filter_count ' ] = $ total ;
1021
+ }
1022
+
1023
+ $ limit = $ limit < 1 ? $ rows : $ limit ;
1024
+ $ pages = $ total ? ceil ($ total / $ limit ) : 1 ;
1025
+ $ page = $ page > $ pages ? $ pages : ( $ page && $ offset >= 0 ? ( floor ($ offset / $ limit ) + 1 ) : $ page );
1026
+ $ offset = $ offset >= 0 ? $ offset : ($ page ? (($ page - 1 ) * $ limit ) : 0 );
1027
+ $ next = $ previous = $ last = $ first = -1 ;
1028
+
1029
+ if ($ pages > 1 ) {
1030
+ $ next = ($ pages > $ page ) ? ($ offset + $ limit ) : null ;
1031
+ $ previous = ($ offset >= $ limit ) ? ($ offset - $ limit ) : ($ limit * ( $ pages - 1 ));
1032
+ $ first = ($ pages < 2 || $ limit < 1 ) ? null : 0 ;
1033
+ $ last = ($ pages < 2 ) ? null : ( ($ pages - 1 ) * $ limit );
1034
+ }
1035
+
1036
+ $ metadata = array_merge ($ metadata , [
1037
+ "limit " => $ limit ,
1038
+ "offset " => $ offset ,
1039
+ "page " => $ page ,
1040
+ "page_count " => $ pages ,
1041
+ "links " => [
1042
+ "self " => $ url ,
1043
+ "current " => "{$ url }? " . urldecode ( http_build_query (array_merge ($ params , ["page " => $ page ]))),
1044
+ "next " => $ next > 0 && $ page < $ pages ? ( "{$ url }? " . urldecode ( http_build_query (array_merge ($ params , ["offset " => $ next , "page " => $ page + 1 ])) ) ) : null ,
1045
+ "previous " => $ previous >= 0 && $ page > 1 ? ( "{$ url }? " . urldecode ( http_build_query (array_merge ($ params , ["offset " => $ previous , "page " => $ page - 1 ])) ) ) : null ,
1046
+ "first " => $ first >= 0 ? ( "{$ url }? " . urldecode ( http_build_query (array_merge ($ params , ["offset " => $ first , "page " => 1 ])) ) ) : null ,
1047
+ "last " => $ last > 0 ? ( "{$ url }? " . urldecode ( http_build_query (array_merge ($ params , ["offset " => $ last , "page " => $ pages ])) ) ) : null
1048
+ ]
1049
+ ]);
1050
+
972
1051
return $ metadata ;
973
1052
}
974
1053
@@ -1020,7 +1099,11 @@ public function fetchItems(array $params = [], \Closure $queryCallback = null)
1020
1099
$ builder ->orderBy ($ this ->primaryKeyFieldName );
1021
1100
1022
1101
try {
1023
- $ this ->enforceReadPermission ($ builder );
1102
+ $ this ->enforceReadPermission ($ builder );
1103
+
1104
+ //If collection is directus_fields, also check permission of actual collection of which fields are retrieving
1105
+ if ($ this ->getTable () == SchemaManager::COLLECTION_FIELDS && ArrayUtils::has ($ params ['filter ' ], 'collection ' ))
1106
+ $ this ->acl ->enforceReadOnce (ArrayUtils::get ($ params ['filter ' ], 'collection ' ));
1024
1107
} catch (PermissionException $ e ) {
1025
1108
$ isForbiddenRead = $ e instanceof ForbiddenCollectionReadException;
1026
1109
$ isUnableFindItems = $ e instanceof UnableFindOwnerItemsException;
@@ -1220,7 +1303,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
1220
1303
$ relational = SchemaService::hasRelationship ($ nextTable , $ nextColumn );
1221
1304
$ columnsTable [] = $ nextTable ;
1222
1305
}
1223
-
1306
+
1224
1307
// if one of the column in the list has not relationship
1225
1308
// it will break the loop before going over all the columns
1226
1309
// which we will call this as column not found
@@ -1231,7 +1314,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
1231
1314
1232
1315
// Remove the original filter column with dot-notation
1233
1316
unset($ filters [$ column ]);
1234
-
1317
+
1235
1318
//Prepare relational data for all the fields
1236
1319
$ columnRelationalData = [];
1237
1320
foreach ($ filterColumns as $ filterColumn ){
@@ -1247,7 +1330,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
1247
1330
];
1248
1331
}
1249
1332
}
1250
-
1333
+
1251
1334
// Reverse all the columns from comments.author.id to id.author.comments
1252
1335
// To filter from the most deep relationship to their parents
1253
1336
$ columns = explode ('. ' , \Directus \column_identifier_reverse ($ column ));
@@ -1264,19 +1347,19 @@ protected function parseDotFilters(Builder $mainQuery, array $filters)
1264
1347
$ query = new Builder ($ this ->getAdapter ());
1265
1348
$ mainTableObject = $ this ->getTableSchema ($ table );
1266
1349
$ selectColumn = $ mainTableObject ->getPrimaryField ()->getName ();
1267
-
1350
+
1268
1351
//check if column type is alias and relationship is O2M
1269
1352
$ previousRelation = isset ($ filterColumns [array_search ($ column , $ filterColumns )-1 ])?$ filterColumns [array_search ($ column , $ filterColumns )-1 ]:'' ;
1270
- if ($ previousRelation && $ columnRelationalData [$ previousRelation ]['type ' ] == \Directus \Database \Schema \Object \FieldRelationship::ONE_TO_MANY ) {
1353
+ if ($ previousRelation && $ columnRelationalData [$ previousRelation ]['type ' ] == \Directus \Database \Schema \Object \FieldRelationship::ONE_TO_MANY ) {
1271
1354
$ selectColumn = $ columnRelationalData [$ previousRelation ]['field_many ' ];
1272
1355
}
1273
-
1356
+
1274
1357
//get last relationship
1275
1358
if ($ mainColumn && !empty ($ mainColumn ) && $ columnRelationalData [$ mainColumn ]['type ' ] == \Directus \Database \Schema \Object \FieldRelationship::ONE_TO_MANY ) {
1276
1359
$ mainColumn = $ mainTableObject ->getPrimaryField ()->getName ();
1277
1360
}
1278
1361
$ query ->columns ([$ selectColumn ]);
1279
-
1362
+
1280
1363
$ query ->from ($ table );
1281
1364
1282
1365
$ this ->doFilter ($ query , $ column , $ condition , $ table );
@@ -1446,8 +1529,8 @@ protected function doFilter(Builder $query, $column, $condition, $table)
1446
1529
$ relatedTable = $ relationship ->getCollectionMany ();
1447
1530
$ relatedRightColumn = $ relationship ->getFieldMany ();
1448
1531
$ tableSchema = SchemaService::getCollection ($ relatedTable );
1449
- $ relatedTableColumns = $ tableSchema ->getFields ();
1450
-
1532
+ $ relatedTableColumns = $ tableSchema ->getFields ();
1533
+
1451
1534
$ query ->orWhereRelational ($ this ->primaryKeyFieldName , $ relatedTable , null , $ relatedRightColumn , function (Builder $ query ) use ($ column , $ relatedTable , $ relatedTableColumns , $ value ) {
1452
1535
foreach ($ relatedTableColumns as $ column ) {
1453
1536
$ isNumeric = $ this ->getSchemaManager ()->isNumericType ($ column ->getType ());
@@ -1512,12 +1595,12 @@ protected function processFilter(Builder $query, array $filters = [])
1512
1595
if (isset ($ fieldReadBlackListDetails ['isReadBlackList ' ]) && $ fieldReadBlackListDetails ['isReadBlackList ' ]) {
1513
1596
throw new Exception \ForbiddenFieldAccessException ($ column );
1514
1597
}else if (isset ($ fieldReadBlackListDetails ['statuses ' ]) && !empty ($ fieldReadBlackListDetails ['statuses ' ])){
1515
- $ blackListStatuses = array_merge ($ blackListStatuses ,array_values ($ fieldReadBlackListDetails ['statuses ' ]));
1598
+ $ blackListStatuses = array_merge ($ blackListStatuses ,array_values ($ fieldReadBlackListDetails ['statuses ' ]));
1516
1599
}
1517
1600
}
1518
- $ filters = $ this ->parseDotFilters ($ query , $ filters );
1519
-
1520
- foreach ($ filters as $ column => $ conditions ) {
1601
+ $ filters = $ this ->parseDotFilters ($ query , $ filters );
1602
+
1603
+ foreach ($ filters as $ column => $ conditions ) {
1521
1604
if ($ conditions instanceof Filter) {
1522
1605
$ column = $ conditions ->getIdentifier ();
1523
1606
$ conditions = $ conditions ->getValue ();
0 commit comments