3535namespace OCA \DAV \Connector \Sabre ;
3636
3737use OC \AppFramework \Http \Request ;
38- use OC \Metadata \ IMetadataManager ;
38+ use OC \FilesMetadata \ Model \ MetadataValueWrapper ;
3939use OCP \Constants ;
4040use OCP \Files \ForbiddenException ;
4141use OCP \Files \StorageNotAvailableException ;
42+ use OCP \FilesMetadata \Exceptions \FilesMetadataNotFoundException ;
43+ use OCP \FilesMetadata \IFilesMetadataManager ;
44+ use OCP \FilesMetadata \Model \IMetadataValueWrapper ;
4245use OCP \IConfig ;
4346use OCP \IPreview ;
4447use OCP \IRequest ;
4548use OCP \IUserSession ;
46- use Psr \Log \LoggerInterface ;
4749use Sabre \DAV \Exception \Forbidden ;
4850use Sabre \DAV \Exception \NotFound ;
4951use Sabre \DAV \IFile ;
50- use Sabre \DAV \INode ;
5152use Sabre \DAV \PropFind ;
5253use Sabre \DAV \PropPatch ;
5354use Sabre \DAV \Server ;
@@ -86,17 +87,6 @@ class FilesPlugin extends ServerPlugin {
8687 public const SUBFOLDER_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-folder-count ' ;
8788 public const SUBFILE_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-file-count ' ;
8889 public const FILE_METADATA_PREFIX = '{http://nextcloud.org/ns}metadata- ' ;
89- public const FILE_METADATA_SIZE = '{http://nextcloud.org/ns}file-metadata-size ' ;
90- public const FILE_METADATA_GPS = '{http://nextcloud.org/ns}file-metadata-gps ' ;
91-
92- public const ALL_METADATA_PROPS = [
93- self ::FILE_METADATA_SIZE => 'size ' ,
94- self ::FILE_METADATA_GPS => 'gps ' ,
95- ];
96- public const METADATA_MIMETYPES = [
97- 'size ' => 'image ' ,
98- 'gps ' => 'image ' ,
99- ];
10090
10191 /** Reference to main server object */
10292 private ?Server $ server = null ;
@@ -434,31 +424,6 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
434424 $ propFind ->handle (self ::UPLOAD_TIME_PROPERTYNAME , function () use ($ node ) {
435425 return $ node ->getFileInfo ()->getUploadTime ();
436426 });
437-
438- if ($ this ->config ->getSystemValueBool ('enable_file_metadata ' , true )) {
439- foreach (self ::ALL_METADATA_PROPS as $ prop => $ meta ) {
440- $ propFind ->handle ($ prop , function () use ($ node , $ meta ) {
441- if ($ node ->getFileInfo ()->getMimePart () !== self ::METADATA_MIMETYPES [$ meta ]) {
442- return [];
443- }
444-
445- if ($ node ->hasMetadata ($ meta )) {
446- $ metadata = $ node ->getMetadata ($ meta );
447- } else {
448- // This code path should not be called since we try to preload
449- // the metadata when loading the folder or the search results
450- // in one go
451- $ metadataManager = \OC ::$ server ->get (IMetadataManager::class);
452- $ metadata = $ metadataManager ->fetchMetadataFor ($ meta , [$ node ->getId ()])[$ node ->getId ()];
453-
454- // TODO would be nice to display this in the profiler...
455- \OC ::$ server ->get (LoggerInterface::class)->debug ('Inefficient fetching of metadata ' );
456- }
457-
458- return $ metadata ->getValue ();
459- });
460- }
461- }
462427 }
463428
464429 if ($ node instanceof Directory) {
@@ -472,39 +437,6 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
472437
473438 $ requestProperties = $ propFind ->getRequestedProperties ();
474439
475- $ requestedMetaData = [];
476- foreach ($ requestProperties as $ requestProperty ) {
477- if (isset (self ::ALL_METADATA_PROPS [$ requestProperty ])) {
478- $ requestedMetaData [] = self ::ALL_METADATA_PROPS [$ requestProperty ];
479- }
480- }
481- if (
482- $ this ->config ->getSystemValueBool ('enable_file_metadata ' , true ) &&
483- $ propFind ->getDepth () === 1 &&
484- $ requestedMetaData
485- ) {
486- $ children = $ node ->getChildren ();
487- // Preloading of the metadata
488-
489- /** @var IMetaDataManager $metadataManager */
490- $ metadataManager = \OC ::$ server ->get (IMetadataManager::class);
491-
492- foreach ($ requestedMetaData as $ requestedMeta ) {
493- $ relevantMimeType = self ::METADATA_MIMETYPES [$ requestedMeta ];
494- $ childrenForMeta = array_filter ($ children , function (INode $ child ) use ($ relevantMimeType ) {
495- return $ child instanceof File && $ child ->getFileInfo ()->getMimePart () === $ relevantMimeType ;
496- });
497- $ fileIds = array_map (function (File $ child ) {
498- return $ child ->getFileInfo ()->getId ();
499- }, $ childrenForMeta );
500- $ preloadedMetadata = $ metadataManager ->fetchMetadataFor ($ requestedMeta , $ fileIds );
501-
502- foreach ($ childrenForMeta as $ child ) {
503- $ child ->setMetadata ($ requestedMeta , $ preloadedMetadata [$ child ->getFileInfo ()->getId ()]);
504- }
505- }
506- }
507-
508440 if (in_array (self ::SUBFILE_COUNT_PROPERTYNAME , $ requestProperties , true )
509441 || in_array (self ::SUBFOLDER_COUNT_PROPERTYNAME , $ requestProperties , true )) {
510442 $ nbFiles = 0 ;
@@ -590,6 +522,59 @@ public function handleUpdateProperties($path, PropPatch $propPatch) {
590522 $ node ->setCreationTime ((int ) $ time );
591523 return true ;
592524 });
525+
526+
527+ /** @var IFilesMetadataManager */
528+ $ filesMetadataManager = \OCP \Server::get (IFilesMetadataManager::class);
529+ $ knownMetadata = $ filesMetadataManager ->getKnownMetadata ();
530+ $ metadata = $ filesMetadataManager ->getMetadata ((int )$ node ->getFileId (), true );
531+
532+ // TODO: test different types
533+ // 1. cast value
534+ foreach ($ propPatch ->getRemainingMutations () as $ mutation ) {
535+ if (!str_starts_with ($ mutation , self ::FILE_METADATA_PREFIX )) {
536+ continue ;
537+ }
538+
539+ $ propPatch ->handle ($ mutation , function (mixed $ value ) use ($ knownMetadata , $ metadata , $ mutation , $ filesMetadataManager ): bool {
540+ $ metadataKey = substr ($ mutation , strlen (self ::FILE_METADATA_PREFIX ));
541+
542+ // If the metadata is unknown, it defaults to string.
543+ try {
544+ $ type = $ knownMetadata ->getType ($ metadataKey );
545+ } catch (FilesMetadataNotFoundException ) {
546+ $ type = IMetadataValueWrapper::TYPE_STRING ;
547+ }
548+
549+ switch ($ type ) {
550+ case IMetadataValueWrapper::TYPE_STRING :
551+ $ metadata ->setString ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
552+ break ;
553+ case IMetadataValueWrapper::TYPE_INT :
554+ $ metadata ->setInt ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
555+ break ;
556+ case IMetadataValueWrapper::TYPE_FLOAT :
557+ $ metadata ->setFloat ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
558+ break ;
559+ case IMetadataValueWrapper::TYPE_BOOL :
560+ $ metadata ->setBool ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
561+ break ;
562+ case IMetadataValueWrapper::TYPE_ARRAY :
563+ $ metadata ->setArray ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
564+ break ;
565+ case IMetadataValueWrapper::TYPE_STRING_LIST :
566+ $ metadata ->setStringList ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
567+ break ;
568+ case IMetadataValueWrapper::TYPE_INT_LIST :
569+ $ metadata ->setIntList ($ metadataKey , $ value , $ knownMetadata ->isIndex ($ metadataKey ));
570+ break ;
571+ }
572+
573+ $ filesMetadataManager ->saveMetadata ($ metadata );
574+ return true ;
575+ });
576+ }
577+
593578 /**
594579 * Disable modification of the displayname property for files and
595580 * folders via PROPPATCH. See PROPFIND for more information.
0 commit comments