diff options
author | Robin Appelman <robin@icewind.nl> | 2023-08-07 13:40:01 +0200 |
---|---|---|
committer | backportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com> | 2023-08-08 13:29:34 +0000 |
commit | 2c4535d2fdade15a25dcb22d014da77a9e5923fa (patch) | |
tree | f3c1cb3d29d6642900403ab6c5a0691e565ec0bb /apps/dav/lib/Connector/Sabre | |
parent | 963a783747229d775267cf260f3a6851ade53fab (diff) | |
download | nextcloud-server-2c4535d2fdade15a25dcb22d014da77a9e5923fa.tar.gz nextcloud-server-2c4535d2fdade15a25dcb22d014da77a9e5923fa.zip |
preload all requested metadata
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/dav/lib/Connector/Sabre')
-rw-r--r-- | apps/dav/lib/Connector/Sabre/FilesPlugin.php | 111 |
1 files changed, 53 insertions, 58 deletions
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index 547071cc6af..ae3caa29b91 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -46,6 +46,7 @@ use Psr\Log\LoggerInterface; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\IFile; +use Sabre\DAV\INode; use Sabre\DAV\PropFind; use Sabre\DAV\PropPatch; use Sabre\DAV\ServerPlugin; @@ -86,6 +87,15 @@ class FilesPlugin extends ServerPlugin { public const FILE_METADATA_SIZE = '{http://nextcloud.org/ns}file-metadata-size'; public const FILE_METADATA_GPS = '{http://nextcloud.org/ns}file-metadata-gps'; + public const ALL_METADATA_PROPS = [ + self::FILE_METADATA_SIZE => 'size', + self::FILE_METADATA_GPS => 'gps', + ]; + public const METADATA_MIMETYPES = [ + 'size' => 'image', + 'gps' => 'image', + ]; + /** Reference to main server object */ private ?Server $server = null; private Tree $tree; @@ -419,47 +429,28 @@ class FilesPlugin extends ServerPlugin { }); if ($this->config->getSystemValueBool('enable_file_metadata', true)) { - $propFind->handle(self::FILE_METADATA_SIZE, function () use ($node) { - if (!str_starts_with($node->getFileInfo()->getMimetype(), 'image')) { - return json_encode((object)[], JSON_THROW_ON_ERROR); - } - - if ($node->hasMetadata('size')) { - $sizeMetadata = $node->getMetadata('size'); - } else { - // 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)->debug('Inefficient fetching of metadata'); - } - - return $sizeMetadata->getValue(); - }); - - $propFind->handle(self::FILE_METADATA_GPS, function () use ($node) { - if (!str_starts_with($node->getFileInfo()->getMimetype(), 'image')) { - return json_encode((object)[], JSON_THROW_ON_ERROR); - } - - if ($node->hasMetadata('gps')) { - $gpsMetadata = $node->getMetadata('gps'); - } else { - // 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); - $gpsMetadata = $metadataManager->fetchMetadataFor('gps', [$node->getId()])[$node->getId()]; - - // TODO would be nice to display this in the profiler... - \OC::$server->get(LoggerInterface::class)->debug('Inefficient fetching of metadata'); - } - - return $gpsMetadata->getValue(); - }); + foreach (self::ALL_METADATA_PROPS as $prop => $meta) { + $propFind->handle($prop, function () use ($node, $meta) { + if ($node->getFileInfo()->getMimePart() !== self::METADATA_MIMETYPES[$meta]) { + return []; + } + + if ($node->hasMetadata($meta)) { + $metadata = $node->getMetadata($meta); + } else { + // 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); + $metadata = $metadataManager->fetchMetadataFor($meta, [$node->getId()])[$node->getId()]; + + // TODO would be nice to display this in the profiler... + \OC::$server->get(LoggerInterface::class)->debug('Inefficient fetching of metadata'); + } + + return $metadata->getValue(); + }); + } } } @@ -474,27 +465,31 @@ class FilesPlugin extends ServerPlugin { $requestProperties = $propFind->getRequestedProperties(); - // TODO detect dynamically which metadata groups are requested and - // preload all of them and not just size - if ($this->config->getSystemValueBool('enable_file_metadata', true) - && in_array(self::FILE_METADATA_SIZE, $requestProperties, true)) { - // Preloading of the metadata - $fileIds = []; - foreach ($node->getChildren() as $child) { - /** @var \OCP\Files\Node|Node $child */ - if (str_starts_with($child->getFileInfo()->getMimeType(), 'image/')) { - /** @var File $child */ - $fileIds[] = $child->getFileInfo()->getId(); + if ($this->config->getSystemValueBool('enable_file_metadata', true)) { + $requestedMetaData = []; + foreach ($requestProperties as $requestProperty) { + if (isset(self::ALL_METADATA_PROPS[$requestProperty])) { + $requestedMetaData[] = self::ALL_METADATA_PROPS[$requestProperty]; } } + $children = $node->getChildren(); + // Preloading of the metadata + /** @var IMetaDataManager $metadataManager */ $metadataManager = \OC::$server->get(IMetadataManager::class); - $preloadedMetadata = $metadataManager->fetchMetadataFor('size', $fileIds); - foreach ($node->getChildren() as $child) { - /** @var \OCP\Files\Node|Node $child */ - if (str_starts_with($child->getFileInfo()->getMimeType(), 'image')) { - /** @var File $child */ - $child->setMetadata('size', $preloadedMetadata[$child->getFileInfo()->getId()]); + + foreach ($requestedMetaData as $requestedMeta) { + $relevantMimeType = self::METADATA_MIMETYPES[$requestedMeta]; + $childrenForMeta = array_filter($children, function (INode $child) use ($relevantMimeType) { + return $child instanceof File && $child->getFileInfo()->getMimePart() === $relevantMimeType; + }); + $fileIds = array_map(function (File $child) { + return $child->getFileInfo()->getId(); + }, $childrenForMeta); + $preloadedMetadata = $metadataManager->fetchMetadataFor($requestedMeta, $fileIds); + + foreach ($childrenForMeta as $child) { + $child->setMetadata($requestedMeta, $preloadedMetadata[$child->getFileInfo()->getId()]); } } } |