diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 371f575b9a25e..9266ddb8f9a77 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3777,7 +3777,6 @@ - mountManager->findByNumericId($numericId)]]> mountManager->findByStorageId($storageId)]]> mountManager->findIn($mountPoint)]]> diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index fef0d634f0562..ab5bf16f408ba 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -338,7 +338,7 @@ public function getAppDataDirectoryName(): string { * in. * * @param int $id - * @return array + * @return list */ protected function getByIdInRootMount(int $id): array { if (!method_exists($this->root, 'createNode')) { diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index c94eadcedb3f6..01ba094390bf4 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -19,6 +19,7 @@ use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; use OCP\Files\Events\Node\FilesystemTornDownEvent; use OCP\Files\IRootFolder; @@ -388,7 +389,7 @@ public function getFirstNodeByIdInPath(int $id, string $path): ?INode { } } } - $node = current($this->getByIdInPath($id, $path)); + $node = current($this->getByIdInPath($id, $path, true)); if (!$node) { return null; } @@ -400,10 +401,10 @@ public function getFirstNodeByIdInPath(int $id, string $path): ?INode { } /** - * @param int $id - * @return Node[] + * @return list + * @note $onlyFirst is not part of the public API, only used by getFirstNodeByIdInPath */ - public function getByIdInPath(int $id, string $path): array { + public function getByIdInPath(int $id, string $path, bool $onlyFirst = false): array { $mountCache = $this->getUserMountCache(); $setupManager = $this->mountManager->getSetupManager(); if ($path !== '' && strpos($path, '/', 1) > 0) { @@ -426,54 +427,46 @@ public function getByIdInPath(int $id, string $path): array { // // so instead of using the cached entries directly, we instead filter the current mounts by the rootid of the cache entry - $mountRootIds = array_map(function ($mount) { - return $mount->getRootId(); - }, $mountsContainingFile); - $mountRootPaths = array_map(function ($mount) { - return $mount->getRootInternalPath(); - }, $mountsContainingFile); - $mountProviders = array_unique(array_map(function ($mount) { - return $mount->getMountProvider(); - }, $mountsContainingFile)); - $mountRoots = array_combine($mountRootIds, $mountRootPaths); + /** @var array $mountRoots */ + $mountRoots = []; + foreach ($mountsContainingFile as $mountInfo) { + $mountRoots[$mountInfo->getRootId()] = $mountInfo->getRootInternalPath(); + } - $mountsContainingFile = array_filter(array_map($this->mountManager->getMountFromMountInfo(...), $mountsContainingFile)); + $userManager = Server::get(IUserManager::class); + $foundMount = false; + $nodes = []; + foreach ($mountsContainingFile as $mountInfo) { + $mount = $this->mountManager->getMountFromMountInfo($mountInfo); + if ($mount === null) { + continue; + } + $foundMount = true; - if (count($mountsContainingFile) === 0) { - if ($user === $this->getAppDataDirectoryName()) { - $folder = $this->get($path); - if ($folder instanceof Folder) { - return $folder->getByIdInRootMount($id); - } else { - throw new \Exception('getByIdInPath with non folder'); - } + $storage = $mount->getStorage(); + if ($storage === null) { + continue; } - return []; - } - $nodes = array_map(function (IMountPoint $mount) use ($id, $mountRoots) { - $rootInternalPath = $mountRoots[$mount->getStorageRootId()]; - $cacheEntry = $mount->getStorage()->getCache()->get($id); - if (!$cacheEntry) { - return null; + $cacheEntry = $storage->getCache()->get($id); + if ($cacheEntry === false) { + continue; } + $rootInternalPath = $mountRoots[$mount->getStorageRootId()]; + // cache jails will hide the "true" internal path $internalPath = ltrim($rootInternalPath . '/' . $cacheEntry->getPath(), '/'); $pathRelativeToMount = substr($internalPath, strlen($rootInternalPath)); $pathRelativeToMount = ltrim($pathRelativeToMount, '/'); $absolutePath = rtrim($mount->getMountPoint() . $pathRelativeToMount, '/'); - $storage = $mount->getStorage(); - if ($storage === null) { - return null; - } $ownerId = $storage->getOwner($pathRelativeToMount); if ($ownerId !== false) { - $owner = Server::get(IUserManager::class)->get($ownerId); + $owner = $userManager->get($ownerId); } else { $owner = null; } - return $this->createNode($absolutePath, new FileInfo( + $node = $this->createNode($absolutePath, new FileInfo( $absolutePath, $storage, $cacheEntry->getPath(), @@ -481,17 +474,29 @@ public function getByIdInPath(int $id, string $path): array { $mount, $owner, )); - }, $mountsContainingFile); - $nodes = array_filter($nodes); + if (PathHelper::getRelativePath($path, $node->getPath()) !== null) { + $nodes[] = $node; + if ($onlyFirst) { + return $nodes; + } + } + } - $folders = array_filter($nodes, function (Node $node) use ($path) { - return PathHelper::getRelativePath($path, $node->getPath()) !== null; - }); - usort($folders, function ($a, $b) { - return $b->getPath() <=> $a->getPath(); - }); - return $folders; + if (!$foundMount) { + if ($user === $this->getAppDataDirectoryName()) { + $folder = $this->get($path); + if ($folder instanceof Folder) { + return $folder->getByIdInRootMount($id); + } else { + throw new \Exception('getByIdInPath with non folder'); + } + } + return []; + } + + usort($nodes, static fn (Node $a, Node $b): int => $b->getPath() <=> $a->getPath()); + return $nodes; } public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode { diff --git a/lib/public/Files/IRootFolder.php b/lib/public/Files/IRootFolder.php index fb8532f8c8153..10672a2b3cdbd 100644 --- a/lib/public/Files/IRootFolder.php +++ b/lib/public/Files/IRootFolder.php @@ -36,7 +36,7 @@ public function getUserFolder($userId); * * @param int $id * @param string $path - * @return Node[] + * @return list * * @since 24.0.0 */