feat(caldav): Create personal event for out-of-office messages

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
pull/41340/head
Christoph Wurst 2 years ago
parent f313b12d54
commit 5b7a5474b9
No known key found for this signature in database
GPG Key ID: CC42AC2A7F0E56D8
  1. 2
      apps/dav/composer/composer/autoload_classmap.php
  2. 2
      apps/dav/composer/composer/autoload_static.php
  3. 8
      apps/dav/lib/AppInfo/Application.php
  4. 5
      apps/dav/lib/Db/Absence.php
  5. 210
      apps/dav/lib/Listener/OutOfOfficeListener.php
  6. 4
      apps/dav/lib/Server.php
  7. 35
      apps/dav/lib/ServerFactory.php
  8. 12
      apps/dav/lib/Service/AbsenceService.php
  9. 546
      apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php

@ -265,6 +265,7 @@ return array(
'OCA\\DAV\\Listener\\CalendarShareUpdateListener' => $baseDir . '/../lib/Listener/CalendarShareUpdateListener.php',
'OCA\\DAV\\Listener\\CardListener' => $baseDir . '/../lib/Listener/CardListener.php',
'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => $baseDir . '/../lib/Listener/ClearPhotoCacheListener.php',
'OCA\\DAV\\Listener\\OutOfOfficeListener' => $baseDir . '/../lib/Listener/OutOfOfficeListener.php',
'OCA\\DAV\\Listener\\SubscriptionListener' => $baseDir . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => $baseDir . '/../lib/Listener/TrustedServerRemovedListener.php',
'OCA\\DAV\\Listener\\UserPreferenceListener' => $baseDir . '/../lib/Listener/UserPreferenceListener.php',
@ -316,6 +317,7 @@ return array(
'OCA\\DAV\\Search\\EventsSearchProvider' => $baseDir . '/../lib/Search/EventsSearchProvider.php',
'OCA\\DAV\\Search\\TasksSearchProvider' => $baseDir . '/../lib/Search/TasksSearchProvider.php',
'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php',
'OCA\\DAV\\ServerFactory' => $baseDir . '/../lib/ServerFactory.php',
'OCA\\DAV\\Service\\AbsenceService' => $baseDir . '/../lib/Service/AbsenceService.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => $baseDir . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php',

@ -280,6 +280,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Listener\\CalendarShareUpdateListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarShareUpdateListener.php',
'OCA\\DAV\\Listener\\CardListener' => __DIR__ . '/..' . '/../lib/Listener/CardListener.php',
'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => __DIR__ . '/..' . '/../lib/Listener/ClearPhotoCacheListener.php',
'OCA\\DAV\\Listener\\OutOfOfficeListener' => __DIR__ . '/..' . '/../lib/Listener/OutOfOfficeListener.php',
'OCA\\DAV\\Listener\\SubscriptionListener' => __DIR__ . '/..' . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Listener\\TrustedServerRemovedListener' => __DIR__ . '/..' . '/../lib/Listener/TrustedServerRemovedListener.php',
'OCA\\DAV\\Listener\\UserPreferenceListener' => __DIR__ . '/..' . '/../lib/Listener/UserPreferenceListener.php',
@ -331,6 +332,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Search\\EventsSearchProvider' => __DIR__ . '/..' . '/../lib/Search/EventsSearchProvider.php',
'OCA\\DAV\\Search\\TasksSearchProvider' => __DIR__ . '/..' . '/../lib/Search/TasksSearchProvider.php',
'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php',
'OCA\\DAV\\ServerFactory' => __DIR__ . '/..' . '/../lib/ServerFactory.php',
'OCA\\DAV\\Service\\AbsenceService' => __DIR__ . '/..' . '/../lib/Service/AbsenceService.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => __DIR__ . '/..' . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php',

@ -69,6 +69,7 @@ use OCA\DAV\Events\CardDeletedEvent;
use OCA\DAV\Events\CardUpdatedEvent;
use OCA\DAV\Events\SubscriptionCreatedEvent;
use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCA\DAV\Listener\OutOfOfficeListener;
use OCP\Accounts\UserUpdatedEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\Events\TrustedServerRemovedEvent;
@ -103,6 +104,9 @@ use OCP\Config\BeforePreferenceSetEvent;
use OCP\Contacts\IManager as IContactsManager;
use OCP\Files\AppData\IAppDataFactory;
use OCP\IUser;
use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeClearedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
@ -195,6 +199,10 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(BeforePreferenceDeletedEvent::class, UserPreferenceListener::class);
$context->registerEventListener(BeforePreferenceSetEvent::class, UserPreferenceListener::class);
$context->registerEventListener(OutOfOfficeChangedEvent::class, OutOfOfficeListener::class);
$context->registerEventListener(OutOfOfficeClearedEvent::class, OutOfOfficeListener::class);
$context->registerEventListener(OutOfOfficeScheduledEvent::class, OutOfOfficeListener::class);
$context->registerNotifierService(Notifier::class);
$context->registerCalendarProvider(CalendarProvider::class);

@ -27,6 +27,7 @@ declare(strict_types=1);
namespace OCA\DAV\Db;
use DateTimeImmutable;
use Exception;
use InvalidArgumentException;
use JsonSerializable;
use OC\User\OutOfOfficeData;
@ -70,8 +71,10 @@ class Absence extends Entity implements JsonSerializable {
if ($user->getUID() !== $this->getUserId()) {
throw new InvalidArgumentException("The user doesn't match the user id of this absence! Expected " . $this->getUserId() . ", got " . $user->getUID());
}
if ($this->getId() === null) {
throw new Exception('Creating out-of-office data without ID');
}
//$user = $userManager->get($this->getUserId());
$startDate = new DateTimeImmutable($this->getFirstDay());
$endDate = new DateTimeImmutable($this->getLastDay());
return new OutOfOfficeData(

@ -0,0 +1,210 @@
<?php
declare(strict_types=1);
/**
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @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\Listener;
use DateTimeImmutable;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\ServerFactory;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IConfig;
use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeClearedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
use OCP\User\IOutOfOfficeData;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Component\VEvent;
use Sabre\VObject\Component\VTimeZone;
use Sabre\VObject\Reader;
use function fclose;
use function fopen;
use function fwrite;
use function rewind;
/**
* @template-implements IEventListener<OutOfOfficeScheduledEvent|OutOfOfficeChangedEvent|OutOfOfficeClearedEvent>
*/
class OutOfOfficeListener implements IEventListener {
public function __construct(private ServerFactory $serverFactory,
private IConfig $appConfig,
private LoggerInterface $logger) {
}
public function handle(Event $event): void {
if ($event instanceof OutOfOfficeScheduledEvent) {
$userId = $event->getData()->getUser()->getUID();
$principal = "principals/users/$userId";
$calendarNode = $this->getCalendarNode($principal, $userId);
if ($calendarNode === null) {
return;
}
$tz = $calendarNode->getProperties([])['{urn:ietf:params:xml:ns:caldav}calendar-timezone'] ?? null;
$vCalendarEvent = $this->createVCalendarEvent($event->getData(), $tz);
$stream = fopen('php://memory', 'rb+');
try {
fwrite($stream, $vCalendarEvent->serialize());
rewind($stream);
$calendarNode->createFile(
$this->getEventFileName($event->getData()->getId()),
$stream,
);
} finally {
fclose($stream);
}
} else if ($event instanceof OutOfOfficeChangedEvent) {
$userId = $event->getData()->getUser()->getUID();
$principal = "principals/users/$userId";
$calendarNode = $this->getCalendarNode($principal, $userId);
if ($calendarNode === null) {
return;
}
$tz = $calendarNode->getProperties([])['{urn:ietf:params:xml:ns:caldav}calendar-timezone'] ?? null;
$vCalendarEvent = $this->createVCalendarEvent($event->getData(), $tz);
try {
$oldEvent = $calendarNode->getChild($this->getEventFileName($event->getData()->getId()));
$oldEvent->put($vCalendarEvent->serialize());
return;
} catch (NotFound) {
$stream = fopen('php://memory', 'rb+');
try {
fwrite($stream, $vCalendarEvent->serialize());
rewind($stream);
$calendarNode->createFile(
$this->getEventFileName($event->getData()->getId()),
$stream,
);
} finally {
fclose($stream);
}
}
} else if ($event instanceof OutOfOfficeClearedEvent) {
$userId = $event->getData()->getUser()->getUID();
$principal = "principals/users/$userId";
$calendarNode = $this->getCalendarNode($principal, $userId);
if ($calendarNode === null) {
return;
}
try {
$oldEvent = $calendarNode->getChild($this->getEventFileName($event->getData()->getId()));
$oldEvent->delete();
} catch (NotFound) {
// The user must have deleted it or the default calendar changed -> ignore
}
}
}
private function getCalendarNode(string $principal, string $userId): ?Calendar {
$invitationServer = $this->serverFactory->createInviationResponseServer(false);
$server = $invitationServer->getServer();
/** @var \OCA\DAV\CalDAV\Plugin $caldavPlugin */
$caldavPlugin = $server->getPlugin('caldav');
$calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principal);
if ($calendarHomePath === null) {
$this->logger->debug('Principal has no calendar home path');
return null;
}
try {
/** @var CalendarHome $calendarHome */
$calendarHome = $server->tree->getNodeForPath($calendarHomePath);
} catch (NotFound $e) {
$this->logger->debug('Calendar home not found', [
'exception' => $e,
]);
return null;
}
$uri = $this->appConfig->getUserValue($userId, 'dav', 'defaultCalendar', CalDavBackend::PERSONAL_CALENDAR_URI);
try {
$calendarNode = $calendarHome->getChild($uri);
} catch (NotFound $e) {
$this->logger->debug('Personal calendar does not exist', [
'exception' => $e,
'uri' => $uri,
]);
return null;
}
if (!($calendarNode instanceof Calendar)) {
$this->logger->warning('Personal calendar node is not a calendar');
return null;
}
if ($calendarNode->isDeleted()) {
$this->logger->warning('Personal calendar has been deleted');
return null;
}
return $calendarNode;
}
private function getEventFileName(string $id): string {
return "out_of_office_$id.ics";
}
private function createVCalendarEvent(IOutOfOfficeData $data, ?string $timeZoneData): VCalendar {
$shortMessage = $data->getShortMessage();
$longMessage = $data->getMessage();
$start = (new DateTimeImmutable)
->setTimestamp($data->getStartDate())
->setTime(0, 0);
$end = (new DateTimeImmutable())
->setTimestamp($data->getEndDate())
->modify('+ 2 days')
->setTime(0, 0);
$vCalendar = new VCalendar();
$vCalendar->add('VEVENT', [
'SUMMARY' => $shortMessage,
'DESCRIPTION' => $longMessage,
'STATUS' => 'CONFIRMED',
'DTSTART' => $start,
'DTEND' => $end,
'X-NEXTCLOUD-OUT-OF-OFFICE' => $data->getId(),
]);
/** @var VEvent $vEvent */
$vEvent = $vCalendar->VEVENT;
if ($timeZoneData !== null) {
/** @var VCalendar $vtimezoneObj */
$vtimezoneObj = Reader::read($timeZoneData);
/** @var VTimeZone $vtimezone */
$vtimezone = $vtimezoneObj->VTIMEZONE;
$calendarTimeZone = $vtimezone->getTimeZone();
$vCalendar->add($vtimezone);
/** @psalm-suppress UndefinedMethod */
$vEvent->DTSTART->setDateTime($start->setTimezone($calendarTimeZone)->setTime(0, 0));
/** @psalm-suppress UndefinedMethod */
$vEvent->DTEND->setDateTime($end->setTimezone($calendarTimeZone)->setTime(0, 0));
}
return $vCalendar;
}
}

@ -385,4 +385,8 @@ class Server {
}
return false;
}
public function getSabreServer(): Connector\Sabre\Server {
return $this->server;
}
}

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/**
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @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;
use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
class ServerFactory {
public function createInviationResponseServer(bool $public): InvitationResponseServer {
return new InvitationResponseServer(false);
}
}

@ -75,14 +75,18 @@ class AbsenceService {
if ($user === null) {
throw new InvalidArgumentException("User $userId does not exist");
}
$eventData = $absence->toOutOufOfficeData($user);
if ($absence->getId() === null) {
$this->eventDispatcher->dispatchTyped(new OutOfOfficeScheduledEvent($eventData));
return $this->absenceMapper->insert($absence);
$persistedAbsence = $this->absenceMapper->insert($absence);
$this->eventDispatcher->dispatchTyped(new OutOfOfficeScheduledEvent(
$persistedAbsence->toOutOufOfficeData($user)
));
return $persistedAbsence;
}
$this->eventDispatcher->dispatchTyped(new OutOfOfficeChangedEvent($eventData));
$this->eventDispatcher->dispatchTyped(new OutOfOfficeChangedEvent(
$absence->toOutOufOfficeData($user)
));
return $this->absenceMapper->update($absence);
}

@ -0,0 +1,546 @@
<?php
declare(strict_types=1);
/*
* @copyright 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2023 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @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\Listener;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\CalendarObject;
use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
use OCA\DAV\CalDAV\Plugin;
use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Listener\OutOfOfficeListener;
use OCA\DAV\ServerFactory;
use OCP\EventDispatcher\Event;
use OCP\IConfig;
use OCP\IUser;
use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeClearedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
use OCP\User\IOutOfOfficeData;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Tree;
use Test\TestCase;
/**
* @covers \OCA\DAV\Listener\OutOfOfficeListener
*/
class OutOfOfficeListenerTest extends TestCase {
private ServerFactory|MockObject $serverFactory;
private IConfig|MockObject $appConfig;
private LoggerInterface|MockObject $loggerInterface;
private OutOfOfficeListener $listener;
protected function setUp(): void {
parent::setUp();
$this->serverFactory = $this->createMock(ServerFactory::class);
$this->appConfig = $this->createMock(IConfig::class);
$this->loggerInterface = $this->createMock(LoggerInterface::class);
$this->listener = new OutOfOfficeListener(
$this->serverFactory,
$this->appConfig,
$this->loggerInterface,
);
}
public function testHandleUnrelated(): void {
$event = new Event();
$this->listener->handle($event);
$this->addToAssertionCount(1);
}
public function testHandleSchedulingNoCalendarHome(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$event = new OutOfOfficeScheduledEvent($data);
$this->listener->handle($event);
}
public function testHandleSchedulingNoCalendarHomeNode(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeScheduledEvent($data);
$this->listener->handle($event);
}
public function testHandleSchedulingPersonalCalendarNotFound(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeScheduledEvent($data);
$this->listener->handle($event);
}
public function testHandleScheduling(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendar = $this->createMock(Calendar::class);
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willReturn($calendar);
$calendar->expects(self::once())
->method('createFile');
$event = new OutOfOfficeScheduledEvent($data);
$this->listener->handle($event);
}
public function testHandleChangeNoCalendarHome(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$event = new OutOfOfficeChangedEvent($data);
$this->listener->handle($event);
}
public function testHandleChangeNoCalendarHomeNode(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeChangedEvent($data);
$this->listener->handle($event);
}
public function testHandleChangePersonalCalendarNotFound(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeChangedEvent($data);
$this->listener->handle($event);
}
public function testHandleChangeRecreate(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendar = $this->createMock(Calendar::class);
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willReturn($calendar);
$calendar->expects(self::once())
->method('getChild')
->willThrowException(new NotFound());
$calendar->expects(self::once())
->method('createFile');
$event = new OutOfOfficeChangedEvent($data);
$this->listener->handle($event);
}
public function testHandleChange(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendar = $this->createMock(Calendar::class);
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willReturn($calendar);
$eventNode = $this->createMock(CalendarObject::class);
$calendar->expects(self::once())
->method('getChild')
->willReturn($eventNode);
$eventNode->expects(self::once())
->method('put');
$calendar->expects(self::never())
->method('createFile');
$event = new OutOfOfficeChangedEvent($data);
$this->listener->handle($event);
}
public function testHandleClearNoCalendarHome(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
}
public function testHandleClearNoCalendarHomeNode(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
}
public function testHandleClearPersonalCalendarNotFound(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willThrowException(new NotFound('nope'));
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
}
public function testHandleClearRecreate(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendar = $this->createMock(Calendar::class);
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willReturn($calendar);
$calendar->expects(self::once())
->method('getChild')
->willThrowException(new NotFound());
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
}
public function testHandleClear(): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user123');
$data = $this->createMock(IOutOfOfficeData::class);
$data->method('getUser')->willReturn($user);
$davServer = $this->createMock(Server::class);
$invitationServer = $this->createMock(InvitationResponseServer::class);
$invitationServer->method('getServer')->willReturn($davServer);
$this->serverFactory->method('createInviationResponseServer')->willReturn($invitationServer);
$caldavPlugin = $this->createMock(Plugin::class);
$davServer->expects(self::once())
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
$caldavPlugin->expects(self::once())
->method('getCalendarHomeForPrincipal')
->willReturn('/home/calendar');
$tree = $this->createMock(Tree::class);
$davServer->tree = $tree;
$calendarHome = $this->createMock(CalendarHome::class);
$tree->expects(self::once())
->method('getNodeForPath')
->with('/home/calendar')
->willReturn($calendarHome);
$this->appConfig->expects(self::once())
->method('getUserValue')
->with('user123', 'dav', 'defaultCalendar', 'personal')
->willReturn('personal-1');
$calendar = $this->createMock(Calendar::class);
$calendarHome->expects(self::once())
->method('getChild')
->with('personal-1')
->willReturn($calendar);
$eventNode = $this->createMock(CalendarObject::class);
$calendar->expects(self::once())
->method('getChild')
->willReturn($eventNode);
$eventNode->expects(self::once())
->method('delete');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
}
}
Loading…
Cancel
Save