mirror of https://github.com/nextcloud/server.git
Support event reminders (email and notifications)
Signed-off-by: Thomas Citharel <tcit@tcit.fr>pull/3044/head
parent
f452e23a7d
commit
7bddcc091d
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\BackgroundJob;
|
||||
|
||||
use OC\BackgroundJob\TimedJob;
|
||||
use OCA\DAV\CalDAV\Reminder\ReminderService;
|
||||
use OCP\IConfig;
|
||||
|
||||
class EventReminderJob extends TimedJob {
|
||||
|
||||
/** @var ReminderService */
|
||||
private $reminderService;
|
||||
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* EventReminderJob constructor.
|
||||
*
|
||||
* @param ReminderService $reminderService
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(ReminderService $reminderService, IConfig $config) {
|
||||
$this->reminderService = $reminderService;
|
||||
$this->config = $config;
|
||||
/** Run every 5 minutes */
|
||||
$this->setInterval(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $arg
|
||||
* @throws \OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException
|
||||
* @throws \OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException
|
||||
* @throws \OC\User\NoUserException
|
||||
*/
|
||||
public function run($arg): void
|
||||
{
|
||||
if ($this->config->getAppValue('dav', 'sendEventReminders', 'yes') === 'yes') {
|
||||
$this->reminderService->processReminders();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder;
|
||||
|
||||
use \DateTime;
|
||||
use \DateTimeImmutable;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\IUser;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
use Sabre\VObject\Component\VEvent;
|
||||
use Sabre\VObject\DateTimeParser;
|
||||
use Sabre\VObject\Parameter;
|
||||
use Sabre\VObject\Property;
|
||||
|
||||
abstract class AbstractNotificationProvider
|
||||
{
|
||||
|
||||
public const NOTIFICATION_TYPE = '';
|
||||
|
||||
/** @var ILogger */
|
||||
protected $logger;
|
||||
|
||||
/** @var L10NFactory */
|
||||
protected $l10nFactory;
|
||||
|
||||
/** @var IL10N */
|
||||
protected $l10n;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param ILogger $logger
|
||||
* @param L10NFactory $l10nFactory
|
||||
* @param IConfig $config
|
||||
* @param IUrlGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct(ILogger $logger, L10NFactory $l10nFactory, IURLGenerator $urlGenerator, IConfig $config) {
|
||||
$this->logger = $logger;
|
||||
$this->l10nFactory = $l10nFactory;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification
|
||||
*
|
||||
* @param VCalendar $vcalendar
|
||||
* @param string $calendarDisplayName
|
||||
* @param IUser $user
|
||||
* @return void
|
||||
*/
|
||||
public function send(VCalendar $vcalendar, string $calendarDisplayName, IUser $user): void {}
|
||||
|
||||
/**
|
||||
* @var VCalendar $vcalendar
|
||||
* @var string $defaultValue
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function extractEventDetails(VCalendar $vcalendar, $defaultValue = ''): array
|
||||
{
|
||||
/** @var VEvent $vevent */
|
||||
$vevent = $vcalendar->VEVENT;
|
||||
|
||||
/** @var Property $start */
|
||||
$start = $vevent->DTSTART;
|
||||
if (isset($vevent->DTEND)) {
|
||||
$end = $vevent->DTEND;
|
||||
} elseif (isset($vevent->DURATION)) {
|
||||
$isFloating = $vevent->DTSTART->isFloating();
|
||||
$end = clone $vevent->DTSTART;
|
||||
$endDateTime = $end->getDateTime();
|
||||
$endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue()));
|
||||
$end->setDateTime($endDateTime, $isFloating);
|
||||
} elseif (!$vevent->DTSTART->hasTime()) {
|
||||
$isFloating = $vevent->DTSTART->isFloating();
|
||||
$end = clone $vevent->DTSTART;
|
||||
$endDateTime = $end->getDateTime();
|
||||
$endDateTime = $endDateTime->modify('+1 day');
|
||||
$end->setDateTime($endDateTime, $isFloating);
|
||||
} else {
|
||||
$end = clone $vevent->DTSTART;
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => (string) $vevent->SUMMARY ?: $defaultValue,
|
||||
'description' => (string) $vevent->DESCRIPTION ?: $defaultValue,
|
||||
'start'=> $start->getDateTime(),
|
||||
'end' => $end->getDateTime(),
|
||||
'when' => $this->generateWhenString($start, $end),
|
||||
'url' => (string) $vevent->URL ?: $defaultValue,
|
||||
'location' => (string) $vevent->LOCATION ?: $defaultValue,
|
||||
'uid' => (string) $vevent->UID,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Property $dtstart
|
||||
* @param Property $dtend
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function generateWhenString(Property $dtstart, Property $dtend): string
|
||||
{
|
||||
$isAllDay = $dtstart instanceof Property\ICalendar\Date;
|
||||
|
||||
/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */
|
||||
/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */
|
||||
/** @var DateTimeImmutable $dtstartDt */
|
||||
$dtstartDt = $dtstart->getDateTime();
|
||||
/** @var DateTimeImmutable $dtendDt */
|
||||
$dtendDt = $dtend->getDateTime();
|
||||
|
||||
$diff = $dtstartDt->diff($dtendDt);
|
||||
|
||||
$dtstartDt = new DateTime($dtstartDt->format(DateTime::ATOM));
|
||||
$dtendDt = new DateTime($dtendDt->format(DateTime::ATOM));
|
||||
|
||||
if ($isAllDay) {
|
||||
// One day event
|
||||
if ($diff->days === 1) {
|
||||
return $this->l10n->l('date', $dtstartDt, ['width' => 'medium']);
|
||||
}
|
||||
|
||||
//event that spans over multiple days
|
||||
$localeStart = $this->l10n->l('date', $dtstartDt, ['width' => 'medium']);
|
||||
$localeEnd = $this->l10n->l('date', $dtendDt, ['width' => 'medium']);
|
||||
|
||||
return $localeStart . ' - ' . $localeEnd;
|
||||
}
|
||||
|
||||
/** @var Property\ICalendar\DateTime $dtstart */
|
||||
/** @var Property\ICalendar\DateTime $dtend */
|
||||
$isFloating = $dtstart->isFloating();
|
||||
$startTimezone = $endTimezone = null;
|
||||
if (!$isFloating) {
|
||||
$prop = $dtstart->offsetGet('TZID');
|
||||
if ($prop instanceof Parameter) {
|
||||
$startTimezone = $prop->getValue();
|
||||
}
|
||||
|
||||
$prop = $dtend->offsetGet('TZID');
|
||||
if ($prop instanceof Parameter) {
|
||||
$endTimezone = $prop->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
$localeStart = $this->l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
|
||||
$this->l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
|
||||
|
||||
// always show full date with timezone if timezones are different
|
||||
if ($startTimezone !== $endTimezone) {
|
||||
$localeEnd = $this->l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
|
||||
|
||||
return $localeStart . ' (' . $startTimezone . ') - ' .
|
||||
$localeEnd . ' (' . $endTimezone . ')';
|
||||
}
|
||||
|
||||
// show only end time if date is the same
|
||||
if ($this->isDayEqual($dtstartDt, $dtendDt)) {
|
||||
$localeEnd = $this->l10n->l('time', $dtendDt, ['width' => 'short']);
|
||||
} else {
|
||||
$localeEnd = $this->l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
|
||||
$this->l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
|
||||
/**
|
||||
* Class Backend
|
||||
*
|
||||
* @package OCA\DAV\CalDAV\Reminder
|
||||
*/
|
||||
class Backend {
|
||||
|
||||
/** @var IDBConnection */
|
||||
protected $db;
|
||||
|
||||
/** @var ITimeFactory */
|
||||
private $timeFactory;
|
||||
|
||||
/**
|
||||
* @param IDBConnection $db
|
||||
* @param ITimeFactory $timeFactory
|
||||
*/
|
||||
public function __construct(IDBConnection $db, ITimeFactory $timeFactory) {
|
||||
$this->db = $db;
|
||||
$this->timeFactory = $timeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uid
|
||||
* @param string $calendarId
|
||||
* @param string $uri
|
||||
* @param string $type
|
||||
* @param int $notificationDate
|
||||
* @param int $eventStartDate
|
||||
*/
|
||||
public function insertReminder(string $uid, string $calendarId, string $uri, string $type, int $notificationDate, int $eventStartDate): void
|
||||
{
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$query->insert('calendar_reminders')
|
||||
->values([
|
||||
'uid' => $query->createNamedParameter($uid),
|
||||
'calendarid' => $query->createNamedParameter($calendarId),
|
||||
'objecturi' => $query->createNamedParameter($uri),
|
||||
'type' => $query->createNamedParameter($type),
|
||||
'notificationdate' => $query->createNamedParameter($notificationDate),
|
||||
'eventstartdate' => $query->createNamedParameter($eventStartDate),
|
||||
])->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans reminders in database
|
||||
*
|
||||
* @param int $calendarId
|
||||
* @param string $objectUri
|
||||
*/
|
||||
public function cleanRemindersForEvent(int $calendarId, string $objectUri): void
|
||||
{
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
||||
$query->delete('calendar_reminders')
|
||||
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
|
||||
->andWhere($query->expr()->eq('objecturi', $query->createNamedParameter($objectUri)))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all reminders for a calendar
|
||||
*
|
||||
* @param integer $calendarId
|
||||
* @return void
|
||||
*/
|
||||
public function cleanRemindersForCalendar(int $calendarId): void
|
||||
{
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
||||
$query->delete('calendar_reminders')
|
||||
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a reminder by it's id
|
||||
*
|
||||
* @param integer $reminderId
|
||||
* @return void
|
||||
*/
|
||||
public function removeReminder(int $reminderId): void
|
||||
{
|
||||
$query = $this->db->getQueryBuilder();
|
||||
|
||||
$query->delete('calendar_reminders')
|
||||
->where($query->expr()->eq('id', $query->createNamedParameter($reminderId)))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all reminders with a notification date before now
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getRemindersToProcess(): array
|
||||
{
|
||||
$query = $this->db->getQueryBuilder();
|
||||
$fields = ['cr.id', 'cr.calendarid', 'cr.objecturi', 'cr.type', 'cr.notificationdate', 'cr.uid', 'co.calendardata', 'c.displayname'];
|
||||
$stmt = $query->select($fields)
|
||||
->from('calendar_reminders', 'cr')
|
||||
->where($query->expr()->lte('cr.notificationdate', $query->createNamedParameter($this->timeFactory->getTime())))
|
||||
->andWhere($query->expr()->gte('cr.eventstartdate', $query->createNamedParameter($this->timeFactory->getTime()))) # We check that DTSTART isn't before
|
||||
->leftJoin('cr', 'calendars', 'c', $query->expr()->eq('cr.calendarid', 'c.id'))
|
||||
->leftJoin('cr', 'calendarobjects', 'co', $query->expr()->andX($query->expr()->eq('cr.calendarid', 'c.id'), $query->expr()->eq('co.uri', 'cr.objecturi')))
|
||||
->execute();
|
||||
|
||||
return $stmt->fetchAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder\NotificationProvider;
|
||||
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\IUser;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
class EmailProvider extends AbstractNotificationProvider
|
||||
{
|
||||
/** @var IMailer */
|
||||
private $mailer;
|
||||
|
||||
public const NOTIFICATION_TYPE = 'EMAIL';
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param IMailer $mailer
|
||||
* @param ILogger $logger
|
||||
* @param L10NFactory $l10nFactory
|
||||
* @param IUrlGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct(IConfig $config, IMailer $mailer, ILogger $logger,
|
||||
L10NFactory $l10nFactory,
|
||||
IURLGenerator $urlGenerator) {
|
||||
parent::__construct($logger, $l10nFactory, $urlGenerator, $config);
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification
|
||||
*
|
||||
* @param VCalendar $vcalendar
|
||||
* @param string $calendarDisplayName
|
||||
* @param IUser $user
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function send(VCalendar $vcalendar, string $calendarDisplayName, IUser $user): void
|
||||
{
|
||||
if ($user->getEMailAddress() === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lang = $this->config->getUserValue($user->getUID(), 'core', 'lang', $this->l10nFactory->findLanguage());
|
||||
$this->l10n = $this->l10nFactory->get('dav', $lang);
|
||||
|
||||
$event = $this->extractEventDetails($vcalendar);
|
||||
$fromEMail = \OCP\Util::getDefaultEmailAddress('invitations-noreply');
|
||||
|
||||
$message = $this->mailer->createMessage()
|
||||
->setFrom([$fromEMail => 'Nextcloud'])
|
||||
// TODO: Set reply to from event creator
|
||||
// ->setReplyTo([$sender => $senderName])
|
||||
->setTo([$user->getEMailAddress() => $user->getDisplayName()]);
|
||||
|
||||
$template = $this->mailer->createEMailTemplate('dav.calendarReminder', $event);
|
||||
$template->addHeader();
|
||||
|
||||
$this->addSubjectAndHeading($template, $event['title']);
|
||||
$this->addBulletList($template, $event, $calendarDisplayName);
|
||||
|
||||
$template->addFooter();
|
||||
$message->useTemplate($template);
|
||||
|
||||
$attachment = $this->mailer->createAttachment(
|
||||
$vcalendar->serialize(),
|
||||
$event['uid'].'.ics',// TODO(leon): Make file name unique, e.g. add event id
|
||||
'text/calendar'
|
||||
);
|
||||
$message->attach($attachment);
|
||||
|
||||
try {
|
||||
$failed = $this->mailer->send($message);
|
||||
if ($failed) {
|
||||
$this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' => implode(', ', $failed)]);
|
||||
}
|
||||
} catch(\Exception $ex) {
|
||||
$this->logger->logException($ex, ['app' => 'dav']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IEMailTemplate $template
|
||||
* @param string $summary
|
||||
*/
|
||||
private function addSubjectAndHeading(IEMailTemplate $template, string $summary): void
|
||||
{
|
||||
$template->setSubject('Notification: ' . $summary);
|
||||
$template->addHeading($summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IEMailTemplate $template
|
||||
* @param array $eventData
|
||||
* @param string $calendarDisplayName
|
||||
*/
|
||||
private function addBulletList(IEMailTemplate $template, array $eventData, string $calendarDisplayName): void
|
||||
{
|
||||
$template->addBodyListItem($calendarDisplayName, $this->l10n->t('Calendar:'),
|
||||
$this->getAbsoluteImagePath('actions/info.svg'));
|
||||
|
||||
$template->addBodyListItem($eventData['when'], $this->l10n->t('Date:'),
|
||||
$this->getAbsoluteImagePath('places/calendar.svg'));
|
||||
|
||||
if ($eventData['location']) {
|
||||
$template->addBodyListItem((string) $eventData['location'], $this->l10n->t('Where:'),
|
||||
$this->getAbsoluteImagePath('actions/address.svg'));
|
||||
}
|
||||
if ($eventData['description']) {
|
||||
$template->addBodyListItem((string) $eventData['description'], $this->l10n->t('Description:'),
|
||||
$this->getAbsoluteImagePath('actions/more.svg'));
|
||||
}
|
||||
if ($eventData['url']) {
|
||||
$template->addBodyListItem((string) $eventData['url'], $this->l10n->t('Link:'),
|
||||
$this->getAbsoluteImagePath('places/link.svg'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
private function getAbsoluteImagePath($path): string
|
||||
{
|
||||
return $this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->imagePath('core', $path)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder\NotificationProvider;
|
||||
|
||||
class ProviderNotAvailableException extends \Exception {
|
||||
|
||||
/**
|
||||
* ProviderNotAvailableException constructor.
|
||||
*
|
||||
* @since 16.0.0
|
||||
*
|
||||
* @param string $type ReminderType
|
||||
*/
|
||||
public function __construct(string $type) {
|
||||
parent::__construct("No notification provider for type $type available");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder\NotificationProvider;
|
||||
|
||||
use OCA\DAV\AppInfo\Application;
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\Notification\IManager;
|
||||
use OCP\IUser;
|
||||
use OCP\Notification\INotification;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
|
||||
class PushProvider extends AbstractNotificationProvider
|
||||
{
|
||||
|
||||
public const NOTIFICATION_TYPE = 'DISPLAY';
|
||||
|
||||
/**
|
||||
* @var IManager
|
||||
*/
|
||||
private $manager;
|
||||
|
||||
/**
|
||||
* @var ITimeFactory
|
||||
*/
|
||||
private $timeFactory;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param IManager $manager
|
||||
* @param ILogger $logger
|
||||
* @param L10NFactory $l10nFactory
|
||||
* @param IUrlGenerator $urlGenerator
|
||||
* @param ITimeFactory $timeFactory
|
||||
*/
|
||||
public function __construct(IConfig $config, IManager $manager, ILogger $logger,
|
||||
L10NFactory $l10nFactory,
|
||||
IURLGenerator $urlGenerator, ITimeFactory $timeFactory) {
|
||||
parent::__construct($logger, $l10nFactory, $urlGenerator, $config);
|
||||
$this->manager = $manager;
|
||||
$this->timeFactory = $timeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification
|
||||
*
|
||||
* @param VCalendar $vcalendar
|
||||
* @param string $calendarDisplayName
|
||||
* @param IUser $user
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function send(VCalendar $vcalendar, string $calendarDisplayName, IUser $user): void
|
||||
{
|
||||
|
||||
$lang = $this->config->getUserValue($user->getUID(), 'core', 'lang', $this->l10nFactory->findLanguage());
|
||||
$this->l10n = $this->l10nFactory->get('dav', $lang);
|
||||
|
||||
$event = $this->extractEventDetails($vcalendar);
|
||||
/** @var INotification $notification */
|
||||
$notification = $this->manager->createNotification();
|
||||
$notification->setApp(Application::APP_ID)
|
||||
->setUser($user->getUID())
|
||||
->setDateTime($this->timeFactory->getDateTime())
|
||||
->setObject(Application::APP_ID, $event['uid']) // $type and $id
|
||||
->setSubject('calendar_reminder', ['title' => $event['title'], 'start' => $event['start']->getTimestamp()]) // $subject and $parameters
|
||||
->setMessage('calendar_reminder', [
|
||||
'when' => $event['when'],
|
||||
'description' => $event['description'],
|
||||
'location' => $event['location'],
|
||||
'calendar' => $calendarDisplayName
|
||||
])
|
||||
;
|
||||
$this->manager->notify($notification);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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 OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException;
|
||||
|
||||
class NotificationProviderManager {
|
||||
|
||||
/** @var array */
|
||||
private $providers = [];
|
||||
/**
|
||||
* @var string $type
|
||||
* @return AbstractNotificationProvider
|
||||
* @throws ProviderNotAvailableException
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
*/
|
||||
public function getProvider(string $type): AbstractNotificationProvider
|
||||
{
|
||||
if (in_array($type, ReminderService::REMINDER_TYPES, true)) {
|
||||
if (isset($this->providers[$type])) {
|
||||
return $this->providers[$type];
|
||||
}
|
||||
throw new ProviderNotAvailableException($type);
|
||||
}
|
||||
throw new NotificationTypeDoesNotExistException($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $providerClassName
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function registerProvider(string $providerClassName): void
|
||||
{
|
||||
$provider = \OC::$server->query($providerClassName);
|
||||
|
||||
if (!$provider instanceof AbstractNotificationProvider) {
|
||||
throw new \InvalidArgumentException('Invalid notification provider registered');
|
||||
}
|
||||
|
||||
$this->providers[$provider::NOTIFICATION_TYPE] = $provider;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Reminder;
|
||||
|
||||
class NotificationTypeDoesNotExistException extends \Exception {
|
||||
|
||||
/**
|
||||
* NotificationTypeDoesNotExistException constructor.
|
||||
*
|
||||
* @since 16.0.0
|
||||
*
|
||||
* @param string $type ReminderType
|
||||
*/
|
||||
public function __construct(string $type) {
|
||||
parent::__construct("Type $type is not an accepted type of notification");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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 OCA\DAV\AppInfo\Application;
|
||||
use OCP\IL10N;
|
||||
use OCP\L10N\IFactory;
|
||||
use OCP\Notification\INotification;
|
||||
use OCP\Notification\INotifier;
|
||||
use OCP\IURLGenerator;
|
||||
|
||||
class Notifier implements INotifier {
|
||||
|
||||
public static $units = array(
|
||||
'y' => 'year',
|
||||
'm' => 'month',
|
||||
'd' => 'day',
|
||||
'h' => 'hour',
|
||||
'i' => 'minute',
|
||||
's' => 'second',
|
||||
);
|
||||
|
||||
/** @var IFactory */
|
||||
protected $factory;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IL10N */
|
||||
protected $l;
|
||||
|
||||
public function __construct(IFactory $factory, IURLGenerator $urlGenerator) {
|
||||
$this->factory = $factory;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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, $languageCode): INotification
|
||||
{
|
||||
if ($notification->getApp() !== Application::APP_ID) {
|
||||
throw new \InvalidArgumentException('Notification not from this app');
|
||||
}
|
||||
|
||||
// Read the language from the notification
|
||||
$this->l = $this->factory->get('dav', $languageCode);
|
||||
|
||||
if ($notification->getSubject() === 'calendar_reminder') {
|
||||
$subjectParameters = $notification->getSubjectParameters();
|
||||
$notification->setParsedSubject($this->processEventTitle($subjectParameters));
|
||||
|
||||
$messageParameters = $notification->getMessageParameters();
|
||||
$notification->setParsedMessage($this->processEventDescription($messageParameters));
|
||||
$notification->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'places/calendar.svg')));
|
||||
return $notification;
|
||||
}
|
||||
// Unknown subject => Unknown notification => throw
|
||||
throw new \InvalidArgumentException('Unknown subject');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $event
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function processEventTitle(array $event): string
|
||||
{
|
||||
$event_datetime = new \DateTime();
|
||||
$event_datetime->setTimestamp($event['start']);
|
||||
$now = new \DateTime();
|
||||
|
||||
$diff = $event_datetime->diff($now);
|
||||
|
||||
foreach (self::$units as $attribute => $unit) {
|
||||
$count = $diff->$attribute;
|
||||
if (0 !== $count) {
|
||||
return $this->getPluralizedTitle($count, $diff->invert, $unit, $event['title']);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $count
|
||||
* @param int $invert
|
||||
* @param string $unit
|
||||
* @param string $title
|
||||
* @return string
|
||||
*/
|
||||
private function getPluralizedTitle(int $count, int $invert, string $unit, string $title): string
|
||||
{
|
||||
if ($invert) {
|
||||
return $this->l->n('%s (in one %s)', '%s (in %n %ss)', $count, [$title, $unit]);
|
||||
}
|
||||
// This should probably not show up
|
||||
return $this->l->n('%s (one %s ago)', '%s (%n %ss ago)', $count, [$title, $unit]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $event
|
||||
* @return string
|
||||
*/
|
||||
private function processEventDescription(array $event): string
|
||||
{
|
||||
$description = [
|
||||
$this->l->t('Calendar: %s', $event['calendar']),
|
||||
$this->l->t('Date: %s', $event['when']),
|
||||
];
|
||||
|
||||
if ($event['description']) {
|
||||
$description[] = $this->l->t('Description: %s', $event['description']);
|
||||
}
|
||||
if ($event['location']) {
|
||||
$description[] = $this->l->t('Where: %s', $event['location']);
|
||||
}
|
||||
return implode('<br>', $description);
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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 OC\User\NoUserException;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use Sabre\VObject;
|
||||
use Sabre\VObject\Component\VAlarm;
|
||||
use Sabre\VObject\Reader;
|
||||
|
||||
class ReminderService {
|
||||
|
||||
/** @var Backend */
|
||||
private $backend;
|
||||
|
||||
/** @var NotificationProviderManager */
|
||||
private $notificationProviderManager;
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/** @var IGroupManager */
|
||||
private $groupManager;
|
||||
|
||||
/** @var IUserSession */
|
||||
private $userSession;
|
||||
|
||||
public const REMINDER_TYPE_EMAIL = 'EMAIL';
|
||||
public const REMINDER_TYPE_DISPLAY = 'DISPLAY';
|
||||
public const REMINDER_TYPE_AUDIO = 'AUDIO';
|
||||
|
||||
public const REMINDER_TYPES = [self::REMINDER_TYPE_EMAIL, self::REMINDER_TYPE_DISPLAY, self::REMINDER_TYPE_AUDIO];
|
||||
|
||||
public function __construct(Backend $backend,
|
||||
NotificationProviderManager $notificationProviderManager,
|
||||
IUserManager $userManager,
|
||||
IGroupManager $groupManager,
|
||||
IUserSession $userSession) {
|
||||
$this->backend = $backend;
|
||||
$this->notificationProviderManager = $notificationProviderManager;
|
||||
$this->userManager = $userManager;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->userSession = $userSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process reminders to activate
|
||||
*
|
||||
* @throws NoUserException
|
||||
* @throws NotificationProvider\ProviderNotAvailableException
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
*/
|
||||
public function processReminders(): void
|
||||
{
|
||||
|
||||
$reminders = $this->backend->getRemindersToProcess();
|
||||
|
||||
foreach ($reminders as $reminder) {
|
||||
$calendarData = Reader::read($reminder['calendardata']);
|
||||
|
||||
$user = $this->userManager->get($reminder['uid']);
|
||||
|
||||
if ($user === null) {
|
||||
throw new NoUserException('User not found for calendar');
|
||||
}
|
||||
|
||||
$notificationProvider = $this->notificationProviderManager->getProvider($reminder['type']);
|
||||
$notificationProvider->send($calendarData, $reminder['displayname'], $user);
|
||||
$this->backend->removeReminder($reminder['id']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves reminders when a calendar object with some alarms was created/updated/deleted
|
||||
*
|
||||
* @param string $action
|
||||
* @param array $calendarData
|
||||
* @param array $shares
|
||||
* @param array $objectData
|
||||
* @return void
|
||||
* @throws VObject\InvalidDataException
|
||||
* @throws NoUserException
|
||||
*/
|
||||
public function onTouchCalendarObject(string $action, array $calendarData, array $shares, array $objectData): void
|
||||
{
|
||||
if (!isset($calendarData['principaluri'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always remove existing reminders for this event
|
||||
$this->backend->cleanRemindersForEvent($objectData['calendarid'], $objectData['uri']);
|
||||
|
||||
/**
|
||||
* If we are deleting the event, no need to go further
|
||||
*/
|
||||
if ($action === '\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject') {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = $this->userSession->getUser();
|
||||
|
||||
if ($user === null) {
|
||||
throw new NoUserException('No user in session');
|
||||
}
|
||||
|
||||
$users = $this->getUsersForShares($shares);
|
||||
|
||||
$users[] = $user->getUID();
|
||||
|
||||
$vobject = VObject\Reader::read($objectData['calendardata']);
|
||||
|
||||
foreach ($vobject->VEVENT->VALARM as $alarm) {
|
||||
if ($alarm instanceof VAlarm) {
|
||||
$type = strtoupper($alarm->ACTION->getValue());
|
||||
if (in_array($type, self::REMINDER_TYPES, true)) {
|
||||
$time = $alarm->getEffectiveTriggerTime();
|
||||
|
||||
foreach ($users as $uid) {
|
||||
$this->backend->insertReminder(
|
||||
$uid,
|
||||
$objectData['calendarid'],
|
||||
$objectData['uri'],
|
||||
$type,
|
||||
$time->getTimestamp(),
|
||||
$vobject->VEVENT->DTSTART->getDateTime()->getTimestamp());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all users that have access to a given calendar
|
||||
*
|
||||
* @param array $shares
|
||||
* @return string[]
|
||||
*/
|
||||
private function getUsersForShares(array $shares): array
|
||||
{
|
||||
$users = $groups = [];
|
||||
foreach ($shares as $share) {
|
||||
$principal = explode('/', $share['{http://owncloud.org/ns}principal']);
|
||||
if ($principal[1] === 'users') {
|
||||
$users[] = $principal[2];
|
||||
} else if ($principal[1] === 'groups') {
|
||||
$groups[] = $principal[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($groups)) {
|
||||
foreach ($groups as $gid) {
|
||||
$group = $this->groupManager->get($gid);
|
||||
if ($group instanceof IGroup) {
|
||||
foreach ($group->getUsers() as $user) {
|
||||
$users[] = $user->getUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($users);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\DAV\Migration;
|
||||
|
||||
use Closure;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
*/
|
||||
class Version1007Date20181005133326 extends SimpleMigrationStep {
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if (!$schema->hasTable('calendar_reminders')) {
|
||||
$table = $schema->createTable('calendar_reminders');
|
||||
|
||||
$table->addColumn('id', Type::BIGINT, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
'length' => 11,
|
||||
'unsigned' => true,
|
||||
]);
|
||||
$table->addColumn('uid', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
$table->addColumn('calendarid', Type::BIGINT, [
|
||||
'notnull' => false,
|
||||
'length' => 11,
|
||||
]);
|
||||
$table->addColumn('objecturi', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
$table->addColumn('type', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 255,
|
||||
]);
|
||||
$table->addColumn('notificationdate', Type::DATETIME, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('eventstartdate', Type::DATETIME, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
|
||||
$table->setPrimaryKey(['id']);
|
||||
$table->addIndex(['calendarid'], 'calendar_reminder_calendars');
|
||||
|
||||
return $schema;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright 2018, Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\BackgroundJob;
|
||||
|
||||
use OCA\DAV\BackgroundJob\EventReminderJob;
|
||||
use OCA\DAV\CalDAV\Reminder\ReminderService;
|
||||
use OCP\IConfig;
|
||||
use Test\TestCase;
|
||||
|
||||
class EventReminderJobTest extends TestCase {
|
||||
|
||||
/** @var ReminderService|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $reminderService;
|
||||
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $config;
|
||||
|
||||
/** @var EventReminderJob|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $backgroundJob;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->reminderService = $this->createMock(ReminderService::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
|
||||
$this->backgroundJob = new EventReminderJob($this->reminderService, $this->config);
|
||||
}
|
||||
|
||||
public function data(): array
|
||||
{
|
||||
return [[true], [false]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data
|
||||
* @param bool $sendEventReminders
|
||||
*/
|
||||
public function testRun(bool $sendEventReminders): void
|
||||
{
|
||||
$this->config->expects($this->once())->method('getAppValue')->with('dav', 'sendEventReminders', 'yes')->willReturn($sendEventReminders ? 'yes' : 'no');
|
||||
$this->reminderService->expects($this->exactly($sendEventReminders ? 1 : 0))->method('processReminders');
|
||||
|
||||
$this->backgroundJob->run([]);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder;
|
||||
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\IUser;
|
||||
use Test\TestCase;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
abstract class AbstractNotificationProviderTest extends TestCase {
|
||||
|
||||
/** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $logger;
|
||||
|
||||
/** @var L10NFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10nFactory;
|
||||
|
||||
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10n;
|
||||
|
||||
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $config;
|
||||
|
||||
/** @var AbstractNotificationProvider|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* @var VCalendar
|
||||
*/
|
||||
protected $vcalendar;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $calendarDisplayName;
|
||||
|
||||
/**
|
||||
* @var IUser|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = $this->createMock(ILogger::class);
|
||||
$this->l10nFactory = $this->createMock(L10NFactory::class);
|
||||
$this->l10n = $this->createMock(IL10N::class);
|
||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
|
||||
$this->vcalendar = new VCalendar();
|
||||
$this->vcalendar->add('VEVENT', [
|
||||
'SUMMARY' => 'Fellowship meeting',
|
||||
'DTSTART' => new \DateTime('2017-01-01 00:00:00') // 1483228800
|
||||
]);
|
||||
$this->calendarDisplayName = 'Personal';
|
||||
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCA\DAV\CalDAV\Reminder\Backend as ReminderBackend;
|
||||
use Test\TestCase;
|
||||
|
||||
class BackendTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Reminder Backend
|
||||
*
|
||||
* @var ReminderBackend|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
private $reminderBackend;
|
||||
|
||||
/** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $dbConnection;
|
||||
|
||||
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $timeFactory;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->dbConnection = $this->createMock(IDBConnection::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$this->reminderBackend = new ReminderBackend($this->dbConnection, $this->timeFactory);
|
||||
}
|
||||
|
||||
public function testCleanRemindersForEvent(): void
|
||||
{
|
||||
/** @var IQueryBuilder|\PHPUnit\Framework\MockObject\MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(IQueryBuilder::class);
|
||||
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
|
||||
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
|
||||
|
||||
$this->dbConnection->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->with()
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->method('expr')
|
||||
->will($this->returnValue($expr));
|
||||
|
||||
$expr->method('eq')
|
||||
->will($this->returnValueMap([
|
||||
['calendarid', 'createNamedParameter-1', null, 'WHERE_CLAUSE_1'],
|
||||
['objecturi', 'createNamedParameter-2', null, 'WHERE_CLAUSE_2'],
|
||||
]));
|
||||
$queryBuilder->method('createNamedParameter')
|
||||
->will($this->returnValueMap([
|
||||
[1, \PDO::PARAM_STR, null, 'createNamedParameter-1'],
|
||||
['object.ics', \PDO::PARAM_STR, null, 'createNamedParameter-2'],
|
||||
]));
|
||||
|
||||
$queryBuilder->expects($this->at(0))
|
||||
->method('delete')
|
||||
->with('calendar_reminders')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(3))
|
||||
->method('where')
|
||||
->with('WHERE_CLAUSE_1')
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->expects($this->at(6))
|
||||
->method('andWhere')
|
||||
->with('WHERE_CLAUSE_2')
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->expects($this->at(7))
|
||||
->method('execute')
|
||||
->with()
|
||||
->willReturn($stmt);
|
||||
|
||||
$this->reminderBackend->cleanRemindersForEvent(1, 'object.ics');
|
||||
}
|
||||
|
||||
public function testCleanRemindersForCalendar(): void
|
||||
{
|
||||
/** @var IQueryBuilder|\PHPUnit\Framework\MockObject\MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(IQueryBuilder::class);
|
||||
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
|
||||
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
|
||||
|
||||
$this->dbConnection->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->with()
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->method('expr')
|
||||
->will($this->returnValue($expr));
|
||||
|
||||
$expr->method('eq')
|
||||
->will($this->returnValueMap([
|
||||
['calendarid', 'createNamedParameter-1', null, 'WHERE_CLAUSE_1'],
|
||||
]));
|
||||
$queryBuilder->method('createNamedParameter')
|
||||
->will($this->returnValueMap([
|
||||
[1337, \PDO::PARAM_STR, null, 'createNamedParameter-1'],
|
||||
]));
|
||||
|
||||
$queryBuilder->expects($this->at(0))
|
||||
->method('delete')
|
||||
->with('calendar_reminders')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(3))
|
||||
->method('where')
|
||||
->with('WHERE_CLAUSE_1')
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->expects($this->at(4))
|
||||
->method('execute')
|
||||
->with()
|
||||
->willReturn($stmt);
|
||||
|
||||
$this->reminderBackend->cleanRemindersForCalendar(1337);
|
||||
}
|
||||
|
||||
public function testRemoveReminder(): void
|
||||
{
|
||||
/** @var IQueryBuilder|\PHPUnit\Framework\MockObject\MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(IQueryBuilder::class);
|
||||
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
|
||||
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
|
||||
|
||||
$this->dbConnection->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->with()
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->method('expr')
|
||||
->will($this->returnValue($expr));
|
||||
|
||||
$expr->method('eq')
|
||||
->will($this->returnValueMap([
|
||||
['id', 'createNamedParameter-1', null, 'WHERE_CLAUSE_1'],
|
||||
]));
|
||||
$queryBuilder->method('createNamedParameter')
|
||||
->will($this->returnValueMap([
|
||||
[16, \PDO::PARAM_STR, null, 'createNamedParameter-1'],
|
||||
]));
|
||||
|
||||
$queryBuilder->expects($this->at(0))
|
||||
->method('delete')
|
||||
->with('calendar_reminders')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(3))
|
||||
->method('where')
|
||||
->with('WHERE_CLAUSE_1')
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->expects($this->at(4))
|
||||
->method('execute')
|
||||
->with()
|
||||
->willReturn($stmt);
|
||||
|
||||
$this->reminderBackend->removeReminder(16);
|
||||
}
|
||||
|
||||
public function testGetRemindersToProcess(): void
|
||||
{
|
||||
$dbData = [[
|
||||
'cr.id' => 30,
|
||||
'cr.calendarid' => 3,
|
||||
'cr.objecturi' => 'object.ics',
|
||||
'cr.type' => 'EMAIL',
|
||||
'cr.notificationdate' => 1337,
|
||||
'cr.uid' => 'user1',
|
||||
'co.calendardata' => 'BEGIN:VCALENDAR',
|
||||
'c.displayname' => 'My Calendar'
|
||||
]];
|
||||
|
||||
$this->timeFactory->expects($this->exactly(2))
|
||||
->method('getTime')
|
||||
->with()
|
||||
->willReturn(1337);
|
||||
|
||||
/** @var IQueryBuilder|\PHPUnit\Framework\MockObject\MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(IQueryBuilder::class);
|
||||
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
|
||||
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
|
||||
|
||||
$this->dbConnection->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->with()
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->method('expr')
|
||||
->willReturn($expr);
|
||||
|
||||
$expr->method('eq')
|
||||
->willReturnMap([
|
||||
['cr.calendarid', 'c.id', null, 'EQ_CLAUSE_1'],
|
||||
['co.uri', 'cr.objecturi', null, 'EQ_CLAUSE_2'],
|
||||
]);
|
||||
$expr->method('andX')
|
||||
->willReturnMap([
|
||||
['EQ_CLAUSE_1', 'EQ_CLAUSE_2', 'ANDX_CLAUSE'],
|
||||
]);
|
||||
|
||||
$expr->method('lte')
|
||||
->with('cr.notificationdate', 'createNamedParameter-1', null)
|
||||
->willReturn('LTE_CLAUSE_1');
|
||||
|
||||
$expr->method('gte')
|
||||
->with('cr.eventstartdate', 'createNamedParameter-1', null)
|
||||
->willReturn('GTE_CLAUSE_2');
|
||||
|
||||
$queryBuilder->method('createNamedParameter')
|
||||
->willReturnMap([
|
||||
[1337, \PDO::PARAM_STR, null, 'createNamedParameter-1'],
|
||||
]);
|
||||
|
||||
$queryBuilder->expects($this->at(0))
|
||||
->method('select')
|
||||
->with(['cr.id', 'cr.calendarid', 'cr.objecturi', 'cr.type', 'cr.notificationdate', 'cr.uid', 'co.calendardata', 'c.displayname'])
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(1))
|
||||
->method('from')
|
||||
->with('calendar_reminders', 'cr')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(4))
|
||||
->method('where')
|
||||
->with('LTE_CLAUSE_1')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(7))
|
||||
->method('andWhere')
|
||||
->with('GTE_CLAUSE_2')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(9))
|
||||
->method('leftJoin')
|
||||
->with('cr', 'calendars', 'c', 'EQ_CLAUSE_1')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(13))
|
||||
->method('leftJoin')
|
||||
->with('cr', 'calendarobjects', 'co', 'ANDX_CLAUSE')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(14))
|
||||
->method('execute')
|
||||
->with()
|
||||
->willReturn($stmt);
|
||||
|
||||
$stmt->expects($this->once())
|
||||
->method('fetchAll')
|
||||
->with()
|
||||
->willReturn($dbData);
|
||||
|
||||
$actual = $this->reminderBackend->getRemindersToProcess();
|
||||
$this->assertEquals($dbData, $actual);
|
||||
}
|
||||
|
||||
public function testInsertReminder(): void
|
||||
{
|
||||
/** @var IQueryBuilder|\PHPUnit\Framework\MockObject\MockObject $queryBuilder */
|
||||
$queryBuilder = $this->createMock(IQueryBuilder::class);
|
||||
$stmt = $this->createMock(\Doctrine\DBAL\Driver\Statement::class);
|
||||
$expr = $this->createMock(\OCP\DB\QueryBuilder\IExpressionBuilder::class);
|
||||
|
||||
$this->dbConnection->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->with()
|
||||
->will($this->returnValue($queryBuilder));
|
||||
$queryBuilder->method('expr')
|
||||
->will($this->returnValue($expr));
|
||||
|
||||
$queryBuilder->method('createNamedParameter')
|
||||
->will($this->returnValueMap([
|
||||
['user1', \PDO::PARAM_STR, null, 'createNamedParameter-1'],
|
||||
['1', \PDO::PARAM_STR, null, 'createNamedParameter-2'],
|
||||
['object.ics', \PDO::PARAM_STR, null, 'createNamedParameter-3'],
|
||||
['EMAIL', \PDO::PARAM_STR, null, 'createNamedParameter-4'],
|
||||
[1227, \PDO::PARAM_STR, null, 'createNamedParameter-5'],
|
||||
[1337, \PDO::PARAM_STR, null, 'createNamedParameter-6'],
|
||||
]));
|
||||
|
||||
$queryBuilder->expects($this->at(0))
|
||||
->method('insert')
|
||||
->with('calendar_reminders')
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(7))
|
||||
->method('values')
|
||||
->with([
|
||||
'uid' => 'createNamedParameter-1',
|
||||
'calendarid' => 'createNamedParameter-2',
|
||||
'objecturi' => 'createNamedParameter-3',
|
||||
'type' => 'createNamedParameter-4',
|
||||
'notificationdate' => 'createNamedParameter-5',
|
||||
'eventstartdate' => 'createNamedParameter-6',
|
||||
])
|
||||
->willReturn($queryBuilder);
|
||||
$queryBuilder->expects($this->at(8))
|
||||
->method('execute')
|
||||
->with()
|
||||
->willReturn($stmt);
|
||||
|
||||
$actual = $this->reminderBackend->insertReminder('user1', '1', 'object.ics', 'EMAIL', 1227, 1337);
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder\NotificationProvider;
|
||||
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\EmailProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\IUser;
|
||||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\Mail\IAttachment;
|
||||
use OCP\Mail\IMessage;
|
||||
use Test\TestCase;
|
||||
use OCA\DAV\Tests\unit\CalDAV\Reminder\AbstractNotificationProviderTest;
|
||||
|
||||
class EmailProviderTest extends AbstractNotificationProviderTest {
|
||||
|
||||
const USER_EMAIL = 'frodo@hobb.it';
|
||||
|
||||
/** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $logger;
|
||||
|
||||
/** @var L10NFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10nFactory;
|
||||
|
||||
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10n;
|
||||
|
||||
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $config;
|
||||
|
||||
/** @var IMailer|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $mailer;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->mailer = $this->createMock(IMailer::class);
|
||||
|
||||
$this->provider = new EmailProvider(
|
||||
$this->config,
|
||||
$this->mailer,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->urlGenerator
|
||||
);
|
||||
}
|
||||
|
||||
public function testSendWithNoUserEmail(): void
|
||||
{
|
||||
$this->user->expects($this->once())
|
||||
->method('getEMailAddress')
|
||||
->with()
|
||||
->willReturn(null);
|
||||
|
||||
$this->mailer
|
||||
->expects($this->never())
|
||||
->method('send');
|
||||
|
||||
$this->provider->send($this->vcalendar, $this->calendarDisplayName, $this->user);
|
||||
}
|
||||
|
||||
public function testSendWithFailedRecipients(): void
|
||||
{
|
||||
$this->user->expects($this->exactly(2))
|
||||
->method('getEMailAddress')
|
||||
->with()
|
||||
->willReturn(self::USER_EMAIL);
|
||||
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('send')
|
||||
->willReturn([self::USER_EMAIL])
|
||||
;
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('error');
|
||||
|
||||
$l10n = $this->createMock(IL10N::class);
|
||||
$this->l10nFactory
|
||||
->method('get')
|
||||
->willReturn($l10n);
|
||||
|
||||
$this->provider->send($this->vcalendar, $this->calendarDisplayName, $this->user);
|
||||
}
|
||||
|
||||
public function testSendWithMailerFailure(): void
|
||||
{
|
||||
$this->user->expects($this->exactly(2))
|
||||
->method('getEMailAddress')
|
||||
->with()
|
||||
->willReturn(self::USER_EMAIL);
|
||||
|
||||
$ex = new \Exception();
|
||||
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('send')
|
||||
->will($this->throwException($ex))
|
||||
;
|
||||
|
||||
$this->logger
|
||||
->expects($this->once())
|
||||
->method('logException')
|
||||
->with($ex, ['app' => 'dav']);
|
||||
|
||||
$l10n = $this->createMock(IL10N::class);
|
||||
$this->l10nFactory
|
||||
->method('get')
|
||||
->willReturn($l10n);
|
||||
|
||||
$this->provider->send($this->vcalendar, $this->calendarDisplayName, $this->user);
|
||||
}
|
||||
|
||||
public function testSend(): void
|
||||
{
|
||||
$this->user->expects($this->exactly(2))
|
||||
->method('getEMailAddress')
|
||||
->with()
|
||||
->willReturn(self::USER_EMAIL);
|
||||
|
||||
$this->user->expects($this->once())
|
||||
->method('getDisplayName')
|
||||
->with()
|
||||
->willReturn('Frodo');
|
||||
|
||||
$this->urlGenerator
|
||||
->expects($this->exactly(2))
|
||||
->method('getAbsoluteURL');
|
||||
|
||||
$this->urlGenerator
|
||||
->expects($this->exactly(2))
|
||||
->method('imagePath');
|
||||
|
||||
$mailMessage = $this->createMock(IMessage::class);
|
||||
$mailMessage->expects($this->once())
|
||||
->method('setFrom')
|
||||
->with([\OCP\Util::getDefaultEmailAddress('invitations-noreply') => 'Nextcloud'])
|
||||
->willReturn($mailMessage);
|
||||
|
||||
$mailMessage->expects($this->once())
|
||||
->method('setTo')
|
||||
->with([self::USER_EMAIL => 'Frodo'])
|
||||
->willReturn($mailMessage);
|
||||
|
||||
$mailMessage
|
||||
->expects($this->never())
|
||||
->method('setReplyTo')
|
||||
->willReturn($mailMessage);
|
||||
|
||||
$emailTemplate = $this->createMock(IEMailTemplate::class);
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('createEMailTemplate')
|
||||
->willReturn($emailTemplate);
|
||||
|
||||
$emailTemplate->expects($this->once())
|
||||
->method('setSubject')
|
||||
->with('Notification: Fellowship meeting');
|
||||
|
||||
$emailTemplate->expects($this->once())
|
||||
->method('addHeader');
|
||||
|
||||
$emailTemplate->expects($this->once())
|
||||
->method('addHeading');
|
||||
|
||||
$emailTemplate->expects($this->exactly(2))
|
||||
->method('addBodyListItem');
|
||||
|
||||
$emailTemplate->expects($this->once())
|
||||
->method('addFooter');
|
||||
|
||||
$mailMessage->expects($this->once())
|
||||
->method('useTemplate')
|
||||
->with($emailTemplate);
|
||||
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('createMessage')
|
||||
->willReturn($mailMessage);
|
||||
|
||||
$emailAttachment = $this->createMock(IAttachment::class);
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('createAttachment')
|
||||
->willReturn($emailAttachment);
|
||||
|
||||
$this->mailer
|
||||
->expects($this->once())
|
||||
->method('send');
|
||||
|
||||
$l10n = $this->createMock(IL10N::class);
|
||||
$this->l10nFactory
|
||||
->method('get')
|
||||
->willReturn($l10n);
|
||||
|
||||
$this->provider->send($this->vcalendar, $this->calendarDisplayName, $this->user);
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder\NotificationProvider;
|
||||
|
||||
use OCA\DAV\AppInfo\Application;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\ILogger;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory as L10NFactory;
|
||||
use OCP\IUser;
|
||||
use OCP\Notification\IManager;
|
||||
use OCP\Notification\INotification;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use Test\TestCase;
|
||||
use OCA\DAV\Tests\unit\CalDAV\Reminder\AbstractNotificationProviderTest;
|
||||
|
||||
class PushProviderTest extends AbstractNotificationProviderTest {
|
||||
|
||||
/** @var ILogger|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $logger;
|
||||
|
||||
/** @var L10NFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10nFactory;
|
||||
|
||||
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l10n;
|
||||
|
||||
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $urlGenerator;
|
||||
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $config;
|
||||
|
||||
/** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $manager;
|
||||
|
||||
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $timeFactory;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->manager = $this->createMock(IManager::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
|
||||
$this->provider = new PushProvider(
|
||||
$this->config,
|
||||
$this->manager,
|
||||
$this->logger,
|
||||
$this->l10nFactory,
|
||||
$this->urlGenerator,
|
||||
$this->timeFactory
|
||||
);
|
||||
}
|
||||
|
||||
public function testSend(): void
|
||||
{
|
||||
$notification = $this->createMock(INotification::class);
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setApp')
|
||||
->with(Application::APP_ID)
|
||||
->willReturn($notification);
|
||||
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setUser')
|
||||
->willReturn($notification)
|
||||
;
|
||||
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setDateTime')
|
||||
->willReturn($notification)
|
||||
;
|
||||
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setObject')
|
||||
->willReturn($notification)
|
||||
;
|
||||
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setSubject')
|
||||
->willReturn($notification)
|
||||
;
|
||||
|
||||
$notification
|
||||
->expects($this->once())
|
||||
->method('setMessage')
|
||||
->willReturn($notification)
|
||||
;
|
||||
|
||||
$this->manager
|
||||
->expects($this->once())
|
||||
->method('createNotification')
|
||||
->willReturn($notification);
|
||||
|
||||
$this->manager
|
||||
->expects($this->once())
|
||||
->method('notify')
|
||||
->with($notification);
|
||||
|
||||
$l10n = $this->createMock(IL10N::class);
|
||||
$this->l10nFactory
|
||||
->method('get')
|
||||
->willReturn($l10n);
|
||||
|
||||
$this->timeFactory->expects($this->once())
|
||||
->method('getDateTime')
|
||||
->with()
|
||||
->willReturn(new \DateTime());
|
||||
|
||||
$this->provider->send($this->vcalendar, $this->calendarDisplayName, $this->user);
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder;
|
||||
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\EmailProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException;
|
||||
use OCA\DAV\Capabilities;
|
||||
use Test\TestCase;
|
||||
|
||||
class NotificationProviderManagerTest extends TestCase {
|
||||
|
||||
/** @var NotificationProviderManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $providerManager;
|
||||
|
||||
/**
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->providerManager = new NotificationProviderManager();
|
||||
$this->providerManager->registerProvider(EmailProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException
|
||||
* @expectedExceptionMessage Type NOT EXISTENT is not an accepted type of notification
|
||||
* @throws ProviderNotAvailableException
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
*/
|
||||
public function testGetProviderForUnknownType(): void
|
||||
{
|
||||
$this->providerManager->getProvider('NOT EXISTENT');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException
|
||||
* @expectedExceptionMessage No notification provider for type AUDIO available
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
* @throws ProviderNotAvailableException
|
||||
*/
|
||||
public function testGetProviderForUnRegisteredType(): void
|
||||
{
|
||||
$this->providerManager->getProvider('AUDIO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
* @throws ProviderNotAvailableException
|
||||
*/
|
||||
public function testGetProvider(): void
|
||||
{
|
||||
$provider = $this->providerManager->getProvider('EMAIL');
|
||||
$this->assertInstanceOf(EmailProvider::class, $provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotificationTypeDoesNotExistException
|
||||
* @throws ProviderNotAvailableException
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function testRegisterProvider(): void
|
||||
{
|
||||
$this->providerManager->registerProvider(PushProvider::class);
|
||||
$provider = $this->providerManager->getProvider('DISPLAY');
|
||||
$this->assertInstanceOf(PushProvider::class, $provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedExceptionMessage Invalid notification provider registered
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function testRegisterBadProvider(): void
|
||||
{
|
||||
$this->providerManager->registerProvider(Capabilities::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder;
|
||||
|
||||
use OCA\DAV\AppInfo\Application;
|
||||
use OCA\DAV\CalDAV\Reminder\Notifier;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\L10N\IFactory;
|
||||
use OCP\Notification\INotification;
|
||||
use Test\TestCase;
|
||||
|
||||
class NotifierTest extends TestCase {
|
||||
/** @var Notifier */
|
||||
protected $notifier;
|
||||
|
||||
/** @var IFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $factory;
|
||||
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $urlGenerator;
|
||||
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected $l;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
$this->l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function($string, $args) {
|
||||
return vsprintf($string, $args);
|
||||
});
|
||||
$this->l->expects($this->any())
|
||||
->method('n')
|
||||
->willReturnCallback(function($textSingular, $textPlural, $count, $args) {
|
||||
$text = $count === 1 ? $textSingular : $textPlural;
|
||||
$text = str_replace('%n', (string)$count, $text);
|
||||
return vsprintf($text, $args);
|
||||
});
|
||||
$this->factory = $this->createMock(IFactory::class);
|
||||
$this->factory->expects($this->any())
|
||||
->method('get')
|
||||
->willReturn($this->l);
|
||||
|
||||
$this->notifier = new Notifier(
|
||||
$this->factory,
|
||||
$this->urlGenerator
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Notification not from this app
|
||||
*/
|
||||
public function testPrepareWrongApp(): void
|
||||
{
|
||||
/** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
|
||||
$notification = $this->createMock(INotification::class);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('getApp')
|
||||
->willReturn('notifications');
|
||||
$notification->expects($this->never())
|
||||
->method('getSubject');
|
||||
|
||||
$this->notifier->prepare($notification, 'en');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Unknown subject
|
||||
*/
|
||||
public function testPrepareWrongSubject() {
|
||||
/** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
|
||||
$notification = $this->createMock(INotification::class);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('getApp')
|
||||
->willReturn(Application::APP_ID);
|
||||
$notification->expects($this->once())
|
||||
->method('getSubject')
|
||||
->willReturn('wrong subject');
|
||||
|
||||
$this->notifier->prepare($notification, 'en');
|
||||
}
|
||||
|
||||
public function dataPrepare(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'calendar_reminder',
|
||||
[
|
||||
'title' => 'foo',
|
||||
'start' => time() - 60 * 60 * 24
|
||||
],
|
||||
'foo (one day ago)',
|
||||
[
|
||||
'when' => 'foo',
|
||||
'description' => 'bar',
|
||||
'location' => 'NC Headquarters',
|
||||
'calendar' => 'Personal'
|
||||
],
|
||||
'Calendar: Personal<br>Date: foo<br>Description: bar<br>Where: NC Headquarters'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataPrepare
|
||||
*
|
||||
* @param string $subjectType
|
||||
* @param array $subjectParams
|
||||
* @param string $subject
|
||||
* @param array $messageParams
|
||||
* @param string $message
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testPrepare(string $subjectType, array $subjectParams, string $subject, array $messageParams, string $message): void
|
||||
{
|
||||
/** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
|
||||
$notification = $this->createMock(INotification::class);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('getApp')
|
||||
->willReturn(Application::APP_ID);
|
||||
$notification->expects($this->once())
|
||||
->method('getSubject')
|
||||
->willReturn($subjectType);
|
||||
$notification->expects($this->once())
|
||||
->method('getSubjectParameters')
|
||||
->willReturn($subjectParams);
|
||||
$notification->expects($this->once())
|
||||
->method('getMessageParameters')
|
||||
->willReturn($messageParams);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('setParsedSubject')
|
||||
->with($subject)
|
||||
->willReturnSelf();
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('setParsedMessage')
|
||||
->with($message)
|
||||
->willReturnSelf();
|
||||
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('imagePath')
|
||||
->with('core', 'places/calendar.svg')
|
||||
->willReturn('icon-url');
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('getAbsoluteURL')
|
||||
->with('icon-url')
|
||||
->willReturn('absolute-icon-url');
|
||||
$notification->expects($this->once())
|
||||
->method('setIcon')
|
||||
->with('absolute-icon-url')
|
||||
->willReturnSelf();
|
||||
|
||||
$return = $this->notifier->prepare($notification, 'en');
|
||||
|
||||
$this->assertEquals($notification, $return);
|
||||
}
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2019, Thomas Citharel
|
||||
*
|
||||
* @author Thomas Citharel <tcit@tcit.fr>
|
||||
*
|
||||
* @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\Tests\unit\CalDAV\Reminder;
|
||||
|
||||
use OCA\DAV\CalDAV\Reminder\AbstractNotificationProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\Backend;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\EmailProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
|
||||
use OCA\DAV\CalDAV\Reminder\ReminderService;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use Test\TestCase;
|
||||
|
||||
class ReminderServiceTest extends TestCase {
|
||||
|
||||
/** @var Backend|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $backend;
|
||||
|
||||
/** @var NotificationProviderManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $notificationProviderManager;
|
||||
|
||||
/** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $userManager;
|
||||
|
||||
/** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject*/
|
||||
private $groupManager;
|
||||
|
||||
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $userSession;
|
||||
|
||||
public const CALENDAR_DATA = <<<EOD
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Nextcloud calendar v1.6.4
|
||||
BEGIN:VEVENT
|
||||
CREATED:20160602T133732
|
||||
DTSTAMP:20160602T133732
|
||||
LAST-MODIFIED:20160602T133732
|
||||
UID:wej2z68l9h
|
||||
SUMMARY:Test Event
|
||||
LOCATION:Somewhere ...
|
||||
DESCRIPTION:maybe ....
|
||||
DTSTART;TZID=Europe/Berlin;VALUE=DATE:20160609
|
||||
DTEND;TZID=Europe/Berlin;VALUE=DATE:20160610
|
||||
BEGIN:VALARM
|
||||
ACTION:EMAIL
|
||||
TRIGGER:-PT15M
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
EOD;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->backend = $this->createMock(Backend::class);
|
||||
$this->notificationProviderManager = $this->createMock(NotificationProviderManager::class);
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
}
|
||||
|
||||
public function dataTestProcessReminders(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
[], null
|
||||
],
|
||||
[
|
||||
[
|
||||
[
|
||||
'calendardata' => self::CALENDAR_DATA,
|
||||
'displayname' => 'Personal',
|
||||
'type' => 'EMAIL',
|
||||
'uid' => 1,
|
||||
'id' => 1,
|
||||
],
|
||||
],
|
||||
$this->createMock(EmailProvider::class),
|
||||
],
|
||||
[
|
||||
[
|
||||
[
|
||||
'calendardata' => self::CALENDAR_DATA,
|
||||
'displayname' => 'Personal',
|
||||
'type' => 'DISPLAY',
|
||||
'uid' => 1,
|
||||
'id' => 1,
|
||||
],
|
||||
],
|
||||
$this->createMock(PushProvider::class),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataTestProcessReminders
|
||||
* @param array $reminders
|
||||
* @param AbstractNotificationProvider|null $notificationProvider
|
||||
* @throws \OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException
|
||||
* @throws \OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException
|
||||
* @throws \OC\User\NoUserException
|
||||
*/
|
||||
public function testProcessReminders(array $reminders, ?AbstractNotificationProvider $notificationProvider): void
|
||||
{
|
||||
$user = $this->createMock(IUser::class);
|
||||
|
||||
$this->backend->expects($this->once())->method('getRemindersToProcess')->willReturn($reminders);
|
||||
if (count($reminders) > 0) {
|
||||
$this->userManager->expects($this->exactly(count($reminders)))->method('get')->willReturn($user);
|
||||
$this->backend->expects($this->exactly(count($reminders)))->method('removeReminder');
|
||||
$this->notificationProviderManager->expects($this->exactly(count($reminders)))->method('getProvider')->willReturn($notificationProvider);
|
||||
}
|
||||
|
||||
$reminderService = new ReminderService($this->backend, $this->notificationProviderManager, $this->userManager, $this->groupManager, $this->userSession);
|
||||
$reminderService->processReminders();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException OC\User\NoUserException
|
||||
*/
|
||||
public function testProcessReminderWithBadUser(): void
|
||||
{
|
||||
$this->backend->expects($this->once())->method('getRemindersToProcess')->willReturn([
|
||||
[
|
||||
'calendardata' => self::CALENDAR_DATA,
|
||||
'type' => 'DISPLAY',
|
||||
'uid' => 1,
|
||||
'id' => 1,
|
||||
]
|
||||
]);
|
||||
$this->userManager->expects($this->once())->method('get')->with(1)->willReturn(null);
|
||||
$reminderService = new ReminderService($this->backend, $this->notificationProviderManager, $this->userManager, $this->groupManager, $this->userSession);
|
||||
$reminderService->processReminders();
|
||||
}
|
||||
|
||||
public function providesTouchCalendarObject(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject',
|
||||
[
|
||||
'principaluri' => 'principals/users/personal'
|
||||
],
|
||||
[],
|
||||
[
|
||||
'calendarid' => 1,
|
||||
'uri' => 'something.ics',
|
||||
],
|
||||
0
|
||||
],
|
||||
[
|
||||
'\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject',
|
||||
[
|
||||
'principaluri' => 'principals/users/personal'
|
||||
],
|
||||
[],
|
||||
[
|
||||
'calendarid' => 1,
|
||||
'uri' => 'something.ics',
|
||||
'calendardata' => self::CALENDAR_DATA
|
||||
],
|
||||
0
|
||||
],
|
||||
[
|
||||
'\OCA\DAV\CalDAV\CalDavBackend::updateCalendarObject',
|
||||
[
|
||||
'principaluri' => 'principals/users/someone',
|
||||
'uri' => 'personal'
|
||||
],
|
||||
[
|
||||
[
|
||||
'{http://owncloud.org/ns}principal' => 'principals/users/someone'
|
||||
]
|
||||
],
|
||||
[
|
||||
'calendarid' => 1,
|
||||
'uri' => 'something.ics',
|
||||
'calendardata' => self::CALENDAR_DATA
|
||||
],
|
||||
0
|
||||
],
|
||||
[
|
||||
'\OCA\DAV\CalDAV\CalDavBackend::createCalendarObject',
|
||||
[
|
||||
'principaluri' => 'principals/users/someone',
|
||||
'uri' => 'personal'
|
||||
],
|
||||
[
|
||||
[
|
||||
'{http://owncloud.org/ns}principal' => 'principals/groups/somegroup'
|
||||
]
|
||||
],
|
||||
[
|
||||
'calendarid' => 1,
|
||||
'uri' => 'something.ics',
|
||||
'calendardata' => self::CALENDAR_DATA
|
||||
],
|
||||
1
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providesTouchCalendarObject
|
||||
* @param string $action
|
||||
* @param array $calendarData
|
||||
* @param array $shares
|
||||
* @param array $objectData
|
||||
* @param int $numberOfGroups
|
||||
* @throws \OC\User\NoUserException
|
||||
* @throws \Sabre\VObject\InvalidDataException
|
||||
*/
|
||||
public function testOnTouchCalendarObject(string $action, array $calendarData, array $shares, array $objectData, int $numberOfGroups): void
|
||||
{
|
||||
$this->backend->expects($this->once())->method('cleanRemindersForEvent')->with($objectData['calendarid'], $objectData['uri']);
|
||||
|
||||
if ($action !== '\OCA\DAV\CalDAV\CalDavBackend::deleteCalendarObject') {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->once())->method('getUID')->willReturn('user');
|
||||
|
||||
$this->userSession->expects($this->once())->method('getUser')->willReturn($user);
|
||||
if ($numberOfGroups === 0) {
|
||||
$this->backend->expects($this->exactly(count($shares) + 1))->method('insertReminder');
|
||||
} else {
|
||||
$group = $this->createMock(IGroup::class);
|
||||
$groupUser = $this->createMock(IUser::class);
|
||||
$groupUser->expects($this->once())->method('getUID')->willReturn('groupuser');
|
||||
$group->expects($this->once())->method('getUsers')->willReturn([$groupUser]);
|
||||
$this->groupManager->expects($this->exactly($numberOfGroups))->method('get')->willReturn($group);
|
||||
}
|
||||
}
|
||||
$reminderService = new ReminderService($this->backend, $this->notificationProviderManager, $this->userManager, $this->groupManager, $this->userSession);
|
||||
$reminderService->onTouchCalendarObject($action, $calendarData, $shares, $objectData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException OC\User\NoUserException
|
||||
*/
|
||||
public function testOnTouchCalendarObjectWithNoSession(): void
|
||||
{
|
||||
$this->backend->expects($this->once())->method('cleanRemindersForEvent');
|
||||
$this->userSession->expects($this->once())->method('getUser')->willReturn(null);
|
||||
|
||||
$reminderService = new ReminderService($this->backend, $this->notificationProviderManager, $this->userManager, $this->groupManager, $this->userSession);
|
||||
$reminderService->onTouchCalendarObject('', ['principaluri' => 'foo'], [], ['calendarid' => 1, 'uri' => 'bar']);
|
||||
}
|
||||
|
||||
public function testOnTouchCalendarObjectWithNoCalendarURI(): void
|
||||
{
|
||||
$reminderService = new ReminderService($this->backend, $this->notificationProviderManager, $this->userManager, $this->groupManager, $this->userSession);
|
||||
$this->assertNull($reminderService->onTouchCalendarObject('', [], [], []));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue