getName(); $storage = $folder->getStorage(); try { $parentFolder = $parentFolder ?? $folder->getParentFolder(); } catch (InsufficientFolderAccessPermissionsException) { $parentFolder = null; } if (str_contains($folder->getRole(), FolderInterface::ROLE_MOUNT)) { $tableName = 'sys_filemount'; $isStorage = true; } elseif ($parentFolder === null || $folder->getIdentifier() === $storage->getRootLevelFolder()->getIdentifier()) { $tableName = 'sys_file_storage'; $isStorage = true; } else { $tableName = 'sys_file'; $isStorage = false; } try { $hasSubfolders = $storage->isBrowsable() && (is_array($children) ? $children !== [] : !empty($folder->getSubfolders())); } catch (\InvalidArgumentException|InsufficientFolderReadPermissionsException) { $hasSubfolders = false; } return [ 'resource' => $folder, 'identifier' => rawurlencode($folder->getCombinedIdentifier()), 'name' => $name, 'storage' => $storage->getUid(), 'pathIdentifier' => rawurlencode($folder->getIdentifier()), 'hasChildren' => $hasSubfolders, 'parentIdentifier' => !$isStorage ? rawurlencode($parentFolder->getCombinedIdentifier()) : null, 'recordType' => $tableName, ]; } /** * Fetch all file storages / file mounts visible for a user. */ public function getRootNodes(BackendUserAuthentication $user): array { $items = []; $storages = $user->getFileStorages(); foreach ($storages as $storageObject) { $items = array_merge($items, $this->getFoldersInStorage($storageObject, $user)); } return $items; } /** * Fetch all folders recursively in a single store. */ protected function getFoldersInStorage(ResourceStorage $resourceStorage, BackendUserAuthentication $user): array { $rootLevelFolders = $this->getMountsInStorage($resourceStorage, $user); $items = []; foreach ($rootLevelFolders as $rootLevelFolderInfo) { /** @var Folder $rootLevelFolder */ $rootLevelFolder = $rootLevelFolderInfo['folder']; $item = $this->prepareFolderInformation($rootLevelFolder, $rootLevelFolderInfo['name']); $item['depth'] = 0; $item['expanded'] = true; $item['loaded'] = true; $items[] = $item; if ($resourceStorage->isBrowsable()) { // Handle sub folders if the mount is browsable. $childItems = $this->getSubfolders($rootLevelFolder, 1); array_push($items, ...$childItems); } } return $items; } /** * Filter a tree by a search word * * @return FolderInterface[] * @throws \Exception */ public function getFilteredTree(BackendUserAuthentication $user, string $search): array { $foundFolders = []; $storages = $user->getFileStorages(); foreach ($storages as $resourceStorage) { $processingFolders = $resourceStorage->getProcessingFolders(); $processingFolderIdentifiers = array_map(static function (Folder $folder): string { return $folder->getIdentifier(); }, $processingFolders); $resourceStorage->addFileAndFolderNameFilter(static function ($itemName, $itemIdentifier, $parentIdentifier, array $additionalInformation, DriverInterface $driver) use ($resourceStorage, $search, $processingFolderIdentifiers) { // Skip items in processing folders $isInProcessingFolder = array_filter($processingFolderIdentifiers, static function (string $processingFolderIdentifier) use ($parentIdentifier): bool { return stripos($parentIdentifier, $processingFolderIdentifier) !== false; }); if (!empty($isInProcessingFolder)) { return -1; } if ($itemName instanceof Folder) { if ($resourceStorage->isProcessingFolder($itemName)) { return -1; } $name = $itemName->getName(); } elseif (is_string($itemName)) { $name = $itemName; } else { return -1; } if (stripos($name, $search) !== false) { return true; } return -1; }); try { $files = $folders = []; // Because $resourceStorage->getRootLevelFolder() does not return an actual root folder but // the first file mount, we first need to check if we have file mounts and then fetch them one by one. if (($fileMounts = $resourceStorage->getFileMounts()) !== []) { foreach ($fileMounts as $identifier => $configuration) { foreach ($resourceStorage->getFilesInFolder($resourceStorage->getFolder($identifier), 0, 0, true, true) as $file) { $files[] = $file; } foreach ($resourceStorage->getFolderIdentifiersInFolder($identifier, true, true) as $folder) { $folders[] = $folder; } } } else { $files = $resourceStorage->getFilesInFolder($resourceStorage->getRootLevelFolder(), 0, 0, true, true); $folders = $resourceStorage->getFolderIdentifiersInFolder($resourceStorage->getRootLevelFolder()->getIdentifier(), true, true); } foreach ($files as $file) { $folder = $file->getParentFolder(); $foundFolders[$folder->getCombinedIdentifier()] = $folder; } foreach ($folders as $folder) { $folderObj = $resourceStorage->getFolder($folder); $foundFolders[$folderObj->getCombinedIdentifier()] = $folderObj; } } catch (InsufficientFolderAccessPermissionsException $e) { // do nothing } $resourceStorage->resetFileAndFolderNameFiltersToDefault(); } return $foundFolders; } public function getSubfolders(Folder $folderObject, int $currentDepth): array { $items = []; $subFolders = []; if (!$folderObject instanceof InaccessibleFolder) { $subFolders = $folderObject->getSubfolders(); $subFolders = ListUtility::resolveSpecialFolderNames($subFolders); uksort($subFolders, strnatcasecmp(...)); } foreach ($subFolders as $subFolderName => $subFolder) { $subFolderName = (string)$subFolderName; // Enforce string cast in case $subFolderName contains numeric chars only $children = []; if (!($subFolder instanceof InaccessibleFolder)) { // Get children to determine if that folder can be expanded again, 'hasChildren true' then renders expand triangle $children = $subFolder->getSubfolders(); } $items[] = array_merge( $this->prepareFolderInformation($subFolder, $subFolderName, $folderObject, $children), [ 'depth' => $currentDepth, 'expanded' => false, 'loaded' => false, ] ); } return $items; } /** * Fetches all "root level folders" of a storage. If a user has file mounts in this storage, they are properly resolved. * * @return array|array[] */ protected function getMountsInStorage(ResourceStorage $resourceStorage, BackendUserAuthentication $user): array { $fileMounts = $resourceStorage->getFileMounts(); if (!empty($fileMounts)) { return array_map(static function (array $fileMountInfo): array { return [ 'folder' => $fileMountInfo['folder'], 'name' => $fileMountInfo['title'], ]; }, $fileMounts); } if ($user->isAdmin()) { return [ [ 'folder' => $resourceStorage->getRootLevelFolder(), 'name' => $resourceStorage->getName(), ], ]; } return []; } }