diff options
Diffstat (limited to 'apps/dav/lib/CalDAV/Reminder/Notifier.php')
-rw-r--r-- | apps/dav/lib/CalDAV/Reminder/Notifier.php | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/apps/dav/lib/CalDAV/Reminder/Notifier.php b/apps/dav/lib/CalDAV/Reminder/Notifier.php new file mode 100644 index 00000000000..2c5f05f62ab --- /dev/null +++ b/apps/dav/lib/CalDAV/Reminder/Notifier.php @@ -0,0 +1,316 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019, Thomas Citharel + * @copyright Copyright (c) 2019, Georg Ehrke + * + * @author Thomas Citharel <tcit@tcit.fr> + * @author Georg Ehrke <oc.list@georgehrke.com> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\CalDAV\Reminder; + +use \DateTime; +use OCA\DAV\AppInfo\Application; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IL10N; +use OCP\L10N\IFactory; +use OCP\Notification\INotification; +use OCP\Notification\INotifier; +use OCP\IURLGenerator; + +/** + * Class Notifier + * + * @package OCA\DAV\CalDAV\Reminder + */ +class Notifier implements INotifier { + + /** @var IFactory */ + private $l10nFactory; + + /** @var IURLGenerator */ + private $urlGenerator; + + /** @var IL10N */ + private $l10n; + + /** @var ITimeFactory */ + private $timeFactory; + + /** + * Notifier constructor. + * + * @param IFactory $factory + * @param IURLGenerator $urlGenerator + * @param ITimeFactory $timeFactory + */ + public function __construct(IFactory $factory, + IURLGenerator $urlGenerator, + ITimeFactory $timeFactory) { + $this->l10nFactory = $factory; + $this->urlGenerator = $urlGenerator; + $this->timeFactory = $timeFactory; + } + + /** + * Identifier of the notifier, only use [a-z0-9_] + * + * @return string + * @since 17.0.0 + */ + public function getID():string { + return Application::APP_ID; + } + + /** + * Human readable name describing the notifier + * + * @return string + * @since 17.0.0 + */ + public function getName():string { + return $this->l10nFactory->get('dav')->t('Calendar'); + } + + /** + * Prepare sending the notification + * + * @param INotification $notification + * @param string $languageCode The code of the language that should be used to prepare the notification + * @return INotification + * @throws \Exception + */ + public function prepare(INotification $notification, + string $languageCode):INotification { + if ($notification->getApp() !== Application::APP_ID) { + throw new \InvalidArgumentException('Notification not from this app'); + } + + // Read the language from the notification + $this->l10n = $this->l10nFactory->get('dav', $languageCode); + + // Handle notifier subjects + switch($notification->getSubject()) { + case 'calendar_reminder': + return $this->prepareReminderNotification($notification); + + default: + throw new \InvalidArgumentException('Unknown subject'); + + } + } + + /** + * @param INotification $notification + * @return INotification + */ + private function prepareReminderNotification(INotification $notification):INotification { + $imagePath = $this->urlGenerator->imagePath('core', 'places/calendar.svg'); + $iconUrl = $this->urlGenerator->getAbsoluteURL($imagePath); + $notification->setIcon($iconUrl); + + $this->prepareNotificationSubject($notification); + $this->prepareNotificationMessage($notification); + + return $notification; + } + + /** + * Sets the notification subject based on the parameters set in PushProvider + * + * @param INotification $notification + */ + private function prepareNotificationSubject(INotification $notification): void { + $parameters = $notification->getSubjectParameters(); + + $startTime = \DateTime::createFromFormat(\DateTime::ATOM, $parameters['start_atom']); + $now = $this->timeFactory->getDateTime(); + $title = $this->getTitleFromParameters($parameters); + + $diff = $startTime->diff($now); + if ($diff === false) { + return; + } + + $components = []; + if ($diff->y) { + $components[] = $this->l10n->n('%n year', '%n years', $diff->y); + } + if ($diff->m) { + $components[] = $this->l10n->n('%n month', '%n months', $diff->m); + } + if ($diff->d) { + $components[] = $this->l10n->n('%n day', '%n days', $diff->d); + } + if ($diff->h) { + $components[] = $this->l10n->n('%n hour', '%n hours', $diff->h); + } + if ($diff->i) { + $components[] = $this->l10n->n('%n minute', '%n minutes', $diff->i); + } + + // Limiting to the first three components to prevent + // the string from getting too long + $firstThreeComponents = array_slice($components, 0, 2); + $diffLabel = implode(', ', $firstThreeComponents); + + if ($diff->invert) { + $title = $this->l10n->t('%s (in %s)', [$title, $diffLabel]); + } else { + $title = $this->l10n->t('%s (%s ago)', [$title, $diffLabel]); + } + + $notification->setParsedSubject($title); + } + + /** + * Sets the notification message based on the parameters set in PushProvider + * + * @param INotification $notification + */ + private function prepareNotificationMessage(INotification $notification): void { + $parameters = $notification->getMessageParameters(); + + $description = [ + $this->l10n->t('Calendar: %s', $parameters['calendar_displayname']), + $this->l10n->t('Date: %s', $this->generateDateString($parameters)), + ]; + if ($parameters['description']) { + $description[] = $this->l10n->t('Description: %s', $parameters['description']); + } + if ($parameters['location']) { + $description[] = $this->l10n->t('Where: %s', $parameters['location']); + } + + $message = implode("\r\n", $description); + $notification->setParsedMessage($message); + } + + /** + * @param array $parameters + * @return string + */ + private function getTitleFromParameters(array $parameters):string { + return $parameters['title'] ?? $this->l10n->t('Untitled event'); + } + + /** + * @param array $parameters + * @return string + * @throws \Exception + */ + private function generateDateString(array $parameters):string { + $startDateTime = DateTime::createFromFormat(\DateTime::ATOM, $parameters['start_atom']); + $endDateTime = DateTime::createFromFormat(\DateTime::ATOM, $parameters['end_atom']); + $isAllDay = $parameters['all_day']; + $diff = $startDateTime->diff($endDateTime); + + if ($isAllDay) { + // One day event + if ($diff->days === 1) { + return $this->getDateString($startDateTime); + } + + return implode(' - ', [ + $this->getDateString($startDateTime), + $this->getDateString($endDateTime), + ]); + } + + $startTimezone = $endTimezone = null; + if (!$parameters['start_is_floating']) { + $startTimezone = $parameters['start_timezone']; + $endTimezone = $parameters['end_timezone']; + } + + $localeStart = implode(', ', [ + $this->getWeekDayName($startDateTime), + $this->getDateTimeString($startDateTime) + ]); + + // always show full date with timezone if timezones are different + if ($startTimezone !== $endTimezone) { + $localeEnd = implode(', ', [ + $this->getWeekDayName($endDateTime), + $this->getDateTimeString($endDateTime) + ]); + + return $localeStart + . ' (' . $startTimezone . ') ' + . ' - ' + . $localeEnd + . ' (' . $endTimezone . ')'; + } + + // Show only the time if the day is the same + $localeEnd = $this->isDayEqual($startDateTime, $endDateTime) + ? $this->getTimeString($endDateTime) + : implode(', ', [ + $this->getWeekDayName($endDateTime), + $this->getDateTimeString($endDateTime) + ]); + + return $localeStart + . ' - ' + . $localeEnd + . ' (' . $startTimezone . ')'; + } + + /** + * @param DateTime $dtStart + * @param DateTime $dtEnd + * @return bool + */ + private function isDayEqual(DateTime $dtStart, + DateTime $dtEnd):bool { + return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d'); + } + + /** + * @param DateTime $dt + * @return string + */ + private function getWeekDayName(DateTime $dt):string { + return $this->l10n->l('weekdayName', $dt, ['width' => 'abbreviated']); + } + + /** + * @param DateTime $dt + * @return string + */ + private function getDateString(DateTime $dt):string { + return $this->l10n->l('date', $dt, ['width' => 'medium']); + } + + /** + * @param DateTime $dt + * @return string + */ + private function getDateTimeString(DateTime $dt):string { + return $this->l10n->l('datetime', $dt, ['width' => 'medium|short']); + } + + /** + * @param DateTime $dt + * @return string + */ + private function getTimeString(DateTime $dt):string { + return $this->l10n->l('time', $dt, ['width' => 'short']); + } +} |