summaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/Connector/Sabre
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2023-08-07 13:40:01 +0200
committerbackportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com>2023-08-08 13:29:34 +0000
commit2c4535d2fdade15a25dcb22d014da77a9e5923fa (patch)
treef3c1cb3d29d6642900403ab6c5a0691e565ec0bb /apps/dav/lib/Connector/Sabre
parent963a783747229d775267cf260f3a6851ade53fab (diff)
downloadnextcloud-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.php111
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()]);
}
}
}