aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/lib/Listener
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2024-03-08 13:08:57 -0100
committerMaxence Lange <maxence@artificial-owl.com>2024-03-08 13:09:22 -0100
commit467c84ec53511b008c7d6ac0888645a381787288 (patch)
treefe2f3471f74d70068630c9dcbba36452346d1c72 /apps/files/lib/Listener
parent9522ef849771392583b51a3f03812a429a666d01 (diff)
downloadnextcloud-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.php78
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;