Signed-off-by: Joas Schilling <coding@schilljs.com>tags/v11.0RC2
@@ -46,6 +46,8 @@ | |||
<providers> | |||
<provider>OCA\DAV\CalDAV\Activity\Provider\Calendar</provider> | |||
<provider>OCA\DAV\CalDAV\Activity\Provider\Event</provider> | |||
<provider>OCA\DAV\CalDAV\Activity\Provider\Todo</provider> | |||
</providers> | |||
</activity> | |||
</info> |
@@ -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() { |
@@ -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]; | |||
} | |||
/** |
@@ -1,261 +0,0 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,212 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,114 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> | |||
* | |||
* @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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
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(); | |||
} | |||
} |
@@ -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') |