diff --git a/code/GraphQL/FolderTypeCreator.php b/code/GraphQL/FolderTypeCreator.php index 5cd6f543d..74c2fa61e 100644 --- a/code/GraphQL/FolderTypeCreator.php +++ b/code/GraphQL/FolderTypeCreator.php @@ -164,8 +164,52 @@ public function resolveChildrenConnection( $result = $childrenConnection->resolveList($list, $args); $list = $result['edges']; - // Filter by permission - $ids = $list->column('ID'); + if (!isset($args['sortBy'])) { + // only show folders first if no manual ordering is set + + $list = $list->alterDataQuery(static function (DataQuery $dataQuery) { + $query = $dataQuery->query(); + $existingOrderBys = []; + foreach ($query->getOrderBy() as $field => $direction) { + if (strpos($field, '.') === false) { + // some fields may be surrogates added by extending augmentSQL (e.g. fluent) + // we have to preserve those expressions rather than auto-generated names + // that SQLSelect::addOrderBy leaves for them (usually that's alike _SortColumn0) + // + // see related issues for more details: + // - https://github.com/silverstripe/silverstripe-asset-admin/issues/820 + // - https://github.com/silverstripe/silverstripe-asset-admin/issues/893 + $field = $query->expressionForField(trim($field, '"')) ?: $field; + } + + $existingOrderBys[$field] = $direction; + } + + // Folders should always go first due to backwards compatibility + // See https://github.com/silverstripe/silverstripe-asset-admin/issues/893 + $dataQuery->sort( + sprintf( + '(CASE WHEN "ClassName"=%s THEN 1 ELSE 0 END)', + DB::get_conn()->quoteString('SilverStripe\Assets\Folder') + ), + 'DESC', + true + ); + + foreach ($existingOrderBys as $field => $dir) { + $dataQuery->sort($field, $dir, false); + } + + return $dataQuery; + }); + } + + + // DataQuery::column ignores surrogate sorting fields + // see https://github.com/silverstripe/silverstripe-framework/issues/8926 + // the following line is a workaround for `$ids = $list->column('ID');` + $ids = $list->dataQuery()->execute()->column('ID'); + $permissionChecker = File::singleton()->getPermissionChecker(); $canViewIDs = array_keys(array_filter($permissionChecker->canViewMultiple( $ids, diff --git a/tests/php/GraphQL/FolderTypeCreatorTest.php b/tests/php/GraphQL/FolderTypeCreatorTest.php index 6b65f4b88..cc9657b31 100644 --- a/tests/php/GraphQL/FolderTypeCreatorTest.php +++ b/tests/php/GraphQL/FolderTypeCreatorTest.php @@ -18,6 +18,26 @@ class FolderTypeCreatorTest extends SapphireTest protected $usesDatabase = true; + public function testItSortsChildrenOnTypeByDefault() + { + $rootFolder = Folder::singleton(); + $file = File::create(['Name' => 'aaa file']); + $file->write(); + $folder = Folder::create(['Name' => 'bbb folder']); + $folder->write(); + $list = $this->resolveChildrenConnection( + $rootFolder, + [] + ); + $this->assertEquals( + [ + $folder->Name, + $file->Name, + ], + $list['edges']->column('Name') + ); + } + public function testItDoesNotFilterByParentIdWithRecursiveFlag() { $rootFolder = Folder::singleton();