Implement a full children endpoint

This commit is contained in:
Marcel Klehr 2020-04-07 02:03:33 +02:00
parent ce9cda6791
commit 1ad192cfd3
3 changed files with 84 additions and 0 deletions

View File

@ -51,6 +51,7 @@ return [
['name' => 'internal_folders#edit_folder', 'url' => '/folder/{folderId}', 'verb' => 'PUT'],
['name' => 'internal_folders#delete_folder', 'url' => '/folder/{folderId}', 'verb' => 'DELETE'],
['name' => 'internal_folders#hash_folder', 'url' => '/folder/{folderId}/hash', 'verb' => 'GET'],
['name' => 'internal_folders#get_folder_children', 'url' => '/folder/{folderId}/children', 'verb' => 'GET'],
['name' => 'internal_folders#get_folder_children_order', 'url' => '/folder/{folderId}/childorder', 'verb' => 'GET'],
['name' => 'internal_folders#set_folder_children_order', 'url' => '/folder/{folderId}/childorder', 'verb' => 'PATCH'],
['name' => 'internal_folders#add_to_folder', 'url' => '/folder/{folderId}/bookmarks/{bookmarkId}', 'verb' => 'POST'],
@ -85,6 +86,7 @@ return [
['name' => 'folders#delete_folder', 'url' => '/public/rest/v2/folder/{folderId}', 'verb' => 'DELETE'],
['name' => 'folders#hash_folder', 'url' => '/public/rest/v2/folder/{folderId}/hash', 'verb' => 'GET'],
['name' => 'bookmark#import_bookmark', 'url' => '/public/rest/v2/folder/{folder}/import', 'verb' => 'POST'],
['name' => 'folders#get_folder_children', 'url' => '/public/rest/v2/folder/{folderId}/children', 'verb' => 'GET'],
['name' => 'folders#get_folder_children_order', 'url' => '/public/rest/v2/folder/{folderId}/childorder', 'verb' => 'GET'],
['name' => 'folders#set_folder_children_order', 'url' => '/public/rest/v2/folder/{folderId}/childorder', 'verb' => 'PATCH'],
['name' => 'folders#add_to_folder', 'url' => '/public/rest/v2/folder/{folderId}/bookmarks/{bookmarkId}', 'verb' => 'POST'],

View File

@ -359,6 +359,24 @@ class FoldersController extends ApiController {
}
}
/**
* @param int $folderId
* @param int $layers
* @return JSONResponse
*
* @NoAdminRequired
* @NoCSRFRequired
* @CORS
* @PublicPage
*/
public function getFolderChildren($folderId, $layers = 0): JSONResponse {
if (!Authorizer::hasPermission(Authorizer::PERM_READ, $this->authorizer->getPermissionsForFolder($folderId, $this->request))) {
return new JSONResponse(['status' => 'error', 'data' => 'Insufficient permissions'], Http::STATUS_BAD_REQUEST);
}
$folderId = $this->toInternalFolderId($folderId);
$children = $this->treeMapper->getChildren($folderId, $layers);
return new JSONResponse(['status' => 'success', 'data' => $children]);
}
/**
* @param int $folderId

View File

@ -586,4 +586,68 @@ class TreeMapper extends QBMapper {
->where($qb->expr()->eq('parent_folder', $qb->createPositionalParameter($folderId)));
return $qb->execute()->fetch(\PDO::FETCH_COLUMN);
}
public function getChildren(int $folderId, int $layers = 0) {
$qb = $this->db->getQueryBuilder();
$qb
->select(array_merge(['index', 't.type'], array_map(static function ($col) {
return 'b.' . $col;
}, Bookmark::$columns)))
->from('bookmarks', 'b')
->innerJoin('b', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'b.id'))
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_BOOKMARK)))
->orderBy('t.index', 'ASC');
$childBookmarks = $qb->execute()->fetchAll();
$qb = $this->db->getQueryBuilder();
$qb
->select('f.id', 'title', 'user_id', 'index', 't.type')
->from('bookmarks_folders', 'f')
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'f.id'))
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_FOLDER)))
->orderBy('t.index', 'ASC');
$childFolders = $qb->execute()->fetchAll();
$qb = $this->db->getQueryBuilder();
$qb
->select('folder_id', 'f.title', 'user_id', 'index', 't.type')
->from('bookmarks_shares', 's')
->innerJoin('s', 'bookmarks_shared_folders', 'f', $qb->expr()->eq('f.share_id', 's.id'))
->innerJoin('f', 'bookmarks_tree', 't', $qb->expr()->eq('t.id', 'f.id'))
->where($qb->expr()->eq('t.parent_folder', $qb->createPositionalParameter($folderId)))
->andWhere($qb->expr()->eq('t.type', $qb->createPositionalParameter(self::TYPE_SHARE)))
->orderBy('t.index', 'ASC');
$childShares = $qb->execute()->fetchAll();
$children = array_merge($childBookmarks, $childFolders, $childShares);
$indices = array_column($children, 'index');
array_multisort($indices, $children);
$bookmark = new Bookmark();
$children = array_map(function ($child) use ($layers, $bookmark) {
$item = ['type' => $child['type'], 'id' => (int)$child['id'], 'title' => $child['title'], 'userId' => $child['user_id']];
if ($item['type'] === self::TYPE_SHARE) {
$item['type'] = self::TYPE_FOLDER;
$item['id'] = (int)$child['folder_id'];
}
if ($item['type'] === self::TYPE_BOOKMARK) {
foreach (Bookmark::$columns as $col) {
$item[$bookmark->columnToProperty($col)] = $child[$col];
}
}
if ($item['type'] === self::TYPE_FOLDER && $layers !== 0) {
$item['children'] = $this->getChildren($item['id'], $layers - 1);
}
return $item;
}, $children);
return $children;
}
}