4242class FolderController extends OCSController {
4343 private readonly ?IUser $ user ;
4444
45- protected const ALLOWED_ORDER_BY = [
46- 'mount_point ' ,
47- 'quota ' ,
48- 'groups ' ,
49- 'acl ' ,
50- ];
51-
5245 public function __construct (
5346 string $ AppName ,
5447 IRequest $ request ,
@@ -110,7 +103,8 @@ private function formatFolder(FolderWithMappingsAndCache $folder): array {
110103 * @param bool $applicable Filter by applicable groups
111104 * @param non-negative-int $offset Number of items to skip.
112105 * @param ?positive-int $limit Number of items to return.
113- * @param null|'mount_point'|'quota'|'groups'|'acl' $orderBy The key to order by
106+ * @param 'mount_point'|'quota'|'groups'|'acl' $orderBy The key to order by
107+ * @param 'asc'|'desc' $order Sort ascending or descending
114108 * @return DataResponse<Http::STATUS_OK, array<string, GroupFoldersFolder>, array{}>
115109 * @throws OCSNotFoundException Storage not found
116110 * @throws OCSBadRequestException Wrong limit used
@@ -119,58 +113,39 @@ private function formatFolder(FolderWithMappingsAndCache $folder): array {
119113 */
120114 #[NoAdminRequired]
121115 #[FrontpageRoute(verb: 'GET ' , url: '/folders ' )]
122- public function getFolders (bool $ applicable = false , int $ offset = 0 , ?int $ limit = null , ?string $ orderBy = 'mount_point ' ): DataResponse {
116+ public function getFolders (bool $ applicable = false , int $ offset = 0 , ?int $ limit = null , string $ orderBy = 'mount_point ' , string $ order = 'asc ' ): DataResponse {
117+ /** @psalm-suppress DocblockTypeContradiction */
123118 if ($ limit !== null && $ limit <= 0 ) {
124119 throw new OCSBadRequestException ('The limit must be greater than 0. ' );
125120 }
126121
122+ /** @psalm-suppress DocblockTypeContradiction */
123+ if (!in_array ($ orderBy , ['mount_point ' , 'quota ' , 'groups ' , 'acl ' ], true )) {
124+ throw new OCSBadRequestException ('The orderBy is not allowed. ' );
125+ }
126+
127+ /** @psalm-suppress DocblockTypeContradiction */
128+ if (!in_array ($ order , ['asc ' , 'desc ' ], true )) {
129+ throw new OCSBadRequestException ('The order is not allowed. ' );
130+ }
131+
127132 $ storageId = $ this ->getRootFolderStorageId ();
128133 if ($ storageId === null ) {
129134 throw new OCSNotFoundException ();
130135 }
131136
132137 $ folders = [];
133- foreach ($ this ->manager ->getAllFoldersWithSize () as $ id => $ folder ) {
138+ $ i = 0 ;
139+ foreach ($ this ->manager ->getAllFoldersWithSize ($ offset , $ limit , $ orderBy , $ order ) as $ id => $ folder ) {
134140 // Make them string-indexed for OpenAPI JSON output
135- $ folders [(string )$ id ] = $ this ->formatFolder ($ folder );
141+ // JavaScript doesn't preserve JSON object key orders, so we need to manually add this information.
142+ $ folders [(string )$ id ] = array_merge ($ this ->formatFolder ($ folder ), [
143+ 'sortIndex ' => $ offset + $ i ++,
144+ ]);
136145 }
137146
138- $ orderBy = in_array ($ orderBy , self ::ALLOWED_ORDER_BY , true )
139- ? $ orderBy
140- : 'mount_point ' ;
141-
142- // in case of equal orderBy value always fall back to the mount_point - same as on the frontend
143- /**
144- * @var GroupFoldersFolder $a
145- * @var GroupFoldersFolder $b
146- */
147- uasort ($ folders , function (array $ a , array $ b ) use ($ orderBy ) {
148- if ($ orderBy === 'groups ' ) {
149- if (($ value = count ($ a ['groups ' ]) - count ($ b ['groups ' ])) !== 0 ) {
150- return $ value ;
151- }
152- } else {
153- if (($ value = $ this ->compareFolderNames ((string )($ a [$ orderBy ] ?? '' ), (string )($ b [$ orderBy ] ?? '' ))) !== 0 ) {
154- return $ value ;
155- }
156- }
157-
158- // fallback to mount_point
159- if (($ value = $ this ->compareFolderNames ($ a ['mount_point ' ] ?? '' , $ b ['mount_point ' ])) !== 0 ) {
160- return $ value ;
161- }
162-
163- // fallback to id
164- return $ a ['id ' ] - $ b ['id ' ];
165- });
166-
167147 $ isAdmin = $ this ->delegationService ->isAdminNextcloud () || $ this ->delegationService ->isDelegatedAdmin ();
168148 if ($ isAdmin && !$ applicable ) {
169- // If only the default values are provided the pagination can be skipped.
170- if ($ offset !== 0 || $ limit !== null ) {
171- $ folders = array_slice ($ folders , $ offset , $ limit , true );
172- }
173-
174149 return new DataResponse ($ folders );
175150 }
176151
@@ -182,11 +157,6 @@ public function getFolders(bool $applicable = false, int $offset = 0, ?int $limi
182157 $ folders = array_filter (array_map ($ this ->filterNonAdminFolder (...), $ folders ));
183158 }
184159
185- // If only the default values are provided the pagination can be skipped.
186- if ($ offset !== 0 || $ limit !== null ) {
187- $ folders = array_slice ($ folders , $ offset , $ limit , true );
188- }
189-
190160 return new DataResponse ($ folders );
191161 }
192162
0 commit comments