Newer
Older
<?php
/**
* Copyright Maarch since 2008 under licence GPLv3.
* See LICENCE.txt file at the root folder for more details.
* This file is part of Maarch software.
*/
/**
* @brief Folder Controller
*
* @author dev@maarch.org
*/
namespace Folder\controllers;
use Attachment\models\AttachmentModel;
use Folder\models\EntityFolderModel;
use Folder\models\ResourceFolderModel;
use Folder\models\UserPinnedFolderModel;
use Group\controllers\PrivilegeController;
use History\controllers\HistoryController;
use Resource\controllers\ResController;
use Resource\controllers\ResourceListController;
use Resource\models\ResourceListModel;
use Resource\models\UserFollowedResourceModel;
use Respect\Validation\Validator;
use Slim\Http\Request;
use Slim\Http\Response;
use SrcCore\controllers\PreparedClauseController;
use SrcCore\models\DatabaseModel;
use SrcCore\models\ValidatorModel;
use User\models\UserEntityModel;
class FolderController
{
public function get(Request $request, Response $response)
{
$folders = FolderController::getScopeFolders(['login' => $GLOBALS['login']]);
$userEntities = EntityModel::getWithUserEntities(['select' => ['entities.id'], 'where' => ['user_id = ?'], 'data' => [$GLOBALS['id']]]);
$userEntities = array_column($userEntities, 'id');
if (empty($userEntities)) {
$userEntities = 0;
}
$foldersWithResources = FolderModel::getWithEntitiesAndResources([
'select' => ['COUNT(DISTINCT resources_folders.res_id)', 'resources_folders.folder_id'],
'where' => ['(entities_folders.entity_id in (?) OR folders.user_id = ? OR keyword = ?)'],
'data' => [$userEntities, $GLOBALS['id'], 'ALL_ENTITIES'],
'groupBy' => ['resources_folders.folder_id']
]);
$tree = [];
foreach ($folders as $folder) {
$key = array_keys(array_column($foldersWithResources, 'folder_id'), $folder['id']);
$count = 0;
if (isset($key[0])) {
$count = $foldersWithResources[$key[0]]['count'];
}
Guillaume Heurtier
committed
$isPinned = !empty(
UserPinnedFolderModel::get([
'where' => ['folder_id = ?', 'user_id = ?'],
'data' => [$folder['id'], $GLOBALS['id']]
])
);
$folderScope = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $folder['id'], 'edition' => true]);
'name' => $folder['label'],
'id' => $folder['id'],
'label' => $folder['label'],
'public' => $folder['public'],
'user_id' => $folder['user_id'],
'parent_id' => $folder['parent_id'],
'level' => $folder['level'],
Guillaume Heurtier
committed
'countResources' => $count,
'pinned' => $isPinned,
'canEdit' => !empty($folderScope)
array_splice($tree, 0, 0, [$insert]);
foreach ($tree as $key => $branch) {
if ($branch['id'] == $folder['parent_id']) {
array_splice($tree, $key + 1, 0, [$insert]);
$insert['level'] = 0;
$insert['parent_id'] = null;
return $response->withJson(['folders' => $tree]);
public function getById(Request $request, Response $response, array $args)
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $args['id']]);
if (empty($folder[0])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder not found or out of your perimeter']);
$ownerInfo = UserModel::getById(['select' => ['firstname', 'lastname'], 'id' => $folder['user_id']]);
$folder['ownerDisplayName'] = $ownerInfo['firstname'] . ' ' . $ownerInfo['lastname'];
$userEntities = EntityModel::getWithUserEntities([
'select' => ['id'],
'where' => ['user_id = ?'],
]);
$userEntities = array_column($userEntities, 'id');
$folder['sharing']['entities'] = [];
if ($folder['public']) {
$entitiesFolder = EntityFolderModel::getEntitiesByFolderId(['folder_id' => $args['id'], 'select' => ['entities_folders.entity_id', 'entities_folders.edition', 'entities.entity_label']]);
$canDeleteWithChildren = FolderController::areChildrenInPerimeter(['folderId' => $args['id'], 'entities' => $userEntities]);
foreach ($entitiesFolder as $value) {
$canDelete = $canDeleteWithChildren && $value['edition'] == true;
$folder['sharing']['entities'][] = ['entity_id' => $value['entity_id'], 'edition' => $value['edition'], 'canDelete' => $canDelete, 'label' => $value['entity_label']];
$keywordsFolder = EntityFolderModel::getKeywordsByFolderId(['folder_id' => $args['id'], 'select' => ['edition', 'keyword']]);
foreach ($keywordsFolder as $value) {
$canDelete = $canDeleteWithChildren && $value['edition'] == true;
Guillaume Heurtier
committed
$folder['sharing']['entities'][] = ['keyword' => $value['keyword'], 'edition' => $value['edition'], 'canDelete' => $canDelete];
Guillaume Heurtier
committed
$folder['pinned'] = !empty(
UserPinnedFolderModel::get([
'where' => ['folder_id = ?', 'user_id = ?'],
'data' => [$folder['id'], $GLOBALS['id']]
])
);
return $response->withJson(['folder' => $folder]);
}
public function create(Request $request, Response $response)
{
$data = $request->getParsedBody();
if (!Validator::stringType()->notEmpty()->validate($data['label'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body label is empty or not a string']);
}
if (!empty($data['parent_id']) && !Validator::intval()->validate($data['parent_id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body parent_id is not an integer']);
$owner = $GLOBALS['id'];
$public = false;
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $data['parent_id'], 'edition' => true]);
if (empty($folder[0])) {
return $response->withStatus(400)->withJson(['errors' => 'Parent Folder not found or out of your perimeter']);
}
$owner = $folder[0]['user_id'];
$public = $folder[0]['public'];
$level = $folder[0]['level'] + 1;
'label' => $data['label'],
'public' => $public,
'user_id' => $owner,
'parent_id' => $data['parent_id'],
'level' => $level
if (!empty($data['parent_id'])) {
$parentSharing = EntityFolderModel::get([
'select' => ['entity_id', 'edition', 'keyword'],
'where' => ['folder_id = ?'],
'data' => [$data['parent_id']]
]);
foreach ($parentSharing as $sharing) {
EntityFolderModel::create([
'folder_id' => $id,
'entity_id' => $sharing['entity_id'],
'edition' => $sharing['edition'],
'keyword' => $sharing['keyword']
]);
}
}
Guillaume Heurtier
committed
UserPinnedFolderModel::create([
'folder_id' => $id,
'user_id' => $GLOBALS['id']
]);
if ($public && !empty($data['parent_id'])) {
$entitiesSharing = EntityFolderModel::getEntitiesByFolderId(['folder_id' => $data['parent_id'], 'select' => ['entities.id', 'entities_folders.edition']]);
foreach ($entitiesSharing as $entity) {
EntityFolderModel::create([
'folder_id' => $id,
'entity_id' => $entity['id'],
'edition' => $entity['edition'],
]);
}
}
HistoryController::add([
'tableName' => 'folders',
'recordId' => $id,
'eventType' => 'ADD',
'info' => _FOLDER_CREATION . " : {$data['label']}",
'moduleId' => 'folder',
'eventId' => 'folderCreation',
]);
return $response->withJson(['folder' => $id]);
}
Guillaume Heurtier
committed
public function update(Request $request, Response $response, array $args)
{
$data = $request->getParams();
Guillaume Heurtier
committed
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Query id is empty or not an integer']);
}
if (!Validator::stringType()->notEmpty()->validate($data['label'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body label is empty or not a string']);
}
if (!empty($data['parent_id']) && !Validator::intval()->validate($data['parent_id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body parent_id is not an integer']);
}
Guillaume Heurtier
committed
if ($data['parent_id'] == $args['id']) {
return $response->withStatus(400)->withJson(['errors' => 'Parent_id and id can not be the same']);
Guillaume Heurtier
committed
if (!empty($data['parent_id']) && FolderController::isParentFolder(['parent_id' => $data['parent_id'], 'id' => $args['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'parent_id does not exist or Id is a parent of parent_id']);
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $args['id'], 'edition' => true]);
if (empty($folder[0])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder not found or out of your perimeter']);
}
Guillaume Heurtier
committed
$folderOwner = $folder[0]['user_id'];
$folderParent = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $data['parent_id'], 'edition' => true]);
Guillaume Heurtier
committed
if (empty($folderParent[0])) {
return $response->withStatus(400)->withJson(['errors' => 'Parent Folder not found or out of your perimeter']);
}
Guillaume Heurtier
committed
$level = $folderParent[0]['level'] + 1;
$folderOwner = $folderParent[0]['user_id'];
Guillaume Heurtier
committed
if ($folder[0]['parent_id'] != $data['parent_id']) {
$userEntities = EntityModel::getWithUserEntities([
'select' => ['id'],
'where' => ['user_id = ?'],
]);
$userEntities = array_column($userEntities, 'id');
$childrenInPerimeter = FolderController::areChildrenInPerimeter(['folderId' => $args['id'], 'entities' => $userEntities]);
Guillaume Heurtier
committed
if (!$childrenInPerimeter && $folder[0]['user_id'] != $GLOBALS['id']) {
Guillaume Heurtier
committed
return $response->withStatus(400)->withJson(['errors' => 'Cannot move folder because at least one folder is out of your perimeter']);
}
Guillaume Heurtier
committed
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
if (!empty($data['parent_id'])) {
$parentEntities = EntityFolderModel::get([
'select' => ['entity_id', 'edition'],
'where' => ['folder_id = ?', 'entity_id is not null'],
'data' => [$data['parent_id']]
]);
$entities = [];
foreach ($parentEntities as $entity) {
$entities[] = ['entity_id' => $entity['entity_id'], 'edition' => $entity['edition']];
}
$keywordsList = EntityFolderModel::get([
'select' => ['keyword', 'edition'],
'where' => ['folder_id in (?)', 'keyword is not null'],
'data' => [[$data['parent_id'], $args['id']]],
'groupBy' => ['keyword', 'edition'],
'orderBy' => ['edition DESC']
]);
$keywords = [];
foreach ($keywordsList as $keyword) {
$keywords[] = ['keyword' => $keyword['keyword'], 'edition' => $keyword['edition']];
}
DatabaseModel::beginTransaction();
$sharing = FolderController::folderSharing([
'folderId' => $args['id'],
'public' => true,
'remove' => [],
'add' => $entities,
'keywords' => $keywords
]);
if (!$sharing) {
DatabaseModel::rollbackTransaction();
return $response->withStatus(400)->withJson(['errors' => 'Cannot share/unshare folder because at least one folder is out of your perimeter']);
}
DatabaseModel::commitTransaction();
}
FolderModel::update([
'set' => [
'parent_id' => $data['parent_id'],
'level' => $level,
'user_id' => $folderOwner
],
'where' => ['id = ?'],
'data' => [$args['id']]
]);
Guillaume Heurtier
committed
}
FolderController::updateChildren($args['id'], $level, $folderOwner);
FolderModel::update([
'set' => [
'label' => $data['label']
],
'where' => ['id = ?'],
'data' => [$args['id']]
]);
HistoryController::add([
'tableName' => 'folders',
Guillaume Heurtier
committed
'recordId' => $args['id'],
'eventType' => 'UP',
'info' => _FOLDER_MODIFICATION . " : {$data['label']}",
'moduleId' => 'folder',
'eventId' => 'folderModification',
]);
return $response->withStatus(200);
}
Guillaume Heurtier
committed
public function sharing(Request $request, Response $response, array $args)
{
$data = $request->getParams();
Guillaume Heurtier
committed
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Query id is empty or not an integer']);
}
if (!Validator::boolType()->validate($data['public'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body public is empty or not a boolean']);
}
Guillaume Heurtier
committed
if ($data['public'] && !isset($data['sharing']['entities'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body sharing/entities does not exists']);
}
Guillaume Heurtier
committed
$keywords = [];
$entities = [];
foreach ($data['sharing']['entities'] as $item) {
if (isset($item['entity_id'])) {
$entities[] = $item;
Guillaume Heurtier
committed
$keywords[] = $item;
}
}
$entitiesBefore = EntityFolderModel::getEntitiesByFolderId(['select' => ['entities_folders.entity_id, edition'], 'folder_id' => $args['id']]);
Guillaume Heurtier
committed
$entitiesAfter = $entities;
Guillaume Heurtier
committed
$entitiesToRemove = array_udiff($entitiesBefore, $entitiesAfter, function ($a, $b) {
Guillaume Heurtier
committed
if ($a['entity_id'] == $b['entity_id'] && $a['edition'] != $b['edition']) {
return 1;
}
Guillaume Heurtier
committed
if ($a["entity_id"] < $b["entity_id"]) {
return -1;
}
if ($a["entity_id"] > $b["entity_id"]) {
return 1;
}
return 0;
});
$entitiesToAdd = array_udiff($entitiesAfter, $entitiesBefore, function ($a, $b) {
Guillaume Heurtier
committed
if ($a['entity_id'] == $b['entity_id'] && $a['edition'] != $b['edition']) {
return 1;
}
Guillaume Heurtier
committed
if ($a["entity_id"] < $b["entity_id"]) {
return -1;
}
if ($a["entity_id"] > $b["entity_id"]) {
return 1;
}
return 0;
});
DatabaseModel::beginTransaction();
$sharing = FolderController::folderSharing([
'folderId' => $args['id'],
'public' => $data['public'],
'remove' => $entitiesToRemove,
'add' => $entitiesToAdd,
'keywords' => $keywords
]);
if (!$sharing) {
DatabaseModel::rollbackTransaction();
Guillaume Heurtier
committed
return $response->withStatus(400)->withJson(['errors' => 'Cannot share/unshare folder because at least one folder is out of your perimeter']);
}
DatabaseModel::commitTransaction();
Guillaume Heurtier
committed
$folder = FolderModel::getById(['select' => ['label'], 'id' => $args['id']]);
HistoryController::add([
'tableName' => 'folders',
Guillaume Heurtier
committed
'recordId' => $args['id'],
'info' => _FOLDER_SHARING_MODIFICATION . " : {$folder['label']}",
'moduleId' => 'folder',
'eventId' => 'folderModification',
]);
public function folderSharing($args = [])
{
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $args['folderId'], 'edition' => true]);
Guillaume Heurtier
committed
$entitiesToRemove = array_column($args['remove'], 'entity_id');
'set' => [
Guillaume Heurtier
committed
'public' => empty($args['public']) ? 'false' : 'true',
'data' => [$args['folderId']]
$entitiesToAdd = array_column($args['add'], 'entity_id');
if (!empty($entitiesToAdd)) {
$alreadyPresentEntities = EntityFolderModel::get(['select' => ['entity_id'], 'where' => ['folder_id = ?', 'entity_id in (?)'], 'data' => [$args['folderId'], $entitiesToAdd]]);
$alreadyPresentEntities = array_column($alreadyPresentEntities, 'entity_id');
$entitiesToRemove = array_merge($entitiesToRemove, $alreadyPresentEntities);
}
if (!empty($entitiesToRemove)) {
EntityFolderModel::delete(['where' => ['entity_id in (?)', 'folder_id = ?'], 'data' => [$entitiesToRemove, $args['folderId']]]);
Guillaume Heurtier
committed
}
if (!empty($args['add'])) {
foreach ($args['add'] as $entity) {
Guillaume Heurtier
committed
'folder_id' => $args['folderId'],
'entity_id' => $entity['entity_id'],
Guillaume Heurtier
committed
'edition' => $entity['edition']
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
if (!empty($args['keywords'])) {
$folderKeywords = EntityFolderModel::get([
'select' => ['id'],
'where' => ['folder_id = ?', 'entity_id is null', 'keyword is not null'],
'data' => [$args['folderId']]
]);
$folderKeywords = array_column($folderKeywords, 'id');
if (!empty($folderKeywords)) {
EntityFolderModel::delete([
'where' => ['id in (?)'],
'data' => [$folderKeywords]
]);
}
foreach ($args['keywords'] as $keyword) {
EntityFolderModel::create([
'folder_id' => $args['folderId'],
'entity_id' => null,
'edition' => $keyword['edition'],
'keyword' => $keyword['keyword']
]);
}
} else {
EntityFolderModel::delete([
'where' => ['folder_id = ?', 'entity_id is null', 'keyword is not null'],
'data' => [$args['folderId']]
]);
}
$entitiesOfFolder = EntityFolderModel::getEntitiesByFolderId([
'select' => ['entities.entity_id'],
'folder_id' => $args['folderId']
]);
$entitiesOfFolder = array_column($entitiesOfFolder, 'entity_id');
$users = UserPinnedFolderModel::get([
'select' => ['user_id'],
'where' => ['folder_id = ?'],
'data' => [$args['folderId']]
]);
if (!empty($users) && empty($entitiesOfFolder)) {
UserPinnedFolderModel::delete([
'where' => ['folder_id = ?', 'user_id != ?'],
'data' => [$args['folderId'], $folder[0]['user_id']]
]);
} else {
foreach ($users as $user) {
if ($user['user_id'] != $folder[0]['user_id']) {
$inEntities = UserEntityModel::getWithUsers([
'select' => ['users.id'],
'where' => ['users.id = ?', 'entity_id in (?)'],
'data' => [$user['user_id'], $entitiesOfFolder]
]);
if (empty($inEntities)) {
UserPinnedFolderModel::delete([
'where' => ['folder_id = ?', 'user_id = ?'],
'data' => [$args['folderId'], $user['user_id']]
]);
}
}
}
}
Guillaume Heurtier
committed
$folderChild = FolderModel::getChild(['id' => $args['folderId'], 'select' => ['id']]);
if (!empty($folderChild)) {
foreach ($folderChild as $child) {
FolderController::folderSharing([
'folderId' => $child['id'],
'public' => $args['public'],
'remove' => $args['remove'],
'add' => $args['add'],
'keywords' => $args['keywords']
]);
}
public function delete(Request $request, Response $response, array $aArgs)
{
if (!Validator::numeric()->notEmpty()->validate($aArgs['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Query id is empty or not an integer']);
}
$userEntities = EntityModel::getWithUserEntities([
'select' => ['id'],
'where' => ['user_id = ?'],
]);
$userEntities = array_column($userEntities, 'id');
$canDelete = FolderController::areChildrenInPerimeter(['folderId' => $aArgs['id'], 'entities' => $userEntities]);
Guillaume Heurtier
committed
if (!$canDelete) {
return $response->withStatus(400)->withJson(['errors' => 'Cannot delete because at least one folder is out of your perimeter']);
}
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $aArgs['id'], 'edition' => true]);
DatabaseModel::beginTransaction();
$deletion = FolderController::folderDeletion(['folderId' => $aArgs['id']]);
if (!$deletion) {
DatabaseModel::rollbackTransaction();
Guillaume Heurtier
committed
return $response->withStatus(400)->withJson(['errors' => 'Cannot delete because at least one folder is out of your perimeter']);
}
DatabaseModel::commitTransaction();
HistoryController::add([
'tableName' => 'folder',
'recordId' => $aArgs['id'],
'eventType' => 'DEL',
'info' => _FOLDER_SUPPRESSION . " : {$folder[0]['label']}",
'moduleId' => 'folder',
'eventId' => 'folderSuppression',
]);
public static function folderDeletion(array $args = [])
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $args['folderId'], 'edition' => true]);
if (empty($folder[0])) {
return false;
}
FolderModel::delete(['where' => ['id = ?'], 'data' => [$args['folderId']]]);
EntityFolderModel::deleteByFolderId(['folder_id' => $args['folderId']]);
ResourceFolderModel::delete(['where' => ['folder_id = ?'], 'data' => [$args['folderId']]]);
UserPinnedFolderModel::delete([ 'where' => ['folder_id = ?'], 'data' => [$args['folderId']] ]);
$folderChild = FolderModel::getChild(['id' => $args['folderId'], 'select' => ['id']]);
if (!empty($folderChild)) {
foreach ($folderChild as $child) {
$deletion = FolderController::folderDeletion(['folderId' => $child['id']]);
if (!$deletion) {
return false;
}
}
}
return true;
}
Guillaume Heurtier
committed
public static function areChildrenInPerimeter(array $args = [])
ValidatorModel::notEmpty($args, ['folderId', 'entities']);
ValidatorModel::intVal($args, ['folderId']);
ValidatorModel::arrayType($args, ['entities']);
Guillaume Heurtier
committed
$folder = FolderController::getScopeFolders(['login' => $GLOBALS['login'], 'folderId' => $args['folderId'], 'edition' => true]);
Guillaume Heurtier
committed
if (empty($folder[0])) {
return false;
}
$folder = $folder[0];
// All sub-folders of a folders have the same owner user -> if user is owner of folder, all children are in perimeter
if ($folder['user_id'] == $GLOBALS['id']) {
return true;
}
Guillaume Heurtier
committed
Guillaume Heurtier
committed
$children = FolderModel::getWithEntities([
'select' => ['distinct (folders.id)', 'edition', 'user_id', 'keyword', 'entity_id', 'parent_id'],
'where' => ['parent_id = ?', '(entity_id in (?) OR entity_id is null)'],
'data' => [$args['folderId'], $args['entities']]
Guillaume Heurtier
committed
]);
$allEntitiesCanDelete = true;
Guillaume Heurtier
committed
foreach ($children as $key => $child) {
if (!($child['keyword'] == 'ALL_ENTITIES' && $child['edition'] == true)) {
$allEntitiesCanDelete = false;
break;
Guillaume Heurtier
committed
}
}
Guillaume Heurtier
committed
if (!empty($children)) {
foreach ($children as $child) {
if (($child['edition'] == null || $child['edition'] == false) && (!$allEntitiesCanDelete)) {
Guillaume Heurtier
committed
return false;
}
if (!FolderController::areChildrenInPerimeter(['folderId' => $child['id'], 'entities' => $args['entities']])) {
return false;
}
Guillaume Heurtier
committed
}
}
return true;
}
public function getResourcesById(Request $request, Response $response, array $args)
{
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
if (!FolderController::hasFolders(['folders' => [$args['id']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder out of perimeter']);
}
$foldersResources = ResourceFolderModel::get(['select' => ['res_id'], 'where' => ['folder_id = ?'], 'data' => [$args['id']]]);
$foldersResources = array_column($foldersResources, 'res_id');
$formattedResources = [];
$count = 0;
if (!empty($foldersResources)) {
$queryParams = $request->getQueryParams();
$queryParams['offset'] = (empty($queryParams['offset']) || !is_numeric($queryParams['offset']) ? 0 : (int)$queryParams['offset']);
$queryParams['limit'] = (empty($queryParams['limit']) || !is_numeric($queryParams['limit']) ? 10 : (int)$queryParams['limit']);
$allQueryData = ResourceListController::getResourcesListQueryData(['data' => $queryParams]);
if (!empty($allQueryData['order'])) {
$data['order'] = $allQueryData['order'];
}
$rawResources = ResourceListModel::getOnView([
'select' => ['res_id'],
'table' => $allQueryData['table'],
'leftJoin' => $allQueryData['leftJoin'],
'where' => array_merge(['res_id in (?)'], $allQueryData['where']),
'data' => array_merge([$foldersResources], $allQueryData['queryData']),
'orderBy' => empty($data['order']) ? ['creation_date'] : [$data['order']]
]);
$resIds = ResourceListController::getIdsWithOffsetAndLimit(['resources' => $rawResources, 'offset' => $queryParams['offset'], 'limit' => $queryParams['limit']]);
$allResources = array_column($rawResources, 'res_id');
$formattedResources = [];
if (!empty($resIds)) {
$attachments = AttachmentModel::get([
'select' => ['COUNT(res_id)', 'res_id_master'],
'where' => ['res_id_master in (?)', 'status not in (?)', '((status = ? AND typist = ?) OR status != ?)'],
'data' => [$resIds, ['DEL', 'OBS'], 'TMP', $GLOBALS['id'], 'TMP'],
'groupBy' => ['res_id_master']
]);
$select = [
'res_letterbox.res_id', 'res_letterbox.subject', 'res_letterbox.barcode', 'res_letterbox.alt_identifier',
Guillaume Heurtier
committed
'status.label_status AS "status.label_status"', 'status.img_filename AS "status.img_filename"', 'priorities.color AS "priorities.color"',
'res_letterbox.filename as res_filename'
$tableFunction = ['status', 'priorities'];
$leftJoinFunction = ['res_letterbox.status = status.id', 'res_letterbox.priority = priorities.id'];
$order = 'CASE res_letterbox.res_id ';
foreach ($resIds as $key => $resId) {
$order .= "WHEN {$resId} THEN {$key} ";
}
$order .= 'END';
$resources = ResourceListModel::getOnResource([
'select' => $select,
'table' => $tableFunction,
'leftJoin' => $leftJoinFunction,
'where' => ['res_letterbox.res_id in (?)'],
'data' => [$resIds],
'orderBy' => [$order]
]);
$followedResources = UserFollowedResourceModel::get(['select' => ['res_id'], 'where' => ['user_id = ?'], 'data' => [$GLOBALS['id']]]);
$followedResources = array_column($followedResources, 'res_id');
$formattedResources = ResourceListController::getFormattedResources([
'resources' => $resources,
'userId' => $GLOBALS['id'],
'attachments' => $attachments,
'checkLocked' => false,
'trackedMails' => $followedResources,
'listDisplay' => ['folders']
$folderPrivilege = PrivilegeController::hasPrivilege(['privilegeId' => 'include_folders_and_followed_resources_perimeter', 'userId' => $GLOBALS['id']]);
foreach ($formattedResources as $key => $formattedResource) {
if ($folderPrivilege) {
$formattedResources[$key]['allowed'] = true;
} else {
$formattedResources[$key]['allowed'] = ResController::hasRightByResId(['resId' => [$formattedResource['resId']], 'userId' => $GLOBALS['id']]);
}
}
}
$count = count($rawResources);
}
return $response->withJson(['resources' => $formattedResources, 'countResources' => $count, 'allResources' => $allResources]);
}
public function addResourcesById(Request $request, Response $response, array $args)
{
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$body = $request->getParsedBody();
if (!Validator::arrayType()->notEmpty()->validate($body['resources'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body resources is empty or not an array']);
}
if (!FolderController::hasFolders(['folders' => [$args['id']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder out of perimeter']);
}
$foldersResources = ResourceFolderModel::get(['select' => ['res_id'], 'where' => ['folder_id = ?'], 'data' => [$args['id']]]);
$foldersResources = array_column($foldersResources, 'res_id');
$resourcesToClassify = array_diff($body['resources'], $foldersResources);
if (empty($resourcesToClassify)) {
return $response->withJson(['countResources' => count($foldersResources)]);
}
if (!ResController::hasRightByResId(['resId' => $resourcesToClassify, 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Resources out of perimeter']);
}
foreach ($resourcesToClassify as $value) {
ResourceFolderModel::create(['folder_id' => $args['id'], 'res_id' => $value]);
}
$folders = FolderModel::getById(['select' => ['label'], 'id' => $args['id']]);
$resourcesInfo = ResModel::get(['select' => ['alt_identifier'], 'where' => ['res_id in (?)'], 'data' => [$resourcesToClassify]]);
$resourcesIdentifier = array_column($resourcesInfo, 'alt_identifier');
foreach ($resourcesToClassify as $resource) {
HistoryController::add([
'tableName' => 'res_letterbox',
'recordId' => $resource,
'eventType' => 'UP',
'info' => _ADDED_TO_FOLDER . " \"" . $folders['label'] . "\"",
'moduleId' => 'resource',
'eventId' => 'resourceModification',
]);
}
Guillaume Heurtier
committed
HistoryController::add([
'tableName' => 'resources_folders',
'recordId' => $args['id'],
'eventType' => 'ADD',
'info' => _FOLDER_RESOURCES_ADDED . " : " . implode(", ", $resourcesIdentifier) . " " . _FOLDER_TO_FOLDER . " \"" . $folders['label'] . "\"",
Guillaume Heurtier
committed
'moduleId' => 'folder',
'eventId' => 'folderResourceAdded',
]);
return $response->withJson(['countResources' => count($foldersResources) + count($resourcesToClassify)]);
public function removeResourcesById(Request $request, Response $response, array $args)
{
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
if (!FolderController::hasFolders(['folders' => [$args['id']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder out of perimeter']);
}
$foldersResources = ResourceFolderModel::get(['select' => ['res_id'], 'where' => ['folder_id = ?'], 'data' => [$args['id']]]);
$foldersResources = array_column($foldersResources, 'res_id');
$body = $request->getParsedBody();
if (!Validator::arrayType()->notEmpty()->validate($body['resources'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body resources is empty or not an array']);
}
$resourcesToUnclassify = array_intersect($foldersResources, $body['resources']);
if (empty($resourcesToUnclassify)) {
return $response->withJson(['countResources' => count($foldersResources)]);
}
$folder = FolderModel::getById(['select' => ['label', 'public', 'user_id'], 'id' => $args['id']]);
if ($folder['public'] || $folder['user_id'] != $GLOBALS['id']) {
if (!ResController::hasRightByResId(['resId' => $resourcesToUnclassify, 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Resources out of perimeter']);
}
}
foreach ($resourcesToUnclassify as $value) {
ResourceFolderModel::delete(['where' => ['folder_id = ?', 'res_id = ?'], 'data' => [$args['id'], $value]]);
}
$resourcesInfo = ResModel::get(['select' => ['alt_identifier'], 'where' => ['res_id in (?)'], 'data' => [$resourcesToUnclassify]]);
$resourcesIdentifier = array_column($resourcesInfo, 'alt_identifier');
foreach ($resourcesToUnclassify as $resource) {
HistoryController::add([
'tableName' => 'res_letterbox',
'recordId' => $resource,
'eventType' => 'UP',
'info' => _REMOVED_TO_FOLDER . " \"" . $folder['label'] . "\"",
'moduleId' => 'resource',
'eventId' => 'resourceModification',
]);
}
Guillaume Heurtier
committed
HistoryController::add([
'tableName' => 'resources_folders',
'recordId' => $args['id'],
'eventType' => 'DEL',
'info' => _FOLDER_RESOURCES_REMOVED . " : " . implode(", ", $resourcesIdentifier) . " " . _FOLDER_TO_FOLDER . " \"" . $folder['label'] . "\"",
Guillaume Heurtier
committed
'moduleId' => 'folder',
Guillaume Heurtier
committed
'eventId' => 'folderResourceRemoved',
Guillaume Heurtier
committed
]);
return $response->withJson(['countResources' => count($foldersResources) - count($resourcesToUnclassify)]);
}
public function getBasketsFromFolder(Request $request, Response $response, array $args)
{
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
if (!FolderController::hasFolders(['folders' => [$args['id']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Folder out of perimeter']);
}
$foldersResource = ResourceFolderModel::get(['select' => [1], 'where' => ['folder_id = ?', 'res_id = ?'], 'data' => [$args['id'], $args['resId']]]);
if (empty($foldersResource)) {
return $response->withStatus(403)->withJson(['errors' => 'Resource out of perimeter']);
}
$baskets = BasketModel::getWithPreferences([
'select' => ['baskets.id', 'baskets.basket_name', 'baskets.basket_clause', 'users_baskets_preferences.group_serial_id', 'usergroups.group_desc'],
'where' => ['users_baskets_preferences.user_serial_id = ?'],
'data' => [$GLOBALS['id']],
'orderBy' => ['baskets.basket_name']
$groupsBaskets = [];
$inCheckedBaskets = [];
$outCheckedBaskets = [];
foreach ($baskets as $basket) {
if (in_array($basket['id'], $outCheckedBaskets)) {
continue;
} else {
if (!in_array($basket['id'], $inCheckedBaskets)) {
$preparedClause = PreparedClauseController::getPreparedClause(['clause' => $basket['basket_clause'], 'login' => $GLOBALS['login']]);
$resource = ResModel::getOnView(['select' => [1], 'where' => ['res_id = ?', "({$preparedClause})"], 'data' => [$args['resId']]]);
if (empty($resource)) {
$outCheckedBaskets[] = $basket['id'];
continue;
}
}
$inCheckedBaskets[] = $basket['id'];
$groupsBaskets[] = ['groupId' => $basket['group_serial_id'], 'groupName' => $basket['group_desc'], 'basketId' => $basket['id'], 'basketName' => $basket['basket_name']];
return $response->withJson(['groupsBaskets' => $groupsBaskets]);
public function getFilters(Request $request, Response $response, array $args)
{
if (!Validator::numeric()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
if (!FolderController::hasFolders(['folders' => [$args['id']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(400)->withJson(['errors' => 'Folder out of perimeter']);
}
$foldersResources = ResourceFolderModel::get(['select' => ['res_id'], 'where' => ['folder_id = ?'], 'data' => [$args['id']]]);
$foldersResources = array_column($foldersResources, 'res_id');
if (empty($foldersResources)) {
return $response->withJson([
'entities' => [],
'priorities' => [],
'categories' => [],
'statuses' => [],
'entitiesChildren' => [],
'doctypes' => [],
'folders' => []
]);
}
$where = ['(res_id in (?))'];
$queryData = [$foldersResources];
$queryParams = $request->getQueryParams();
$filters = ResourceListController::getFormattedFilters(['where' => $where, 'queryData' => $queryData, 'queryParams' => $queryParams]);
return $response->withJson($filters);
}
// login (string) : Login of user connected
// folderId (integer) : Check specific folder
// edition (boolean) : whether user can edit or not
Guillaume Heurtier
committed
public static function getScopeFolders(array $args)
Guillaume Heurtier
committed
$login = $args['login'];
$user = UserModel::getByLogin(['login' => $login, 'select' => ['id']]);
$userEntities = EntityModel::getWithUserEntities(['select' => ['entities.id'], 'where' => ['user_id = ?'], 'data' => [$user['id']]]);
$userEntities = array_column($userEntities, 'id');
if (empty($userEntities)) {
Guillaume Heurtier
committed
$userEntities = [0];
Guillaume Heurtier
committed
$args['edition'] = $args['edition'] ?? false;
Guillaume Heurtier
committed
if ($args['edition']) {
$edition = [1];
} else {
$edition = [0, 1, null];
}
$where = ['keyword = ?', 'entities_folders.edition in (?)'];
$data = ['ALL_ENTITIES', $edition];
Guillaume Heurtier
committed
if (!empty($args['folderId'])) {
$where[] = 'folder_id = ?';
$data[] = $args['folderId'];
}
$folderKeywords = EntityFolderModel::get([
'select' => ['folder_id'],
'where' => $where,
'data' => $data
]);
$folderKeywords = array_column($folderKeywords, 'folder_id');
if (empty($folderKeywords)) {
$folderKeywords = [0];
}