diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php index 8e70752c63580..6c37998499524 100644 --- a/apps/dav/lib/Connector/Sabre/File.php +++ b/apps/dav/lib/Connector/Sabre/File.php @@ -82,7 +82,7 @@ class File extends Node implements IFile { protected IL10N $l10n; /** @var array */ - private array $metadata; + private array $metadata = []; /** * Sets up the node, expects a full path name diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index b68976f6ed890..dedf2452d99d2 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -42,6 +42,7 @@ use OCP\IPreview; use OCP\IRequest; use OCP\IUserSession; +use Psr\Log\LoggerInterface; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\IFile; @@ -448,8 +449,14 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) if ($node->hasMetadata('size')) { $sizeMetadata = $node->getMetadata('size'); } else { - // TODO fetch metadata manually in that case - // or is that always the case? + // This code path should not be called since we try to preload + // the metadata when loading the folder or the search results + // in one go + $metadataManager = \OC::$server->get(IMetadataManager::class); + $sizeMetadata = $metadataManager->fetchMetadataFor('size', [$node->getId()])[$node->getId()]; + + // TODO would be nice to display this in the profiler... + \OC::$server->get(LoggerInterface::class)->warning('Inefficient fetching of metadata'); } return json_encode($sizeMetadata->getMetadata()); diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php index 7d47205ea5865..d5701e52fa8e3 100644 --- a/apps/dav/lib/Files/FileSearchBackend.php +++ b/apps/dav/lib/Files/FileSearchBackend.php @@ -30,8 +30,10 @@ use OC\Files\Search\SearchOrder; use OC\Files\Search\SearchQuery; use OC\Files\View; +use OC\Metadata\IMetadataManager; use OCA\DAV\Connector\Sabre\CachingTree; use OCA\DAV\Connector\Sabre\Directory; +use OCA\DAV\Connector\Sabre\File; use OCA\DAV\Connector\Sabre\FilesPlugin; use OCA\DAV\Connector\Sabre\TagsPlugin; use OCP\Files\Cache\ICacheEntry; @@ -44,6 +46,7 @@ use OCP\IUser; use OCP\Share\IManager; use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\INode; use SearchDAV\Backend\ISearchBackend; use SearchDAV\Backend\SearchPropertyDefinition; use SearchDAV\Backend\SearchResult; @@ -137,6 +140,32 @@ public function getPropertyDefinitionsForScope($href, $path) { ]; } + /** + * @param INode[] $nodes + * @param string[] $requestProperties + */ + public function preloadPropertyFor(array $nodes, array $requestProperties): void { + if (in_array(FilesPlugin::FILE_METADATA_SIZE, $requestProperties, true)) { + // Preloading of the metadata + $fileIds = []; + foreach ($nodes as $node) { + if (str_starts_with($node->getFileInfo()->getMimeType(), 'image')) { + /** @var File $node */ + $fileIds[] = $node->getFileInfo()->getId(); + } + } + /** @var IMetaDataManager $metadataManager */ + $metadataManager = \OC::$server->get(IMetadataManager::class); + $preloadedMetadata = $metadataManager->fetchMetadataFor('size', $fileIds); + foreach ($nodes as $node) { + if (str_starts_with($node->getFileInfo()->getMimeType(), 'image')) { + /** @var File $child */ + $node->setMetadata('size', $preloadedMetadata[$node->getFileInfo()->getId()]); + } + } + } + } + /** * @param Query $search * @return SearchResult[] @@ -254,8 +283,6 @@ private function getSearchResultProperty(SearchResult $result, SearchPropertyDef return $node->getSize(); case FilesPlugin::INTERNAL_FILEID_PROPERTYNAME: return $node->getInternalFileId(); - case FilesPlugin::FILE_METADATA_SIZE: - return $node->getMetadata('size'); default: return null; } diff --git a/apps/dav/lib/Files/LazySearchBackend.php b/apps/dav/lib/Files/LazySearchBackend.php index d84c11306e360..bed91cdeffa8b 100644 --- a/apps/dav/lib/Files/LazySearchBackend.php +++ b/apps/dav/lib/Files/LazySearchBackend.php @@ -22,6 +22,7 @@ */ namespace OCA\DAV\Files; +use Sabre\DAV\INode; use SearchDAV\Backend\ISearchBackend; use SearchDAV\Query\Query; @@ -66,4 +67,10 @@ public function search(Query $query) { return []; } } + + public function preloadPropertyFor(array $nodes, array $requestProperties): void { + if ($this->backend) { + $this->backend->preloadPropertyFor($nodes, $requestProperties); + } + } }