From fe215a85754650cd2c085fe6ea813ce5365b6f0c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 12 Aug 2022 13:57:18 +0200 Subject: expose more metadata Signed-off-by: Louis Chemineau --- lib/Album/AlbumFile.php | 16 ++++++++++ lib/Sabre/Album/AlbumRoot.php | 4 +++ lib/Sabre/Album/PropFindPlugin.php | 64 ++++++++++++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/Album/AlbumFile.php b/lib/Album/AlbumFile.php index 99823650..babbddb0 100644 --- a/lib/Album/AlbumFile.php +++ b/lib/Album/AlbumFile.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace OCA\Photos\Album; +use OC\Metadata\FileMetadata; + class AlbumFile { private int $fileId; private string $name; @@ -30,6 +32,8 @@ class AlbumFile { private int $size; private int $mtime; private string $etag; + /** @var array */ + private array $metaData = []; public function __construct( int $fileId, @@ -70,4 +74,16 @@ class AlbumFile { public function getEtag() { return $this->etag; } + + public function setMetadata(string $key, FileMetadata $value): void { + $this->metaData[$key] = $value; + } + + public function hasMetadata(string $key): bool { + return isset($this->metaData[$key]); + } + + public function getMetadata(string $key): FileMetadata { + return $this->metaData[$key]; + } } diff --git a/lib/Sabre/Album/AlbumRoot.php b/lib/Sabre/Album/AlbumRoot.php index da7e6ab5..4cb132c0 100644 --- a/lib/Sabre/Album/AlbumRoot.php +++ b/lib/Sabre/Album/AlbumRoot.php @@ -114,4 +114,8 @@ class AlbumRoot implements ICollection, ICopyTarget { } throw new \Exception("Can't add file to album, only files from $uid can be added"); } + + public function getAlbum(): AlbumWithFiles { + return $this->album; + } } diff --git a/lib/Sabre/Album/PropFindPlugin.php b/lib/Sabre/Album/PropFindPlugin.php index 02b62096..68c306b2 100644 --- a/lib/Sabre/Album/PropFindPlugin.php +++ b/lib/Sabre/Album/PropFindPlugin.php @@ -23,28 +23,72 @@ declare(strict_types=1); namespace OCA\Photos\Sabre\Album; +use OC\Metadata\IMetadataManager; +use OCA\DAV\Connector\Sabre\FilesPlugin; +use OCP\IConfig; use Sabre\DAV\INode; use Sabre\DAV\PropFind; use Sabre\DAV\Server; use Sabre\DAV\ServerPlugin; class PropFindPlugin extends ServerPlugin { - private Server $server; + private IConfig $config; + private IMetadataManager $metadataManager; + private bool $metadataEnabled; - public function initialize(Server $server) { - $this->server = $server; - - $this->server->on('propFind', [$this, 'propFind']); + public function __construct(IConfig $config, IMetadataManager $metadataManager) { + $this->config = $config; + $this->metadataManager = $metadataManager; + $this->metadataEnabled = $this->config->getSystemValueBool('enable_file_metadata', true); } + public function initialize(Server $server) { + $server->on('propFind', [$this, 'propFind']); + } + public function propFind(PropFind $propFind, INode $node) { - if (!($node instanceof AlbumPhoto)) { - return; + if ($node instanceof AlbumPhoto) { + $propFind->handle('{http://nextcloud.org/ns}file-name', function () use ($node) { + return $node->getFile()->getName(); + }); + $propFind->handle(FilesPlugin::INTERNAL_FILEID_PROPERTYNAME, function () use ($node) { + return $node->getFile()->getFileId(); + }); + $propFind->handle(FilesPlugin::GETETAG_PROPERTYNAME, function () use ($node): string { + return $node->getETag(); + }); + + if ($this->metadataEnabled) { + $propFind->handle(FilesPlugin::FILE_METADATA_SIZE, function () use ($node) { + if (!str_starts_with($node->getFile()->getMimetype(), 'image')) { + return json_encode((object)[]); + } + + if ($node->getFile()->hasMetadata('size')) { + $sizeMetadata = $node->getFile()->getMetadata('size'); + } else { + $sizeMetadata = $this->metadataManager->fetchMetadataFor('size', [$node->getFile()->getFileId()])[$node->getFile()->getFileId()]; + } + + return json_encode((object)$sizeMetadata->getMetadata()); + }); + } } - $propFind->handle('{http://nextcloud.org/ns}file-name', function () use ($node) { - return $node->getFile()->getName(); - }); + if ($node instanceof AlbumRoot) { + // TODO detect dynamically which metadata groups are requested and + // preload all of them and not just size + if ($this->metadataEnabled && in_array(FilesPlugin::FILE_METADATA_SIZE, $propFind->getRequestedProperties(), true)) { + $fileIds = $node->getAlbum()->getFileIds(); + + $preloadedMetadata = $this->metadataManager->fetchMetadataFor('size', $fileIds); + foreach ($node->getAlbum()->getFiles() as $file) { + if (str_starts_with($file->getMimeType(), 'image')) { + $file->setMetadata('size', $preloadedMetadata[$file->getFileId()]); + } + } + } + } } } -- cgit v1.2.3