diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2024-03-08 13:08:57 -0100 |
---|---|---|
committer | Maxence Lange <maxence@artificial-owl.com> | 2024-03-08 13:09:22 -0100 |
commit | 467c84ec53511b008c7d6ac0888645a381787288 (patch) | |
tree | fe2f3471f74d70068630c9dcbba36452346d1c72 /apps/files/lib/Listener | |
parent | 9522ef849771392583b51a3f03812a429a666d01 (diff) | |
download | nextcloud-server-467c84ec53511b008c7d6ac0888645a381787288.tar.gz nextcloud-server-467c84ec53511b008c7d6ac0888645a381787288.zip |
feat(files): copy live photos
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'apps/files/lib/Listener')
-rw-r--r-- | apps/files/lib/Listener/SyncLivePhotosListener.php | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/apps/files/lib/Listener/SyncLivePhotosListener.php b/apps/files/lib/Listener/SyncLivePhotosListener.php index ea63c08f94d..8f8234428d6 100644 --- a/apps/files/lib/Listener/SyncLivePhotosListener.php +++ b/apps/files/lib/Listener/SyncLivePhotosListener.php @@ -29,9 +29,13 @@ use OCA\Files_Trashbin\Trash\ITrashItem; use OCA\Files_Trashbin\Trash\ITrashManager; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\Exceptions\AbortedEventException; use OCP\Files\Cache\CacheEntryRemovedEvent; +use OCP\Files\Events\Node\AbstractNodesEvent; +use OCP\Files\Events\Node\BeforeNodeCopiedEvent; use OCP\Files\Events\Node\BeforeNodeDeletedEvent; use OCP\Files\Events\Node\BeforeNodeRenamedEvent; +use OCP\Files\Events\Node\NodeCopiedEvent; use OCP\Files\Folder; use OCP\Files\Node; use OCP\Files\NotFoundException; @@ -44,7 +48,7 @@ use OCP\IUserSession; * @template-implements IEventListener<Event> */ class SyncLivePhotosListener implements IEventListener { - /** @var Array<int, string> */ + /** @var Array<int> */ private array $pendingRenames = []; /** @var Array<int, bool> */ private array $pendingDeletion = []; @@ -65,7 +69,6 @@ class SyncLivePhotosListener implements IEventListener { } $peerFile = null; - if ($event instanceof BeforeNodeRenamedEvent) { $peerFile = $this->getLivePhotoPeer($event->getSource()->getId()); } elseif ($event instanceof BeforeNodeRestoredEvent) { @@ -74,6 +77,8 @@ class SyncLivePhotosListener implements IEventListener { $peerFile = $this->getLivePhotoPeer($event->getNode()->getId()); } elseif ($event instanceof CacheEntryRemovedEvent) { $peerFile = $this->getLivePhotoPeer($event->getFileId()); + } elseif ($event instanceof BeforeNodeCopiedEvent || $event instanceof NodeCopiedEvent) { + $peerFile = $this->getLivePhotoPeer($event->getSource()->getId()); } if ($peerFile === null) { @@ -81,13 +86,17 @@ class SyncLivePhotosListener implements IEventListener { } if ($event instanceof BeforeNodeRenamedEvent) { - $this->handleMove($event, $peerFile); + $this->handleMove($event, $peerFile, false); } elseif ($event instanceof BeforeNodeDeletedEvent) { $this->handleDeletion($event, $peerFile); } elseif ($event instanceof CacheEntryRemovedEvent) { $peerFile->delete(); } elseif ($event instanceof BeforeNodeRestoredEvent) { $this->handleRestore($event, $peerFile); + } elseif ($event instanceof BeforeNodeCopiedEvent) { + $this->handleMove($event, $peerFile, true); + } elseif ($event instanceof NodeCopiedEvent) { + $this->handleCopy($event, $peerFile); } } @@ -98,44 +107,79 @@ class SyncLivePhotosListener implements IEventListener { * of pending renames inside the 'pendingRenames' property, * to prevent infinite recursive. */ - private function handleMove(BeforeNodeRenamedEvent $event, Node $peerFile): void { + private function handleMove(AbstractNodesEvent $event, Node $peerFile, bool $prepForCopyOnly = false): void { + if (!($event instanceof BeforeNodeCopiedEvent) && + !($event instanceof BeforeNodeRenamedEvent)) { + return; + } + $sourceFile = $event->getSource(); $targetFile = $event->getTarget(); $targetParent = $targetFile->getParent(); $sourceExtension = $sourceFile->getExtension(); $peerFileExtension = $peerFile->getExtension(); $targetName = $targetFile->getName(); - $targetPath = $targetFile->getPath(); - if (!str_ends_with($targetName, ".".$sourceExtension)) { - $event->abortOperation(new NotPermittedException("Cannot change the extension of a Live Photo")); + if (!str_ends_with($targetName, "." . $sourceExtension)) { + throw new AbortedEventException('Cannot change the extension of a Live Photo'); } try { $targetParent->get($targetName); - $event->abortOperation(new NotPermittedException("A file already exist at destination path of the Live Photo")); - } catch (NotFoundException $ex) { + throw new AbortedEventException('A file already exist at destination path of the Live Photo'); + } catch (NotFoundException) { } $peerTargetName = substr($targetName, 0, -strlen($sourceExtension)) . $peerFileExtension; try { $targetParent->get($peerTargetName); - $event->abortOperation(new NotPermittedException("A file already exist at destination path of the Live Photo")); - } catch (NotFoundException $ex) { + throw new AbortedEventException('A file already exist at destination path of the Live Photo'); + } catch (NotFoundException) { } // in case the rename was initiated from this listener, we stop right now - if (array_key_exists($peerFile->getId(), $this->pendingRenames)) { + if ($prepForCopyOnly || in_array($peerFile->getId(), $this->pendingRenames)) { return; } - $this->pendingRenames[$sourceFile->getId()] = $targetPath; + $this->pendingRenames[] = $sourceFile->getId(); try { $peerFile->move($targetParent->getPath() . '/' . $peerTargetName); } catch (\Throwable $ex) { - $event->abortOperation($ex); + throw new AbortedEventException($ex->getMessage()); } - unset($this->pendingRenames[$sourceFile->getId()]); + + array_diff($this->pendingRenames, [$sourceFile->getId()]); + } + + + /** + * handle copy, we already know if it is doable from BeforeNodeCopiedEvent, so we just copy the linked file + * + * @param NodeCopiedEvent $event + * @param Node $peerFile + */ + private function handleCopy(NodeCopiedEvent $event, Node $peerFile): void { + $sourceFile = $event->getSource(); + $sourceExtension = $sourceFile->getExtension(); + $peerFileExtension = $peerFile->getExtension(); + $targetFile = $event->getTarget(); + $targetParent = $targetFile->getParent(); + $targetName = $targetFile->getName(); + $peerTargetName = substr($targetName, 0, -strlen($sourceExtension)) . $peerFileExtension; + + /** + * let's use freshly set variable. + * we copy the file and get its id. We already have the id of the current copy + * We have everything to update metadata and keep the link between the 2 copies. + */ + $newPeerFile = $peerFile->copy($targetParent->getPath() . '/' . $peerTargetName); + $targetMetadata = $this->filesMetadataManager->getMetadata($targetFile->getId(), true); + $targetMetadata->setString('files-live-photo', (string)$newPeerFile->getId()); + $this->filesMetadataManager->saveMetadata($targetMetadata); + $peerMetadata = $this->filesMetadataManager->getMetadata($newPeerFile->getId(), true); + $peerMetadata->setString('files-live-photo', (string)$targetFile->getId()); + $this->filesMetadataManager->saveMetadata($peerMetadata); } /** @@ -152,14 +196,14 @@ class SyncLivePhotosListener implements IEventListener { unset($this->pendingDeletion[$peerFile->getId()]); return; } else { - $event->abortOperation(new NotPermittedException("Cannot delete the video part of a live photo")); + throw new AbortedEventException("Cannot delete the video part of a live photo"); } } else { $this->pendingDeletion[$deletedFile->getId()] = true; try { $peerFile->delete(); } catch (\Throwable $ex) { - $event->abortOperation($ex); + throw new AbortedEventException($ex->getMessage()); } } return; |