From 084ef83c1fa67b265b27e5d3981bdd7d42539824 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Wed, 28 Jan 2026 23:54:17 +0100 Subject: [PATCH 1/2] perf: Allow filtering the directory content by mimetype Signed-off-by: Carl Schwan --- apps/files/lib/Controller/ApiController.php | 8 +- apps/files_sharing/lib/External/Cache.php | 4 +- autotest.sh | 2 +- lib/private/Files/Cache/Cache.php | 13 +- lib/private/Files/Cache/FailedCache.php | 26 ++-- .../Files/Cache/Wrapper/CacheWrapper.php | 6 +- lib/private/Files/Filesystem.php | 6 +- lib/private/Files/Node/Folder.php | 13 +- lib/private/Files/Node/LazyFolder.php | 6 +- lib/private/Files/Node/NonExistingFolder.php | 4 +- lib/private/Files/View.php | 133 +++++++++--------- lib/private/Lockdown/Filesystem/NullCache.php | 14 +- lib/public/Files/Cache/ICache.php | 4 +- lib/public/Files/Folder.php | 5 +- tests/lib/Encryption/DecryptAllTest.php | 4 +- 15 files changed, 128 insertions(+), 120 deletions(-) diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index d8fb0ab0d59fc..790b0264594bd 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -249,7 +249,7 @@ public function getRecentFiles() { * @param \OCP\Files\Node[] $nodes * @param int $depth The depth to traverse into the contents of each node */ - private function getChildren(array $nodes, int $depth = 1, int $currentDepth = 0): array { + private function getChildren(array $nodes, int $depth = 1, int $currentDepth = 0, string $mimeTypeFilter = ''): array { if ($currentDepth >= $depth) { return []; } @@ -264,7 +264,7 @@ private function getChildren(array $nodes, int $depth = 1, int $currentDepth = 0 $entry = [ 'id' => $node->getId(), 'basename' => $basename, - 'children' => $this->getChildren($node->getDirectoryListing(), $depth, $currentDepth + 1), + 'children' => $this->getChildren($node->getDirectoryListing($mimeTypeFilter), $depth, $currentDepth + 1), ]; $displayName = $node->getName(); if ($basename !== $displayName) { @@ -308,8 +308,8 @@ public function getFolderTree(string $path = '/', int $depth = 1): JSONResponse 'message' => $this->l10n->t('Invalid folder path'), ], Http::STATUS_BAD_REQUEST); } - $nodes = $node->getDirectoryListing(); - $tree = $this->getChildren($nodes, $depth); + $nodes = $node->getDirectoryListing('httpd/unix-directory'); + $tree = $this->getChildren($nodes, $depth, 0, 'httpd/unix-directory'); } catch (NotFoundException $e) { return new JSONResponse([ 'message' => $this->l10n->t('Folder not found'), diff --git a/apps/files_sharing/lib/External/Cache.php b/apps/files_sharing/lib/External/Cache.php index 027f682d81841..865850fd537cc 100644 --- a/apps/files_sharing/lib/External/Cache.php +++ b/apps/files_sharing/lib/External/Cache.php @@ -41,8 +41,8 @@ public function get($file) { return $result; } - public function getFolderContentsById($fileId) { - $results = parent::getFolderContentsById($fileId); + public function getFolderContentsById($fileId, ?string $mimeTypeFilter = null): array { + $results = parent::getFolderContentsById($fileId, $mimeTypeFilter); foreach ($results as &$file) { $file['displayname_owner'] = $this->cloudId->getDisplayId(); } diff --git a/autotest.sh b/autotest.sh index bac67a768beec..ec8631a72722c 100755 --- a/autotest.sh +++ b/autotest.sh @@ -309,7 +309,7 @@ function execute_tests { if [ ! -z "$USEDOCKER" ] ; then echo "Fire up the postgres docker" DOCKER_CONTAINER_ID=$(docker run -e POSTGRES_DB="$DATABASENAME" -e POSTGRES_USER="$DATABASEUSER" -e POSTGRES_PASSWORD=owncloud -d postgres) - DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID") + DATABASEHOST=$(docker inspect --format="{{ range .NetworkSettings.Networks }}{{ .IPAddress }}{{ end }}" "$DOCKER_CONTAINER_ID") echo "Waiting for Postgres initialisation ..." diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 6213b88fc17df..a5b751eeee43b 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -216,7 +216,7 @@ public function getFolderContents($folder) { * @param int $fileId the file id of the folder * @return ICacheEntry[] */ - public function getFolderContentsById($fileId) { + public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null) { if ($fileId > -1) { $query = $this->getQueryBuilder(); $query->selectFileCache() @@ -224,13 +224,22 @@ public function getFolderContentsById($fileId) { ->whereStorageId($this->getNumericStorageId()) ->orderBy('name', 'ASC'); + if ($mimeTypeFilter !== null) { + $mimetype = $this->mimetypeLoader->getId($mimeTypeFilter); + if (str_contains($mimeTypeFilter, '/')) { + $query->andWhere($query->expr()->eq('mimetype', $query->createNamedParameter($mimetype))); + } else { + $query->andWhere($query->expr()->eq('mimepart', $query->createNamedParameter($mimetype))); + } + } + $metadataQuery = $query->selectMetadata(); $result = $query->executeQuery(); $files = $result->fetchAll(); $result->closeCursor(); - return array_map(function (array $data) use ($metadataQuery) { + return array_map(function (array $data) use ($metadataQuery): ICacheEntry { $data['metadata'] = $metadataQuery->extractMetadata($data)->asArray(); return self::cacheEntryFromData($data, $this->mimetypeLoader); }, $files); diff --git a/lib/private/Files/Cache/FailedCache.php b/lib/private/Files/Cache/FailedCache.php index 44c1016ca8ea6..010ff80cd15e2 100644 --- a/lib/private/Files/Cache/FailedCache.php +++ b/lib/private/Files/Cache/FailedCache.php @@ -19,24 +19,20 @@ * Storage placeholder to represent a missing precondition, storage unavailable */ class FailedCache implements ICache { - /** @var bool whether to show the failed storage in the ui */ - private $visible; /** - * FailedCache constructor. - * - * @param bool $visible + * @param bool $visible Whether to show the failed storage in the ui */ - public function __construct($visible = true) { - $this->visible = $visible; + public function __construct( + private bool $visible = true, + ) { } - - public function getNumericStorageId() { + public function getNumericStorageId(): int { return -1; } - public function get($file) { + public function get($file): false|ICacheEntry { if ($file === '') { return new CacheEntry([ 'fileid' => -1, @@ -51,11 +47,11 @@ public function get($file) { } } - public function getFolderContents($folder) { + public function getFolderContents($folder): array { return []; } - public function getFolderContentsById($fileId) { + public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null): array { return []; } @@ -68,15 +64,15 @@ public function insert($file, array $data) { public function update($id, array $data) { } - public function getId($file) { + public function getId($file): int { return -1; } - public function getParentId($file) { + public function getParentId($file): int { return -1; } - public function inCache($file) { + public function inCache($file): bool { return false; } diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index bf23f1cc30ab0..80c25289f21b1 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -105,9 +105,9 @@ public function getFolderContents($folder) { * @param int $fileId the file id of the folder * @return array */ - public function getFolderContentsById($fileId) { - $results = $this->getCache()->getFolderContentsById($fileId); - return array_map([$this, 'formatCacheEntry'], $results); + public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null) { + $results = $this->getCache()->getFolderContentsById($fileId, $mimeTypeFilter); + return array_map($this->formatCacheEntry(...), $results); } /** diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 3054eddf3e7de..73b1edc37bcf9 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -660,11 +660,11 @@ public static function putFileInfo($path, $data) { * get the content of a directory * * @param string $directory path under datadirectory - * @param string $mimetype_filter limit returned content to this mimetype or mimepart + * @param string $mimeTypeFilter limit returned content to this mimetype or mimepart * @return \OC\Files\FileInfo[] */ - public static function getDirectoryContent($directory, $mimetype_filter = '') { - return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter); + public static function getDirectoryContent($directory, $mimeTypeFilter = '') { + return self::$defaultInstance->getDirectoryContent($directory, $mimeTypeFilter); } /** diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index fef0d634f0562..c27f051108059 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -76,16 +76,11 @@ public function isSubNode($node) { return str_starts_with($node->getPath(), $this->path . '/'); } - /** - * get the content of this directory - * - * @return Node[] - * @throws \OCP\Files\NotFoundException - */ - public function getDirectoryListing() { - $folderContent = $this->view->getDirectoryContent($this->path, '', $this->getFileInfo(false)); + #[Override] + public function getDirectoryListing(?string $mimetypeFilter = null): array { + $folderContent = $this->view->getDirectoryContent($this->path, $mimetypeFilter, $this->getFileInfo(false)); - return array_map(function (FileInfo $info) { + return array_map(function (FileInfo $info): Node { if ($info->getMimetype() === FileInfo::MIMETYPE_FOLDER) { return new Folder($this->root, $this->view, $info->getPath(), $info, $this); } else { diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php index c23a7d03ada9e..1b3c9692e7477 100644 --- a/lib/private/Files/Node/LazyFolder.php +++ b/lib/private/Files/Node/LazyFolder.php @@ -415,10 +415,8 @@ public function isSubNode($node) { return $this->__call(__FUNCTION__, func_get_args()); } - /** - * @inheritDoc - */ - public function getDirectoryListing() { + #[Override] + public function getDirectoryListing(?string $mimetypeFilter = null): array { return $this->__call(__FUNCTION__, func_get_args()); } diff --git a/lib/private/Files/Node/NonExistingFolder.php b/lib/private/Files/Node/NonExistingFolder.php index 4489fdaf01067..ee07e53beddfc 100644 --- a/lib/private/Files/Node/NonExistingFolder.php +++ b/lib/private/Files/Node/NonExistingFolder.php @@ -8,6 +8,7 @@ namespace OC\Files\Node; use OCP\Files\NotFoundException; +use Override; class NonExistingFolder extends Folder { /** @@ -118,7 +119,8 @@ public function get($path) { throw new NotFoundException(); } - public function getDirectoryListing() { + #[Override] + public function getDirectoryListing(?string $mimetypeFilter = null): never { throw new NotFoundException(); } diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 4a9ef9f813814..f18b8563f80dd 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -1471,15 +1471,20 @@ public function addSubMounts(FileInfo $info, $extOnly = false): void { * get the content of a directory * * @param string $directory path under datadirectory - * @param string $mimetype_filter limit returned content to this mimetype or mimepart + * @param ?non-empty-string $mimeTypeFilter limit returned content to this mimetype or mimepart * @return FileInfo[] */ - public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Files\FileInfo $directoryInfo = null) { + public function getDirectoryContent(string $directory, ?string $mimeTypeFilter = null, ?\OCP\Files\FileInfo $directoryInfo = null) { $this->assertPathLength($directory); if (!Filesystem::isValidPath($directory)) { return []; } + /** @psalm-suppress TypeDoesNotContainType For legacy compatibility */ + if ($mimeTypeFilter === '') { + $mimeTypeFilter = null; + } + $path = $this->getAbsolutePath($directory); $path = Filesystem::normalizePath($path); $mount = $this->getMount($directory); @@ -1506,7 +1511,7 @@ public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Fil } $folderId = $data->getId(); - $contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter + $contents = $cache->getFolderContentsById($folderId, $mimeTypeFilter); $sharingDisabled = \OCP\Util::isSharingDisabledForUser(); $permissionsMask = ~\OCP\Constants::PERMISSION_SHARE; @@ -1567,79 +1572,79 @@ public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Fil $rootEntry = $subCache->get(''); } - if ($rootEntry && ($rootEntry->getPermissions() & Constants::PERMISSION_READ)) { - $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if ($pos = strpos($relativePath, '/')) { - //mountpoint inside subfolder add size to the correct folder - $entryName = substr($relativePath, 0, $pos); - - // Create parent folders if the mountpoint is inside a subfolder that doesn't exist yet - if (!isset($files[$entryName])) { - try { - [$storage, ] = $this->resolvePath($path . '/' . $entryName); - // make sure we can create the mountpoint folder, even if the user has a quota of 0 - if ($storage->instanceOfStorage(Quota::class)) { - $storage->enableQuota(false); - } + if (!$rootEntry || !($rootEntry->getPermissions() & Constants::PERMISSION_READ)) { + continue; + } - if ($this->mkdir($path . '/' . $entryName) !== false) { - $info = $this->getFileInfo($path . '/' . $entryName); - if ($info !== false) { - $files[$entryName] = $info; - } - } + if ($mimeTypeFilter !== null) { + if (strpos($mimeTypeFilter, '/') !== false && $rootEntry['mimetype'] !== $mimeTypeFilter) { + continue; + } elseif (strpos($mimeTypeFilter, '/') === false && $rootEntry['mimepart'] !== $mimeTypeFilter) { + continue; + } + } + + $relativePath = trim(substr($mountPoint, $dirLength), '/'); + if ($pos = strpos($relativePath, '/')) { + //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + + // Create parent folders if the mountpoint is inside a subfolder that doesn't exist yet + if (!isset($files[$entryName])) { + try { + [$storage, ] = $this->resolvePath($path . '/' . $entryName); + // make sure we can create the mountpoint folder, even if the user has a quota of 0 + if ($storage->instanceOfStorage(Quota::class)) { + $storage->enableQuota(false); + } - if ($storage->instanceOfStorage(Quota::class)) { - $storage->enableQuota(true); + if ($this->mkdir($path . '/' . $entryName) !== false) { + $info = $this->getFileInfo($path . '/' . $entryName); + if ($info !== false) { + $files[$entryName] = $info; } - } catch (\Exception $e) { - // Creating the parent folder might not be possible, for example due to a lack of permissions. - $this->logger->debug('Failed to create non-existent parent', ['exception' => $e, 'path' => $path . '/' . $entryName]); } - } - if (isset($files[$entryName])) { - $files[$entryName]->addSubEntry($rootEntry, $mountPoint); - } - } else { //mountpoint in this folder, add an entry for it - $rootEntry['name'] = $relativePath; - $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; - $permissions = $rootEntry['permissions']; - // do not allow renaming/deleting the mount point if they are not shared files/folders - // for shared files/folders we use the permissions given by the owner - if ($mount instanceof MoveableMount) { - $rootEntry['permissions'] = $permissions | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; - } else { - $rootEntry['permissions'] = $permissions & (\OCP\Constants::PERMISSION_ALL - (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)); + if ($storage->instanceOfStorage(Quota::class)) { + $storage->enableQuota(true); + } + } catch (\Exception $e) { + // Creating the parent folder might not be possible, for example due to a lack of permissions. + $this->logger->debug('Failed to create non-existent parent', ['exception' => $e, 'path' => $path . '/' . $entryName]); } + } - $rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/ + if (isset($files[$entryName])) { + $files[$entryName]->addSubEntry($rootEntry, $mountPoint); + } + } else { //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $permissions = $rootEntry['permissions']; + // do not allow renaming/deleting the mount point if they are not shared files/folders + // for shared files/folders we use the permissions given by the owner + if ($mount instanceof MoveableMount) { + $rootEntry['permissions'] = $permissions | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; + } else { + $rootEntry['permissions'] = $permissions & (\OCP\Constants::PERMISSION_ALL - (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE)); + } - // if sharing was disabled for the user we remove the share permissions - if ($sharingDisabled) { - $rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; - } + $rootEntry['path'] = substr(Filesystem::normalizePath($path . '/' . $rootEntry['name']), strlen($user) + 2); // full path without /$user/ - $ownerId = $subStorage->getOwner(''); - if ($ownerId !== false) { - $owner = $this->getUserObjectForOwner($ownerId); - } else { - $owner = null; - } - $files[$rootEntry->getName()] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner); + // if sharing was disabled for the user we remove the share permissions + if ($sharingDisabled) { + $rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE; } - } - } - } - if ($mimetype_filter) { - $files = array_filter($files, function (FileInfo $file) use ($mimetype_filter) { - if (strpos($mimetype_filter, '/')) { - return $file->getMimetype() === $mimetype_filter; - } else { - return $file->getMimePart() === $mimetype_filter; + $ownerId = $subStorage->getOwner(''); + if ($ownerId !== false) { + $owner = $this->getUserObjectForOwner($ownerId); + } else { + $owner = null; + } + $files[$rootEntry->getName()] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner); } - }); + } } return array_values($files); diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php index 5a27c5d5c6e9e..a09f3f433140c 100644 --- a/lib/private/Lockdown/Filesystem/NullCache.php +++ b/lib/private/Lockdown/Filesystem/NullCache.php @@ -17,11 +17,11 @@ use OCP\Files\Search\ISearchQuery; class NullCache implements ICache { - public function getNumericStorageId() { + public function getNumericStorageId(): int { return -1; } - public function get($file) { + public function get($file): false|ICacheEntry { if ($file !== '') { return false; } @@ -41,23 +41,23 @@ public function get($file) { ]); } - public function getFolderContents($folder) { + public function getFolderContents($folder): array { return []; } - public function getFolderContentsById($fileId) { + public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null): array { return []; } - public function put($file, array $data) { + public function put($file, array $data): never { throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); } - public function insert($file, array $data) { + public function insert($file, array $data): never { throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); } - public function update($id, array $data) { + public function update($id, array $data): never { throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); } diff --git a/lib/public/Files/Cache/ICache.php b/lib/public/Files/Cache/ICache.php index cd610b155454b..00bed53b44f39 100644 --- a/lib/public/Files/Cache/ICache.php +++ b/lib/public/Files/Cache/ICache.php @@ -77,10 +77,12 @@ public function getFolderContents($folder); * Only returns files one level deep, no recursion * * @param int $fileId the file id of the folder + * @param ?non-empty-string $mimeTypeFilter The mimetype or mimepart for which the content should be filtered * @return ICacheEntry[] * @since 9.0.0 + * @since 34.0.0 The $mimetypeFilter was added. */ - public function getFolderContentsById($fileId); + public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null); /** * store meta data for a file or folder diff --git a/lib/public/Files/Folder.php b/lib/public/Files/Folder.php index ba23b872abd40..9ed1957e8cab7 100644 --- a/lib/public/Files/Folder.php +++ b/lib/public/Files/Folder.php @@ -46,13 +46,14 @@ public function getRelativePath($path); public function isSubNode($node); /** - * get the content of this directory + * Get the content of this directory. * + * @param ?non-empty-string $mimetypeFilter Limit the returned content to this mimetype or mimepart * @throws \OCP\Files\NotFoundException * @return \OCP\Files\Node[] * @since 6.0.0 */ - public function getDirectoryListing(); + public function getDirectoryListing(?string $mimetypeFilter = null): array; /** * Get the node at $path diff --git a/tests/lib/Encryption/DecryptAllTest.php b/tests/lib/Encryption/DecryptAllTest.php index f7a6497e011be..04cfb5b56fe8b 100644 --- a/tests/lib/Encryption/DecryptAllTest.php +++ b/tests/lib/Encryption/DecryptAllTest.php @@ -248,7 +248,7 @@ public function testDecryptUsersFiles(): void { ->method('getDirectoryContent') ->willReturnMap([ [ - '/user1/files', '', null, + '/user1/files', null, null, [ new FileInfo('path', $storage, 'intPath', ['name' => 'foo', 'type' => 'dir'], null), new FileInfo('path', $storage, 'intPath', ['name' => 'bar', 'type' => 'file', 'encrypted' => true], null), @@ -256,7 +256,7 @@ public function testDecryptUsersFiles(): void { ], ], [ - '/user1/files/foo', '', null, + '/user1/files/foo', null, null, [ new FileInfo('path', $storage, 'intPath', ['name' => 'subfile', 'type' => 'file', 'encrypted' => true], null) ], From ce34d559220c751971c98927a0dfd21daad9b57f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Thu, 29 Jan 2026 15:42:28 +0100 Subject: [PATCH 2/2] perf(file-cache): Add mimetype filter on getFolderContents Signed-off-by: Carl Schwan --- apps/files/lib/Controller/ApiController.php | 4 +++- autotest.sh | 2 +- lib/private/Files/Cache/Cache.php | 19 +++++-------------- lib/private/Files/Cache/FailedCache.php | 2 +- .../Files/Cache/Wrapper/CacheWrapper.php | 4 ++-- lib/private/Files/Filesystem.php | 4 ++-- lib/private/Lockdown/Filesystem/NullCache.php | 2 +- lib/public/Files/Cache/ICache.php | 18 ++++++++++-------- 8 files changed, 25 insertions(+), 30 deletions(-) diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index 790b0264594bd..c5ac714593100 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -247,9 +247,11 @@ public function getRecentFiles() { /** * @param \OCP\Files\Node[] $nodes + * @param ?non-empty-string $mimeTypeFilter limit returned content to this mimetype or mimepart * @param int $depth The depth to traverse into the contents of each node + * @return list */ - private function getChildren(array $nodes, int $depth = 1, int $currentDepth = 0, string $mimeTypeFilter = ''): array { + private function getChildren(array $nodes, int $depth = 1, int $currentDepth = 0, ?string $mimeTypeFilter = null): array { if ($currentDepth >= $depth) { return []; } diff --git a/autotest.sh b/autotest.sh index ec8631a72722c..bac67a768beec 100755 --- a/autotest.sh +++ b/autotest.sh @@ -309,7 +309,7 @@ function execute_tests { if [ ! -z "$USEDOCKER" ] ; then echo "Fire up the postgres docker" DOCKER_CONTAINER_ID=$(docker run -e POSTGRES_DB="$DATABASENAME" -e POSTGRES_USER="$DATABASEUSER" -e POSTGRES_PASSWORD=owncloud -d postgres) - DATABASEHOST=$(docker inspect --format="{{ range .NetworkSettings.Networks }}{{ .IPAddress }}{{ end }}" "$DOCKER_CONTAINER_ID") + DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID") echo "Waiting for Postgres initialisation ..." diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index a5b751eeee43b..7deb5dcad0163 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -35,6 +35,7 @@ use OCP\FilesMetadata\IFilesMetadataManager; use OCP\IDBConnection; use OCP\Util; +use Override; use Psr\Log\LoggerInterface; /** @@ -199,23 +200,13 @@ public static function cacheEntryFromData(array $data, IMimeTypeLoader $mimetype return new CacheEntry($normalized); } - /** - * get the metadata of all files stored in $folder - * - * @param string $folder - * @return ICacheEntry[] - */ - public function getFolderContents($folder) { + #[Override] + public function getFolderContents(string $folder, ?string $mimeTypeFilter = null) { $fileId = $this->getId($folder); - return $this->getFolderContentsById($fileId); + return $this->getFolderContentsById($fileId, $mimeTypeFilter); } - /** - * get the metadata of all files stored in $folder - * - * @param int $fileId the file id of the folder - * @return ICacheEntry[] - */ + #[Override] public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null) { if ($fileId > -1) { $query = $this->getQueryBuilder(); diff --git a/lib/private/Files/Cache/FailedCache.php b/lib/private/Files/Cache/FailedCache.php index 010ff80cd15e2..2bf35ad473797 100644 --- a/lib/private/Files/Cache/FailedCache.php +++ b/lib/private/Files/Cache/FailedCache.php @@ -47,7 +47,7 @@ public function get($file): false|ICacheEntry { } } - public function getFolderContents($folder): array { + public function getFolderContents(string $folder, ?string $mimeTypeFilter = null): array { return []; } diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index 80c25289f21b1..ef0144811df80 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -92,11 +92,11 @@ public function get($file) { * @param string $folder * @return ICacheEntry[] */ - public function getFolderContents($folder) { + public function getFolderContents(string $folder, ?string $mimeTypeFilter = null): array { // can't do a simple $this->getCache()->.... call here since getFolderContentsById needs to be called on this // and not the wrapped cache $fileId = $this->getId($folder); - return $this->getFolderContentsById($fileId); + return $this->getFolderContentsById($fileId, $mimeTypeFilter); } /** diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 73b1edc37bcf9..36de155acf4c5 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -660,10 +660,10 @@ public static function putFileInfo($path, $data) { * get the content of a directory * * @param string $directory path under datadirectory - * @param string $mimeTypeFilter limit returned content to this mimetype or mimepart + * @param ?non-empty-string $mimeTypeFilter limit returned content to this mimetype or mimepart * @return \OC\Files\FileInfo[] */ - public static function getDirectoryContent($directory, $mimeTypeFilter = '') { + public static function getDirectoryContent($directory, ?string $mimeTypeFilter = null): array { return self::$defaultInstance->getDirectoryContent($directory, $mimeTypeFilter); } diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php index a09f3f433140c..ce4684e2518d0 100644 --- a/lib/private/Lockdown/Filesystem/NullCache.php +++ b/lib/private/Lockdown/Filesystem/NullCache.php @@ -41,7 +41,7 @@ public function get($file): false|ICacheEntry { ]); } - public function getFolderContents($folder): array { + public function getFolderContents(string $folder, ?string $mimeTypeFilter = null): array { return []; } diff --git a/lib/public/Files/Cache/ICache.php b/lib/public/Files/Cache/ICache.php index 00bed53b44f39..2f324c85f85aa 100644 --- a/lib/public/Files/Cache/ICache.php +++ b/lib/public/Files/Cache/ICache.php @@ -52,7 +52,7 @@ interface ICache { public function getNumericStorageId(); /** - * get the stored metadata of a file or folder + * Get the stored metadata of a file or folder. * * @param string | int $file either the path of a file or folder or the file id for a file or folder * @return ICacheEntry|false the cache entry or false if the file is not found in the cache @@ -61,20 +61,21 @@ public function getNumericStorageId(); public function get($file); /** - * get the metadata of all files stored in $folder + * Get the metadata of all files stored in $folder. * - * Only returns files one level deep, no recursion + * @note This only returns files one level deep with no recursion. * * @param string $folder + * @param ?non-empty-string $mimeTypeFilter The mimetype or mimepart for which the content should be filtered * @return ICacheEntry[] * @since 9.0.0 */ - public function getFolderContents($folder); + public function getFolderContents(string $folder, ?string $mimeTypeFilter = null); /** - * get the metadata of all files stored in $folder + * Get the metadata of all files stored in $folder. * - * Only returns files one level deep, no recursion + * @note This only returns files one level deep with no recursion. * * @param int $fileId the file id of the folder * @param ?non-empty-string $mimeTypeFilter The mimetype or mimepart for which the content should be filtered @@ -85,8 +86,9 @@ public function getFolderContents($folder); public function getFolderContentsById(int $fileId, ?string $mimeTypeFilter = null); /** - * store meta data for a file or folder - * This will automatically call either insert or update depending on if the file exists + * Store meta data for a file or folder. + * + * This will automatically call either insert or update depending on if the file exists. * * @param string $file * @param array $data