From 39ef0500d1d9b2d16540c7548100181e535f2a31 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 12 May 2022 09:23:26 +0200 Subject: Handle the move operation properly between shared calendars - Introduce a new CalendarObjectMovedEvent typed event dedicated for this operation - Handle the event in the activity backend and add new appropriate activity subjects Signed-off-by: Thomas Citharel --- apps/dav/composer/composer/autoload_classmap.php | 1 + apps/dav/composer/composer/autoload_static.php | 1 + apps/dav/lib/AppInfo/Application.php | 3 + apps/dav/lib/CalDAV/Activity/Backend.php | 102 +++++++++++++++++- apps/dav/lib/CalDAV/Activity/Provider/Event.php | 23 +++++ apps/dav/lib/CalDAV/Activity/Provider/Todo.php | 22 ++++ apps/dav/lib/CalDAV/CalDavBackend.php | 20 ++-- apps/dav/lib/CalDAV/Calendar.php | 2 +- apps/dav/lib/CalDAV/CalendarObject.php | 7 ++ apps/dav/lib/Events/CalendarObjectMovedEvent.php | 120 ++++++++++++++++++++++ apps/dav/lib/Listener/ActivityUpdaterListener.php | 22 +++- 11 files changed, 312 insertions(+), 11 deletions(-) create mode 100644 apps/dav/lib/Events/CalendarObjectMovedEvent.php (limited to 'apps/dav') diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 6f02140df40..c620de3fe4a 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -209,6 +209,7 @@ return array( 'OCA\\DAV\\Events\\CalendarMovedToTrashEvent' => $baseDir . '/../lib/Events/CalendarMovedToTrashEvent.php', 'OCA\\DAV\\Events\\CalendarObjectCreatedEvent' => $baseDir . '/../lib/Events/CalendarObjectCreatedEvent.php', 'OCA\\DAV\\Events\\CalendarObjectDeletedEvent' => $baseDir . '/../lib/Events/CalendarObjectDeletedEvent.php', + 'OCA\\DAV\\Events\\CalendarObjectMovedEvent' => $baseDir . '/../lib/Events/CalendarObjectMovedEvent.php', 'OCA\\DAV\\Events\\CalendarObjectMovedToTrashEvent' => $baseDir . '/../lib/Events/CalendarObjectMovedToTrashEvent.php', 'OCA\\DAV\\Events\\CalendarObjectRestoredEvent' => $baseDir . '/../lib/Events/CalendarObjectRestoredEvent.php', 'OCA\\DAV\\Events\\CalendarObjectUpdatedEvent' => $baseDir . '/../lib/Events/CalendarObjectUpdatedEvent.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 296b8a497c9..21f94cf71ce 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -224,6 +224,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\Events\\CalendarMovedToTrashEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarMovedToTrashEvent.php', 'OCA\\DAV\\Events\\CalendarObjectCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectCreatedEvent.php', 'OCA\\DAV\\Events\\CalendarObjectDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectDeletedEvent.php', + 'OCA\\DAV\\Events\\CalendarObjectMovedEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectMovedEvent.php', 'OCA\\DAV\\Events\\CalendarObjectMovedToTrashEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectMovedToTrashEvent.php', 'OCA\\DAV\\Events\\CalendarObjectRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectRestoredEvent.php', 'OCA\\DAV\\Events\\CalendarObjectUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/CalendarObjectUpdatedEvent.php', diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index e4eeed61dbe..10f0c52c79c 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -57,6 +57,7 @@ use OCA\DAV\Events\CalendarDeletedEvent; use OCA\DAV\Events\CalendarMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectCreatedEvent; use OCA\DAV\Events\CalendarObjectDeletedEvent; +use OCA\DAV\Events\CalendarObjectMovedEvent; use OCA\DAV\Events\CalendarObjectMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectRestoredEvent; use OCA\DAV\Events\CalendarObjectUpdatedEvent; @@ -154,6 +155,8 @@ class Application extends App implements IBootstrap { $context->registerEventListener(CalendarObjectUpdatedEvent::class, CalendarObjectReminderUpdaterListener::class); $context->registerEventListener(CalendarObjectDeletedEvent::class, ActivityUpdaterListener::class); $context->registerEventListener(CalendarObjectDeletedEvent::class, CalendarObjectReminderUpdaterListener::class); + $context->registerEventListener(CalendarObjectMovedEvent::class, ActivityUpdaterListener::class); + $context->registerEventListener(CalendarObjectMovedEvent::class, CalendarObjectReminderUpdaterListener::class); $context->registerEventListener(CalendarObjectMovedToTrashEvent::class, ActivityUpdaterListener::class); $context->registerEventListener(CalendarObjectMovedToTrashEvent::class, CalendarObjectReminderUpdaterListener::class); $context->registerEventListener(CalendarObjectRestoredEvent::class, ActivityUpdaterListener::class); diff --git a/apps/dav/lib/CalDAV/Activity/Backend.php b/apps/dav/lib/CalDAV/Activity/Backend.php index af2d790e10d..23256054b26 100644 --- a/apps/dav/lib/CalDAV/Activity/Backend.php +++ b/apps/dav/lib/CalDAV/Activity/Backend.php @@ -438,6 +438,11 @@ class Backend { $classification = $objectData['classification'] ?? CalDavBackend::CLASSIFICATION_PUBLIC; $object = $this->getObjectNameAndType($objectData); + + if (!$object) { + return; + } + $action = $action . '_' . $object['type']; if ($object['type'] === 'todo' && strpos($action, Event::SUBJECT_OBJECT_UPDATE) === 0 && $object['status'] === 'COMPLETED') { @@ -493,9 +498,104 @@ class Backend { } } + /** + * Creates activities when a calendar object was moved + */ + public function onMovedCalendarObject(array $sourceCalendarData, array $targetCalendarData, array $sourceShares, array $targetShares, array $objectData): void { + if (!isset($targetCalendarData['principaluri'])) { + return; + } + + $sourcePrincipal = explode('/', $sourceCalendarData['principaluri']); + $sourceOwner = array_pop($sourcePrincipal); + + $targetPrincipal = explode('/', $targetCalendarData['principaluri']); + $targetOwner = array_pop($targetPrincipal); + + if ($sourceOwner !== $targetOwner) { + $this->onTouchCalendarObject( + Event::SUBJECT_OBJECT_DELETE, + $sourceCalendarData, + $sourceShares, + $objectData + ); + $this->onTouchCalendarObject( + Event::SUBJECT_OBJECT_ADD, + $targetCalendarData, + $targetShares, + $objectData + ); + return; + } + + $currentUser = $this->userSession->getUser(); + if ($currentUser instanceof IUser) { + $currentUser = $currentUser->getUID(); + } else { + $currentUser = $targetOwner; + } + + $classification = $objectData['classification'] ?? CalDavBackend::CLASSIFICATION_PUBLIC; + $object = $this->getObjectNameAndType($objectData); + + if (!$object) { + return; + } + + $event = $this->activityManager->generateEvent(); + $event->setApp('dav') + ->setObject('calendar', (int) $targetCalendarData['id']) + ->setType($object['type'] === 'event' ? 'calendar_event' : 'calendar_todo') + ->setAuthor($currentUser); + + $users = $this->getUsersForShares(array_intersect($sourceShares, $targetShares)); + $users[] = $targetOwner; + + // Users for share can return the owner itself if the calendar is published + foreach (array_unique($users) as $user) { + if ($classification === CalDavBackend::CLASSIFICATION_PRIVATE && $user !== $targetOwner) { + // Private events are only shown to the owner + continue; + } + + $params = [ + 'actor' => $event->getAuthor(), + 'sourceCalendar' => [ + 'id' => (int) $sourceCalendarData['id'], + 'uri' => $sourceCalendarData['uri'], + 'name' => $sourceCalendarData['{DAV:}displayname'], + ], + 'targetCalendar' => [ + 'id' => (int) $targetCalendarData['id'], + 'uri' => $targetCalendarData['uri'], + 'name' => $targetCalendarData['{DAV:}displayname'], + ], + 'object' => [ + 'id' => $object['id'], + 'name' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $targetOwner ? 'Busy' : $object['name'], + 'classified' => $classification === CalDavBackend::CLASSIFICATION_CONFIDENTIAL && $user !== $targetOwner, + ], + ]; + + if ($object['type'] === 'event' && $this->appManager->isEnabledForUser('calendar')) { + $params['object']['link']['object_uri'] = $objectData['uri']; + $params['object']['link']['calendar_uri'] = $targetCalendarData['uri']; + $params['object']['link']['owner'] = $targetOwner; + } + + $event->setAffectedUser($user) + ->setSubject( + $user === $currentUser ? Event::SUBJECT_OBJECT_MOVE . '_' . $object['type'] . '_self' : Event::SUBJECT_OBJECT_MOVE . '_' . $object['type'], + $params + ); + + $this->activityManager->publish($event); + } + } + /** * @param array $objectData - * @return string[]|bool + * @return string[]|false */ protected function getObjectNameAndType(array $objectData) { $vObject = Reader::read($objectData['calendardata']); diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Event.php b/apps/dav/lib/CalDAV/Activity/Provider/Event.php index 3ed591219af..9ae04aadbba 100644 --- a/apps/dav/lib/CalDAV/Activity/Provider/Event.php +++ b/apps/dav/lib/CalDAV/Activity/Provider/Event.php @@ -40,6 +40,7 @@ use OCP\L10N\IFactory; class Event extends Base { public const SUBJECT_OBJECT_ADD = 'object_add'; public const SUBJECT_OBJECT_UPDATE = 'object_update'; + public const SUBJECT_OBJECT_MOVE = 'object_move'; public const SUBJECT_OBJECT_MOVE_TO_TRASH = 'object_move_to_trash'; public const SUBJECT_OBJECT_RESTORE = 'object_restore'; public const SUBJECT_OBJECT_DELETE = 'object_delete'; @@ -145,6 +146,10 @@ class Event extends Base { $subject = $this->l->t('{actor} updated event {event} in calendar {calendar}'); } elseif ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_event_self') { $subject = $this->l->t('You updated event {event} in calendar {calendar}'); + } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE . '_event') { + $subject = $this->l->t('{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}'); + } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE . '_event_self') { + $subject = $this->l->t('You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}'); } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE_TO_TRASH . '_event') { $subject = $this->l->t('{actor} deleted event {event} from calendar {calendar}'); } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE_TO_TRASH . '_event_self') { @@ -198,6 +203,24 @@ class Event extends Base { } } + if (isset($parameters['sourceCalendar']) && isset($parameters['targetCalendar'])) { + switch ($subject) { + case self::SUBJECT_OBJECT_MOVE . '_event': + return [ + 'actor' => $this->generateUserParameter($parameters['actor']), + 'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l), + 'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l), + 'event' => $this->generateClassifiedObjectParameter($parameters['object']), + ]; + case self::SUBJECT_OBJECT_MOVE . '_event_self': + return [ + 'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l), + 'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l), + 'event' => $this->generateClassifiedObjectParameter($parameters['object']), + ]; + } + } + // Legacy - Do NOT Remove unless necessary // Removing this will break parsing of activities that were created on // Nextcloud 12, so we should keep this as long as it's acceptable. diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php index a3ab81e38ae..4b2796aca53 100644 --- a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php +++ b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php @@ -69,6 +69,10 @@ class Todo extends Event { $subject = $this->l->t('{actor} reopened todo {todo} in list {calendar}'); } elseif ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self') { $subject = $this->l->t('You reopened todo {todo} in list {calendar}'); + } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE . '_todo') { + $subject = $this->l->t('{actor} moved todo {todo} from list {sourceCalendar} to list {targetCalendar}'); + } elseif ($event->getSubject() === self::SUBJECT_OBJECT_MOVE . '_todo_self') { + $subject = $this->l->t('You moved todo {todo} from list {sourceCalendar} to list {targetCalendar}'); } else { throw new \InvalidArgumentException(); } @@ -114,6 +118,24 @@ class Todo extends Event { } } + if (isset($parameters['sourceCalendar']) && isset($parameters['targetCalendar'])) { + switch ($subject) { + case self::SUBJECT_OBJECT_MOVE . '_todo': + return [ + 'actor' => $this->generateUserParameter($parameters['actor']), + 'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l), + 'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l), + 'todo' => $this->generateObjectParameter($parameters['object']), + ]; + case self::SUBJECT_OBJECT_MOVE . '_todo_self': + return [ + 'sourceCalendar' => $this->generateCalendarParameter($parameters['sourceCalendar'], $this->l), + 'targetCalendar' => $this->generateCalendarParameter($parameters['targetCalendar'], $this->l), + 'todo' => $this->generateObjectParameter($parameters['object']), + ]; + } + } + // Legacy - Do NOT Remove unless necessary // Removing this will break parsing of activities that were created on // Nextcloud 12, so we should keep this as long as it's acceptable. diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index f445382ce8c..3ab047d5183 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -52,6 +52,7 @@ use OCA\DAV\Events\CalendarDeletedEvent; use OCA\DAV\Events\CalendarMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectCreatedEvent; use OCA\DAV\Events\CalendarObjectDeletedEvent; +use OCA\DAV\Events\CalendarObjectMovedEvent; use OCA\DAV\Events\CalendarObjectMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectRestoredEvent; use OCA\DAV\Events\CalendarObjectUpdatedEvent; @@ -1341,13 +1342,14 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param int $sourceCalendarId * @param int $targetCalendarId * @param int $objectId - * @param string $principalUri + * @param string $oldPrincipalUri + * @param string $newPrincipalUri * @param int $calendarType * @return bool * @throws Exception */ - public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId, int $objectId, string $principalUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool { - $object = $this->getCalendarObjectById($principalUri, $objectId); + public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId, int $objectId, string $oldPrincipalUri, string $newPrincipalUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool { + $object = $this->getCalendarObjectById($oldPrincipalUri, $objectId); if (empty($object)) { return false; } @@ -1365,21 +1367,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $this->addChange($sourceCalendarId, $object['uri'], 1, $calendarType); $this->addChange($targetCalendarId, $object['uri'], 3, $calendarType); - $object = $this->getCalendarObjectById($principalUri, $objectId); + $object = $this->getCalendarObjectById($newPrincipalUri, $objectId); // Calendar Object wasn't found - possibly because it was deleted in the meantime by a different client if (empty($object)) { return false; } - $calendarRow = $this->getCalendarById($targetCalendarId); + $targetCalendarRow = $this->getCalendarById($targetCalendarId); // the calendar this event is being moved to does not exist any longer - if (empty($calendarRow)) { + if (empty($targetCalendarRow)) { return false; } if ($calendarType === self::CALENDAR_TYPE_CALENDAR) { - $shares = $this->getShares($targetCalendarId); - $this->dispatcher->dispatchTyped(new CalendarObjectUpdatedEvent($targetCalendarId, $calendarRow, $shares, $object)); + $sourceShares = $this->getShares($sourceCalendarId); + $targetShares = $this->getShares($targetCalendarId); + $sourceCalendarRow = $this->getCalendarById($sourceCalendarId); + $this->dispatcher->dispatchTyped(new CalendarObjectMovedEvent($sourceCalendarId, $sourceCalendarRow, $targetCalendarId, $targetCalendarRow, $sourceShares, $targetShares, $object)); } return true; } diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php index 79d2244b42c..806e99d8a05 100644 --- a/apps/dav/lib/CalDAV/Calendar.php +++ b/apps/dav/lib/CalDAV/Calendar.php @@ -450,7 +450,7 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable } try { - return $this->caldavBackend->moveCalendarObject($sourceNode->getCalendarId(), (int)$this->calendarInfo['id'], $sourceNode->getId(), $sourceNode->getPrincipalUri()); + return $this->caldavBackend->moveCalendarObject($sourceNode->getCalendarId(), (int)$this->calendarInfo['id'], $sourceNode->getId(), $sourceNode->getOwner(), $this->getOwner()); } catch (Exception $e) { $this->logger->error('Could not move calendar object: ' . $e->getMessage(), ['exception' => $e]); return false; diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php index c927254fba3..32bcff900c2 100644 --- a/apps/dav/lib/CalDAV/CalendarObject.php +++ b/apps/dav/lib/CalDAV/CalendarObject.php @@ -162,4 +162,11 @@ class CalendarObject extends \Sabre\CalDAV\CalendarObject { public function getPrincipalUri(): string { return $this->calendarInfo['principaluri']; } + + public function getOwner(): ?string { + if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) { + return $this->calendarInfo['{http://owncloud.org/ns}owner-principal']; + } + return parent::getOwner(); + } } diff --git a/apps/dav/lib/Events/CalendarObjectMovedEvent.php b/apps/dav/lib/Events/CalendarObjectMovedEvent.php new file mode 100644 index 00000000000..0143dad9a96 --- /dev/null +++ b/apps/dav/lib/Events/CalendarObjectMovedEvent.php @@ -0,0 +1,120 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCA\DAV\Events; + +use OCP\EventDispatcher\Event; + +/** + * Class CalendarObjectMovedEvent + * + * @package OCA\DAV\Events + * @since 25.0.0 + */ +class CalendarObjectMovedEvent extends Event { + private int $sourceCalendarId; + private array $sourceCalendarData; + private int $targetCalendarId; + private array $targetCalendarData; + private array $sourceShares; + private array $targetShares; + private array $objectData; + + /** + * @since 25.0.0 + */ + public function __construct(int $sourceCalendarId, + array $sourceCalendarData, + int $targetCalendarId, + array $targetCalendarData, + array $sourceShares, + array $targetShares, + array $objectData) { + parent::__construct(); + $this->sourceCalendarId = $sourceCalendarId; + $this->sourceCalendarData = $sourceCalendarData; + $this->targetCalendarId = $targetCalendarId; + $this->targetCalendarData = $targetCalendarData; + $this->sourceShares = $sourceShares; + $this->targetShares = $targetShares; + $this->objectData = $objectData; + } + + /** + * @return int + * @since 25.0.0 + */ + public function getSourceCalendarId(): int { + return $this->sourceCalendarId; + } + + /** + * @return array + * @since 25.0.0 + */ + public function getSourceCalendarData(): array { + return $this->sourceCalendarData; + } + + /** + * @return int + * @since 25.0.0 + */ + public function getTargetCalendarId(): int { + return $this->targetCalendarId; + } + + /** + * @return array + * @since 25.0.0 + */ + public function getTargetCalendarData(): array { + return $this->targetCalendarData; + } + + /** + * @return array + * @since 25.0.0 + */ + public function getSourceShares(): array { + return $this->sourceShares; + } + + /** + * @return array + * @since 25.0.0 + */ + public function getTargetShares(): array { + return $this->targetShares; + } + + /** + * @return array + * @since 25.0.0 + */ + public function getObjectData(): array { + return $this->objectData; + } +} diff --git a/apps/dav/lib/Listener/ActivityUpdaterListener.php b/apps/dav/lib/Listener/ActivityUpdaterListener.php index 371912ff035..ea3ec49c14d 100644 --- a/apps/dav/lib/Listener/ActivityUpdaterListener.php +++ b/apps/dav/lib/Listener/ActivityUpdaterListener.php @@ -32,6 +32,7 @@ use OCA\DAV\Events\CalendarDeletedEvent; use OCA\DAV\Events\CalendarMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectCreatedEvent; use OCA\DAV\Events\CalendarObjectDeletedEvent; +use OCA\DAV\Events\CalendarObjectMovedEvent; use OCA\DAV\Events\CalendarObjectMovedToTrashEvent; use OCA\DAV\Events\CalendarObjectRestoredEvent; use OCA\DAV\Events\CalendarObjectUpdatedEvent; @@ -173,7 +174,26 @@ class ActivityUpdaterListener implements IEventListener { ); $this->logger->debug( - sprintf('Activity generated for deleted calendar object %d', $event->getCalendarId()) + sprintf('Activity generated for updated calendar object in calendar %d', $event->getCalendarId()) + ); + } catch (Throwable $e) { + // Any error with activities shouldn't abort the calendar deletion, so we just log it + $this->logger->error('Error generating activity for a deleted calendar object: ' . $e->getMessage(), [ + 'exception' => $e, + ]); + } + } elseif ($event instanceof CalendarObjectMovedEvent) { + try { + $this->activityBackend->onMovedCalendarObject( + $event->getSourceCalendarData(), + $event->getTargetCalendarData(), + $event->getSourceShares(), + $event->getTargetShares(), + $event->getObjectData() + ); + + $this->logger->debug( + sprintf('Activity generated for moved calendar object from calendar %d to calendar %d', $event->getSourceCalendarId(), $event->getTargetCalendarId()) ); } catch (Throwable $e) { // Any error with activities shouldn't abort the calendar deletion, so we just log it -- cgit v1.2.3