From 4c0263b78ab7cac9e7e2af48f4a4053c1a02ed25 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 29 Nov 2016 16:21:36 +0100 Subject: [PATCH] Move event and todo parsing to new API Signed-off-by: Joas Schilling --- apps/dav/appinfo/info.xml | 2 + apps/dav/lib/AppInfo/Application.php | 12 +- apps/dav/lib/CalDAV/Activity/Backend.php | 71 ++--- apps/dav/lib/CalDAV/Activity/Extension.php | 261 ------------------ .../lib/CalDAV/Activity/Provider/Event.php | 212 ++++++++++++++ .../dav/lib/CalDAV/Activity/Provider/Todo.php | 114 ++++++++ .../unit/CalDAV/Activity/BackendTest.php | 34 +-- 7 files changed, 387 insertions(+), 319 deletions(-) delete mode 100644 apps/dav/lib/CalDAV/Activity/Extension.php create mode 100644 apps/dav/lib/CalDAV/Activity/Provider/Event.php create mode 100644 apps/dav/lib/CalDAV/Activity/Provider/Todo.php diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index 5335e020344..f362c882f97 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -46,6 +46,8 @@ OCA\DAV\CalDAV\Activity\Provider\Calendar + OCA\DAV\CalDAV\Activity\Provider\Event + OCA\DAV\CalDAV\Activity\Provider\Todo diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index 7c32fda8f5a..669c52d1489 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -26,6 +26,7 @@ namespace OCA\DAV\AppInfo; use OCA\DAV\CalDAV\Activity\Backend; use OCA\DAV\CalDAV\Activity\Extension; +use OCA\DAV\CalDAV\Activity\Provider\Event; use OCA\DAV\CalDAV\BirthdayService; use OCA\DAV\Capabilities; use OCA\DAV\CardDAV\ContactsManager; @@ -146,11 +147,11 @@ class Application extends App { /** @var Backend $backend */ $backend = $this->getContainer()->query(Backend::class); - $subject = Extension::SUBJECT_OBJECT_ADD; + $subject = Event::SUBJECT_OBJECT_ADD; if ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject') { - $subject = Extension::SUBJECT_OBJECT_UPDATE; + $subject = Event::SUBJECT_OBJECT_UPDATE; } else if ($eventName === '\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject') { - $subject = Extension::SUBJECT_OBJECT_DELETE; + $subject = Event::SUBJECT_OBJECT_DELETE; } $backend->onTouchCalendarObject( $subject, @@ -162,11 +163,6 @@ class Application extends App { $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject', $listener); $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject', $listener); $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject', $listener); - - $aM = $this->getContainer()->getServer()->getActivityManager(); - $aM->registerExtension(function() { - return $this->getContainer()->query(Extension::class); - }); } public function getSyncService() { diff --git a/apps/dav/lib/CalDAV/Activity/Backend.php b/apps/dav/lib/CalDAV/Activity/Backend.php index 6a557fef7bd..953fdcea832 100644 --- a/apps/dav/lib/CalDAV/Activity/Backend.php +++ b/apps/dav/lib/CalDAV/Activity/Backend.php @@ -22,6 +22,8 @@ namespace OCA\DAV\CalDAV\Activity; +use OCA\DAV\CalDAV\Activity\Provider\Calendar; +use OCA\DAV\CalDAV\Activity\Provider\Event; use OCP\Activity\IEvent; use OCP\Activity\IManager as IActivityManager; use OCP\IGroup; @@ -63,7 +65,7 @@ class Backend { * @param array $calendarData */ public function onCalendarAdd(array $calendarData) { - $this->triggerCalendarActivity(Extension::SUBJECT_ADD, $calendarData); + $this->triggerCalendarActivity(Calendar::SUBJECT_ADD, $calendarData); } /** @@ -74,7 +76,7 @@ class Backend { * @param array $properties */ public function onCalendarUpdate(array $calendarData, array $shares, array $properties) { - $this->triggerCalendarActivity(Extension::SUBJECT_UPDATE, $calendarData, $shares, $properties); + $this->triggerCalendarActivity(Calendar::SUBJECT_UPDATE, $calendarData, $shares, $properties); } /** @@ -84,7 +86,7 @@ class Backend { * @param array $shares */ public function onCalendarDelete(array $calendarData, array $shares) { - $this->triggerCalendarActivity(Extension::SUBJECT_DELETE, $calendarData, $shares); + $this->triggerCalendarActivity(Calendar::SUBJECT_DELETE, $calendarData, $shares); } /** @@ -112,8 +114,8 @@ class Backend { $event = $this->activityManager->generateEvent(); $event->setApp('dav') - ->setObject(Extension::CALENDAR, (int) $calendarData['id']) - ->setType(Extension::CALENDAR) + ->setObject('calendar', (int) $calendarData['id']) + ->setType('calendar') ->setAuthor($currentUser); $changedVisibleInformation = array_intersect([ @@ -121,7 +123,7 @@ class Backend { '{http://apple.com/ns/ical/}calendar-color' ], array_keys($changedProperties)); - if (empty($shares) || ($action === Extension::SUBJECT_UPDATE && empty($changedVisibleInformation))) { + if (empty($shares) || ($action === Calendar::SUBJECT_UPDATE && empty($changedVisibleInformation))) { $users = [$owner]; } else { $users = $this->getUsersForShares($shares); @@ -162,8 +164,8 @@ class Backend { $event = $this->activityManager->generateEvent(); $event->setApp('dav') - ->setObject(Extension::CALENDAR, (int) $calendarData['id']) - ->setType(Extension::CALENDAR) + ->setObject('calendar', (int) $calendarData['id']) + ->setType('calendar') ->setAuthor($currentUser); foreach ($remove as $principal) { @@ -179,8 +181,8 @@ class Backend { $principal[2], $event, $calendarData, - Extension::SUBJECT_UNSHARE_USER, - Extension::SUBJECT_DELETE . '_self' + Calendar::SUBJECT_UNSHARE_USER, + Calendar::SUBJECT_DELETE . '_self' ); if ($owner !== $principal[2]) { @@ -190,15 +192,15 @@ class Backend { ]; if ($owner === $event->getAuthor()) { - $subject = Extension::SUBJECT_UNSHARE_USER . '_you'; + $subject = Calendar::SUBJECT_UNSHARE_USER . '_you'; } else if ($principal[2] === $event->getAuthor()) { - $subject = Extension::SUBJECT_UNSHARE_USER . '_self'; + $subject = Calendar::SUBJECT_UNSHARE_USER . '_self'; } else { $event->setAffectedUser($event->getAuthor()) - ->setSubject(Extension::SUBJECT_UNSHARE_USER . '_you', $parameters); + ->setSubject(Calendar::SUBJECT_UNSHARE_USER . '_you', $parameters); $this->activityManager->publish($event); - $subject = Extension::SUBJECT_UNSHARE_USER . '_by'; + $subject = Calendar::SUBJECT_UNSHARE_USER . '_by'; $parameters[] = $event->getAuthor(); } @@ -207,7 +209,7 @@ class Backend { $this->activityManager->publish($event); } } else if ($principal[1] === 'groups') { - $this->triggerActivityGroup($principal[2], $event, $calendarData, Extension::SUBJECT_UNSHARE_USER); + $this->triggerActivityGroup($principal[2], $event, $calendarData, Calendar::SUBJECT_UNSHARE_USER); $parameters = [ $principal[2], @@ -215,13 +217,13 @@ class Backend { ]; if ($owner === $event->getAuthor()) { - $subject = Extension::SUBJECT_UNSHARE_GROUP . '_you'; + $subject = Calendar::SUBJECT_UNSHARE_GROUP . '_you'; } else { $event->setAffectedUser($event->getAuthor()) - ->setSubject(Extension::SUBJECT_UNSHARE_GROUP . '_you', $parameters); + ->setSubject(Calendar::SUBJECT_UNSHARE_GROUP . '_you', $parameters); $this->activityManager->publish($event); - $subject = Extension::SUBJECT_UNSHARE_GROUP . '_by'; + $subject = Calendar::SUBJECT_UNSHARE_GROUP . '_by'; $parameters[] = $event->getAuthor(); } @@ -244,7 +246,7 @@ class Backend { $principal = explode('/', $parts[1]); if ($principal[1] === 'users') { - $this->triggerActivityUser($principal[2], $event, $calendarData, Extension::SUBJECT_SHARE_USER); + $this->triggerActivityUser($principal[2], $event, $calendarData, Calendar::SUBJECT_SHARE_USER); if ($owner !== $principal[2]) { $parameters = [ @@ -253,13 +255,13 @@ class Backend { ]; if ($owner === $event->getAuthor()) { - $subject = Extension::SUBJECT_SHARE_USER . '_you'; + $subject = Calendar::SUBJECT_SHARE_USER . '_you'; } else { $event->setAffectedUser($event->getAuthor()) - ->setSubject(Extension::SUBJECT_SHARE_USER . '_you', $parameters); + ->setSubject(Calendar::SUBJECT_SHARE_USER . '_you', $parameters); $this->activityManager->publish($event); - $subject = Extension::SUBJECT_SHARE_USER . '_by'; + $subject = Calendar::SUBJECT_SHARE_USER . '_by'; $parameters[] = $event->getAuthor(); } @@ -268,7 +270,7 @@ class Backend { $this->activityManager->publish($event); } } else if ($principal[1] === 'groups') { - $this->triggerActivityGroup($principal[2], $event, $calendarData, Extension::SUBJECT_SHARE_USER); + $this->triggerActivityGroup($principal[2], $event, $calendarData, Calendar::SUBJECT_SHARE_USER); $parameters = [ $principal[2], @@ -276,13 +278,13 @@ class Backend { ]; if ($owner === $event->getAuthor()) { - $subject = Extension::SUBJECT_SHARE_GROUP . '_you'; + $subject = Calendar::SUBJECT_SHARE_GROUP . '_you'; } else { $event->setAffectedUser($event->getAuthor()) - ->setSubject(Extension::SUBJECT_SHARE_GROUP . '_you', $parameters); + ->setSubject(Calendar::SUBJECT_SHARE_GROUP . '_you', $parameters); $this->activityManager->publish($event); - $subject = Extension::SUBJECT_SHARE_GROUP . '_by'; + $subject = Calendar::SUBJECT_SHARE_GROUP . '_by'; $parameters[] = $event->getAuthor(); } @@ -379,16 +381,16 @@ class Backend { $object = $this->getObjectNameAndType($objectData); $action = $action . '_' . $object['type']; - if ($object['type'] === 'todo' && strpos($action, Extension::SUBJECT_OBJECT_UPDATE) === 0 && $object['status'] === 'COMPLETED') { + if ($object['type'] === 'todo' && strpos($action, Event::SUBJECT_OBJECT_UPDATE) === 0 && $object['status'] === 'COMPLETED') { $action .= '_completed'; - } else if ($object['type'] === 'todo' && strpos($action, Extension::SUBJECT_OBJECT_UPDATE) === 0 && $object['status'] === 'NEEDS-ACTION') { + } else if ($object['type'] === 'todo' && strpos($action, Event::SUBJECT_OBJECT_UPDATE) === 0 && $object['status'] === 'NEEDS-ACTION') { $action .= '_needs_action'; } $event = $this->activityManager->generateEvent(); $event->setApp('dav') - ->setObject(Extension::CALENDAR, (int) $calendarData['id']) - ->setType($object['type'] === 'event' ? Extension::CALENDAR_EVENT : Extension::CALENDAR_TODO) + ->setObject('calendar', (int) $calendarData['id']) + ->setType($object['type'] === 'event' ? 'calendar_event' : 'calendar_todo') ->setAuthor($currentUser); $users = $this->getUsersForShares($shares); @@ -401,7 +403,10 @@ class Backend { [ $currentUser, $calendarData['{DAV:}displayname'], - $object['name'], + [ + 'id' => $object['id'], + 'name' => $object['name'], + ], ] ); $this->activityManager->publish($event); @@ -428,9 +433,9 @@ class Backend { } if ($componentType === 'VEVENT') { - return ['name' => (string) $component->SUMMARY, 'type' => 'event']; + return ['id' => (string) $component->UID, 'name' => (string) $component->SUMMARY, 'type' => 'event']; } - return ['name' => (string) $component->SUMMARY, 'type' => 'todo', 'status' => (string) $component->STATUS]; + return ['id' => (string) $component->UID, 'name' => (string) $component->SUMMARY, 'type' => 'todo', 'status' => (string) $component->STATUS]; } /** diff --git a/apps/dav/lib/CalDAV/Activity/Extension.php b/apps/dav/lib/CalDAV/Activity/Extension.php deleted file mode 100644 index b6d4e23b71d..00000000000 --- a/apps/dav/lib/CalDAV/Activity/Extension.php +++ /dev/null @@ -1,261 +0,0 @@ - - * - * @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\CalDAV\Activity; - -use OCP\Activity\IExtension; -use OCP\IURLGenerator; -use OCP\L10N\IFactory; - -class Extension implements IExtension { - const APP = 'dav'; - /** - * Filter with all sharing related activities - */ - const CALENDAR = 'calendar'; - const CALENDAR_EVENT = 'calendar_event'; - const CALENDAR_TODO = 'calendar_todo'; - - const SUBJECT_ADD = 'calendar_add'; - const SUBJECT_UPDATE = 'calendar_update'; - const SUBJECT_DELETE = 'calendar_delete'; - const SUBJECT_SHARE_USER = 'calendar_user_share'; - const SUBJECT_SHARE_GROUP = 'calendar_group_share'; - const SUBJECT_UNSHARE_USER = 'calendar_user_unshare'; - const SUBJECT_UNSHARE_GROUP = 'calendar_group_unshare'; - - const SUBJECT_OBJECT_ADD = 'object_add'; - const SUBJECT_OBJECT_UPDATE = 'object_update'; - const SUBJECT_OBJECT_DELETE = 'object_delete'; - - /** @var IFactory */ - protected $languageFactory; - - /** @var IURLGenerator */ - protected $URLGenerator; - - /** - * @param IFactory $languageFactory - * @param IURLGenerator $URLGenerator - */ - public function __construct(IFactory $languageFactory, IURLGenerator $URLGenerator) { - $this->languageFactory = $languageFactory; - $this->URLGenerator = $URLGenerator; - } - - protected function getL10N($languageCode = null) { - return $this->languageFactory->get(self::APP, $languageCode); - } - - /** - * The extension can return an array of additional notification types. - * If no additional types are to be added false is to be returned - * - * @param string $languageCode - * @return array|false - */ - public function getNotificationTypes($languageCode) { - return false; - } - - /** - * For a given method additional types to be displayed in the settings can be returned. - * In case no additional types are to be added false is to be returned. - * - * @param string $method - * @return array|false - */ - public function getDefaultTypes($method) { - return false; - } - - /** - * A string naming the css class for the icon to be used can be returned. - * If no icon is known for the given type false is to be returned. - * - * @param string $type - * @return string|false - */ - public function getTypeIcon($type) { - return false; - } - - /** - * The extension can translate a given message to the requested languages. - * If no translation is available false is to be returned. - * - * @param string $app - * @param string $text - * @param array $params - * @param boolean $stripPath - * @param boolean $highlightParams - * @param string $languageCode - * @return string|false - */ - public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { - if ($app !== self::APP) { - return false; - } - - $l = $this->getL10N($languageCode); - - switch ($text) { - case self::SUBJECT_OBJECT_ADD . '_event': - return (string) $l->t('%1$s created event %3$s in calendar %2$s', $params); - case self::SUBJECT_OBJECT_ADD . '_event_self': - return (string) $l->t('You created event %3$s in calendar %2$s', $params); - case self::SUBJECT_OBJECT_DELETE . '_event': - return (string) $l->t('%1$s deleted event %3$s from calendar %2$s', $params); - case self::SUBJECT_OBJECT_DELETE . '_event_self': - return (string) $l->t('You deleted event %3$s from calendar %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_event': - return (string) $l->t('%1$s updated event %3$s in calendar %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_event_self': - return (string) $l->t('You updated event %3$s in calendar %2$s', $params); - - case self::SUBJECT_OBJECT_ADD . '_todo': - return (string) $l->t('%1$s created todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_ADD . '_todo_self': - return (string) $l->t('You created todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_DELETE . '_todo': - return (string) $l->t('%1$s deleted todo %3$s from list %2$s', $params); - case self::SUBJECT_OBJECT_DELETE . '_todo_self': - return (string) $l->t('You deleted todo %3$s from list %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_todo': - return (string) $l->t('%1$s updated todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_todo_self': - return (string) $l->t('You updated todo %3$s in list %2$s', $params); - - case self::SUBJECT_OBJECT_UPDATE . '_todo_completed': - return (string) $l->t('%1$s solved todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_todo_completed_self': - return (string) $l->t('You solved todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action': - return (string) $l->t('%1$s reopened todo %3$s in list %2$s', $params); - case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self': - return (string) $l->t('You reopened todo %3$s in list %2$s', $params); - - } - - return false; - } - - /** - * The extension can define the type of parameters for translation - * - * Currently known types are: - * * file => will strip away the path of the file and add a tooltip with it - * * username => will add the avatar of the user - * - * @param string $app - * @param string $text - * @return array|false - */ - public function getSpecialParameterList($app, $text) { - if ($app === self::APP) { - switch ($text) { - case self::SUBJECT_OBJECT_ADD . '_event': - case self::SUBJECT_OBJECT_ADD . '_event_self': - case self::SUBJECT_OBJECT_DELETE . '_event': - case self::SUBJECT_OBJECT_DELETE . '_event_self': - case self::SUBJECT_OBJECT_UPDATE . '_event': - case self::SUBJECT_OBJECT_UPDATE . '_event_self': - - case self::SUBJECT_OBJECT_ADD . '_todo': - case self::SUBJECT_OBJECT_ADD . '_todo_self': - case self::SUBJECT_OBJECT_DELETE . '_todo': - case self::SUBJECT_OBJECT_DELETE . '_todo_self': - case self::SUBJECT_OBJECT_UPDATE . '_todo': - case self::SUBJECT_OBJECT_UPDATE . '_todo_self': - - case self::SUBJECT_OBJECT_UPDATE . '_todo_completed': - case self::SUBJECT_OBJECT_UPDATE . '_todo_completed_self': - case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action': - case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self': - return [ - 0 => 'username', - //1 => 'calendar', - //2 => 'object', - ]; - } - } - - return false; - } - - /** - * The extension can define the parameter grouping by returning the index as integer. - * In case no grouping is required false is to be returned. - * - * @param array $activity - * @return integer|false - */ - public function getGroupParameter($activity) { - return false; - } - - /** - * The extension can define additional navigation entries. The array returned has to contain two keys 'top' - * and 'apps' which hold arrays with the relevant entries. - * If no further entries are to be added false is no be returned. - * - * @return array|false - */ - public function getNavigation() { - return false; - } - - /** - * The extension can check if a custom filter (given by a query string like filter=abc) is valid or not. - * - * @param string $filterValue - * @return boolean - */ - public function isFilterValid($filterValue) { - return false; - } - - /** - * The extension can filter the types based on the filter if required. - * In case no filter is to be applied false is to be returned unchanged. - * - * @param array $types - * @param string $filter - * @return array|false - */ - public function filterNotificationTypes($types, $filter) { - return false; - } - - /** - * For a given filter the extension can specify the sql query conditions including parameters for that query. - * In case the extension does not know the filter false is to be returned. - * The query condition and the parameters are to be returned as array with two elements. - * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%')); - * - * @param string $filter - * @return array|false - */ - public function getQueryForFilter($filter) { - return false; - } - -} diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Event.php b/apps/dav/lib/CalDAV/Activity/Provider/Event.php new file mode 100644 index 00000000000..1bad07916b4 --- /dev/null +++ b/apps/dav/lib/CalDAV/Activity/Provider/Event.php @@ -0,0 +1,212 @@ + + * + * @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\CalDAV\Activity\Provider; + +use OCP\Activity\IEvent; +use OCP\Activity\IEventMerger; +use OCP\Activity\IManager; +use OCP\Activity\IProvider; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; + +class Event implements IProvider { + + const SUBJECT_OBJECT_ADD = 'object_add'; + const SUBJECT_OBJECT_UPDATE = 'object_update'; + const SUBJECT_OBJECT_DELETE = 'object_delete'; + + /** @var IL10N */ + protected $l; + + /** @var IURLGenerator */ + protected $url; + + /** @var IManager */ + protected $activityManager; + + /** @var IUserManager */ + protected $userManager; + + /** @var IEventMerger */ + protected $eventMerger; + + /** @var string[] cached displayNames - key is the UID and value the displayname */ + protected $displayNames = []; + + /** + * @param IL10N $l + * @param IURLGenerator $url + * @param IManager $activityManager + * @param IUserManager $userManager + * @param IEventMerger $eventMerger + */ + public function __construct(IL10N $l, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IEventMerger $eventMerger) { + $this->l = $l; + $this->url = $url; + $this->activityManager = $activityManager; + $this->userManager = $userManager; + $this->eventMerger = $eventMerger; + } + + /** + * @param IEvent $event + * @param IEvent|null $previousEvent + * @return IEvent + * @throws \InvalidArgumentException + * @since 11.0.0 + */ + public function parse(IEvent $event, IEvent $previousEvent = null) { + if ($event->getApp() !== 'dav' || $event->getType() !== 'calendar_event') { + throw new \InvalidArgumentException(); + } + + $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'places/calendar-dark.svg'))); + + if ($event->getSubject() === self::SUBJECT_OBJECT_ADD . '_event') { + $subject = $this->l->t('{actor} created event {event} in calendar {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_ADD . '_event_self') { + $subject = $this->l->t('You created event {event} in calendar {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_DELETE . '_event') { + $subject = $this->l->t('{actor} deleted event {event} from calendar {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_DELETE . '_event_self') { + $subject = $this->l->t('You deleted event {event} from calendar {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_event') { + $subject = $this->l->t('{actor} updated event {event} in calendar {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_event_self') { + $subject = $this->l->t('You updated event {event} in calendar {calendar}'); + } else { + throw new \InvalidArgumentException(); + } + + $parsedParameters = $this->getParameters($event); + $this->setSubjects($event, $subject, $parsedParameters); + + $event = $this->eventMerger->mergeEvents('event', $event, $previousEvent); + + return $event; + } + + /** + * @param IEvent $event + * @param string $subject + * @param array $parameters + */ + protected function setSubjects(IEvent $event, $subject, array $parameters) { + $placeholders = $replacements = []; + foreach ($parameters as $placeholder => $parameter) { + $placeholders[] = '{' . $placeholder . '}'; + $replacements[] = $parameter['name']; + } + + $event->setParsedSubject(str_replace($placeholders, $replacements, $subject)) + ->setRichSubject($subject, $parameters); + } + + /** + * @param IEvent $event + * @return array + */ + protected function getParameters(IEvent $event) { + $subject = $event->getSubject(); + $parameters = $event->getSubjectParameters(); + + switch ($subject) { + case self::SUBJECT_OBJECT_ADD . '_event': + case self::SUBJECT_OBJECT_DELETE . '_event': + case self::SUBJECT_OBJECT_UPDATE . '_event': + return [ + 'actor' => $this->generateUserParameter($parameters[0]), + 'calendar' => $this->generateCalendarParameter($event->getObjectId(), $parameters[1]), + 'event' => $this->generateObjectParameter($parameters[2]), + ]; + case self::SUBJECT_OBJECT_ADD . '_event_self': + case self::SUBJECT_OBJECT_DELETE . '_event_self': + case self::SUBJECT_OBJECT_UPDATE . '_event_self': + return [ + 'calendar' => $this->generateCalendarParameter($event->getObjectId(), $parameters[1]), + 'event' => $this->generateObjectParameter($parameters[2]), + ]; + } + + throw new \InvalidArgumentException(); + } + + /** + * @param array $eventData + * @return array + */ + protected function generateObjectParameter($eventData) { + if (!is_array($eventData)) { + throw new \InvalidArgumentException(); + }; + + return [ + 'type' => 'calendar-event', + 'id' => $eventData['id'], + 'name' => $eventData['name'], + ]; + } + + /** + * @param int $id + * @param string $name + * @return array + */ + protected function generateCalendarParameter($id, $name) { + return [ + 'type' => 'calendar', + 'id' => $id, + 'name' => $name, + ]; + } + + /** + * @param string $uid + * @return array + */ + protected function generateUserParameter($uid) { + if (!isset($this->displayNames[$uid])) { + $this->displayNames[$uid] = $this->getDisplayName($uid); + } + + return [ + 'type' => 'user', + 'id' => $uid, + 'name' => $this->displayNames[$uid], + ]; + } + + /** + * @param string $uid + * @return string + */ + protected function getDisplayName($uid) { + $user = $this->userManager->get($uid); + if ($user instanceof IUser) { + return $user->getDisplayName(); + } else { + return $uid; + } + } +} diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php new file mode 100644 index 00000000000..12c341160c0 --- /dev/null +++ b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php @@ -0,0 +1,114 @@ + + * + * @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\CalDAV\Activity\Provider; + +use OCP\Activity\IEvent; +use OCP\Activity\IEventMerger; +use OCP\Activity\IManager; +use OCP\Activity\IProvider; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; + +class Todo extends Event { + + /** + * @param IEvent $event + * @param IEvent|null $previousEvent + * @return IEvent + * @throws \InvalidArgumentException + * @since 11.0.0 + */ + public function parse(IEvent $event, IEvent $previousEvent = null) { + if ($event->getApp() !== 'dav' || $event->getType() !== 'calendar_todo') { + throw new \InvalidArgumentException(); + } + + $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/checkmark.svg'))); + + if ($event->getSubject() === self::SUBJECT_OBJECT_ADD . '_todo') { + $subject = $this->l->t('{actor} created todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_ADD . '_todo_self') { + $subject = $this->l->t('You created todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_DELETE . '_todo') { + $subject = $this->l->t('{actor} deleted todo {todo} from list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_DELETE . '_todo_self') { + $subject = $this->l->t('You deleted todo {todo} from list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo') { + $subject = $this->l->t('{actor} updated todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_self') { + $subject = $this->l->t('You updated todo {todo} in list {calendar}'); + + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_completed') { + $subject = $this->l->t('{actor} solved todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_completed_self') { + $subject = $this->l->t('You solved todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action') { + $subject = $this->l->t('{actor} reopened todo {todo} in list {calendar}'); + } else if ($event->getSubject() === self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self') { + $subject = $this->l->t('You reopened todo {todo} in list {calendar}'); + } else { + throw new \InvalidArgumentException(); + } + + $parsedParameters = $this->getParameters($event); + $this->setSubjects($event, $subject, $parsedParameters); + + $event = $this->eventMerger->mergeEvents('todo', $event, $previousEvent); + + return $event; + } + + /** + * @param IEvent $event + * @return array + */ + protected function getParameters(IEvent $event) { + $subject = $event->getSubject(); + $parameters = $event->getSubjectParameters(); + + switch ($subject) { + case self::SUBJECT_OBJECT_ADD . '_todo': + case self::SUBJECT_OBJECT_DELETE . '_todo': + case self::SUBJECT_OBJECT_UPDATE . '_todo': + case self::SUBJECT_OBJECT_UPDATE . '_todo_completed': + case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action': + return [ + 'actor' => $this->generateUserParameter($parameters[0]), + 'calendar' => $this->generateCalendarParameter($event->getObjectId(), $parameters[1]), + 'todo' => $this->generateObjectParameter($parameters[2]), + ]; + case self::SUBJECT_OBJECT_ADD . '_todo_self': + case self::SUBJECT_OBJECT_DELETE . '_todo_self': + case self::SUBJECT_OBJECT_UPDATE . '_todo_self': + case self::SUBJECT_OBJECT_UPDATE . '_todo_completed_self': + case self::SUBJECT_OBJECT_UPDATE . '_todo_needs_action_self': + return [ + 'calendar' => $this->generateCalendarParameter($event->getObjectId(), $parameters[1]), + 'todo' => $this->generateObjectParameter($parameters[2]), + ]; + } + + throw new \InvalidArgumentException(); + } +} diff --git a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php index 3585d69bad3..d8d15e8f1f7 100644 --- a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php +++ b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php @@ -22,7 +22,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\Activity; use OCA\DAV\CalDAV\Activity\Backend; -use OCA\DAV\CalDAV\Activity\Extension; +use OCA\DAV\CalDAV\Activity\Provider\Calendar; use OCP\Activity\IEvent; use OCP\Activity\IManager; use OCP\IGroup; @@ -74,9 +74,9 @@ class BackendTest extends TestCase { public function dataCallTriggerCalendarActivity() { return [ - ['onCalendarAdd', [['data']], Extension::SUBJECT_ADD, [['data'], [], []]], - ['onCalendarUpdate', [['data'], ['shares'], ['changed-properties']], Extension::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]], - ['onCalendarDelete', [['data'], ['shares']], Extension::SUBJECT_DELETE, [['data'], ['shares'], []]], + ['onCalendarAdd', [['data']], Calendar::SUBJECT_ADD, [['data'], [], []]], + ['onCalendarUpdate', [['data'], ['shares'], ['changed-properties']], Calendar::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]], + ['onCalendarDelete', [['data'], ['shares']], Calendar::SUBJECT_DELETE, [['data'], ['shares'], []]], ]; } @@ -104,51 +104,51 @@ class BackendTest extends TestCase { public function dataTriggerCalendarActivity() { return [ // Add calendar - [Extension::SUBJECT_ADD, [], [], [], '', '', null, []], - [Extension::SUBJECT_ADD, [ + [Calendar::SUBJECT_ADD, [], [], [], '', '', null, []], + [Calendar::SUBJECT_ADD, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], [], [], '', 'admin', null, ['admin']], - [Extension::SUBJECT_ADD, [ + [Calendar::SUBJECT_ADD, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], [], [], 'test2', 'test2', null, ['admin']], // Update calendar - [Extension::SUBJECT_UPDATE, [], [], [], '', '', null, []], + [Calendar::SUBJECT_UPDATE, [], [], [], '', '', null, []], // No visible change - owner only - [Extension::SUBJECT_UPDATE, [ + [Calendar::SUBJECT_UPDATE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], ['shares'], [], '', 'admin', null, ['admin']], // Visible change - [Extension::SUBJECT_UPDATE, [ + [Calendar::SUBJECT_UPDATE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], ['shares'], ['{DAV:}displayname' => 'Name'], '', 'admin', ['user1'], ['user1', 'admin']], - [Extension::SUBJECT_UPDATE, [ + [Calendar::SUBJECT_UPDATE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], ['shares'], ['{DAV:}displayname' => 'Name'], 'test2', 'test2', ['user1'], ['user1', 'admin']], // Delete calendar - [Extension::SUBJECT_DELETE, [], [], [], '', '', null, []], - [Extension::SUBJECT_DELETE, [ + [Calendar::SUBJECT_DELETE, [], [], [], '', '', null, []], + [Calendar::SUBJECT_DELETE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], ['shares'], [], '', 'admin', [], ['admin']], - [Extension::SUBJECT_DELETE, [ + [Calendar::SUBJECT_DELETE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', ], ['shares'], [], '', 'admin', ['user1'], ['user1', 'admin']], - [Extension::SUBJECT_DELETE, [ + [Calendar::SUBJECT_DELETE, [ 'principaluri' => 'principal/user/admin', 'id' => 42, '{DAV:}displayname' => 'Name of calendar', @@ -202,11 +202,11 @@ class BackendTest extends TestCase { ->willReturnSelf(); $event->expects($this->once()) ->method('setObject') - ->with(Extension::CALENDAR, $data['id']) + ->with('calendar', $data['id']) ->willReturnSelf(); $event->expects($this->once()) ->method('setType') - ->with(Extension::CALENDAR) + ->with('calendar') ->willReturnSelf(); $event->expects($this->once()) ->method('setAuthor') -- 2.39.5