diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 1163db1d93015..14845acd69093 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3640,7 +3640,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 c27f051108059..126b708175bca 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -333,7 +333,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 8354f382aa3be..176788495a0f0 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -389,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; } @@ -401,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) { @@ -427,17 +427,12 @@ 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(); - }, $mountInfosContainingFiles); - $mountRootPaths = array_map(function ($mount) { - return $mount->getRootInternalPath(); - }, $mountInfosContainingFiles); - $mountProviders = array_unique(array_map(function ($mount) { - return $mount->getMountProvider(); - }, $mountInfosContainingFiles)); $mountPoints = array_map(fn (ICachedMountInfo $mountInfo) => $mountInfo->getMountPoint(), $mountInfosContainingFiles); - $mountRoots = array_combine($mountRootIds, $mountRootPaths); + /** @var array $mountRoots */ + $mountRoots = []; + foreach ($mountsContainingFile as $mountInfo) { + $mountRoots[$mountInfo->getRootId()] = $mountInfo->getRootInternalPath(); + } $mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders); $mountsContainingFile = array_filter($mounts, fn (IMountPoint $mount) => in_array($mount->getMountPoint(), $mountPoints)); @@ -461,41 +456,40 @@ public function getByIdInPath(int $id, string $path): array { $mountsContainingFile = array_filter(array_map($this->mountManager->getMountFromMountInfo(...), $mountInfosContainingFiles)); } - 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'); - } + $userManager = Server::get(IUserManager::class); + $foundMount = false; + $nodes = []; + foreach ($mountsContainingFile as $mountInfo) { + $mount = $this->mountManager->getMountFromMountInfo($mountInfo); + if ($mount === null) { + continue; } - return []; - } + $foundMount = true; - $nodes = array_map(function (IMountPoint $mount) use ($id, $mountRoots) { - $rootInternalPath = $mountRoots[$mount->getStorageRootId()]; - $cacheEntry = $mount->getStorage()->getCache()->get($id); - if (!$cacheEntry) { - return null; + $storage = $mount->getStorage(); + if ($storage === null) { + continue; } + $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(), @@ -503,17 +497,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 */