summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php1
-rw-r--r--apps/dav/composer/composer/autoload_static.php1
-rw-r--r--apps/dav/lib/CalDAV/Status/Status.php72
-rw-r--r--apps/dav/lib/CalDAV/Status/StatusService.php209
-rw-r--r--apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php862
-rw-r--r--apps/user_status/lib/Controller/UserStatusController.php3
-rw-r--r--apps/user_status/lib/Listener/UserLiveStatusListener.php11
-rw-r--r--apps/user_status/lib/Service/StatusService.php31
-rw-r--r--apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php49
-rw-r--r--apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php19
-rw-r--r--apps/user_status/tests/Unit/Service/StatusServiceTest.php49
11 files changed, 446 insertions, 861 deletions
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 5d6b077ad53..72455e6bf67 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -99,7 +99,6 @@ return array(
'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\PropFilter' => $baseDir . '/../lib/CalDAV/Search/Xml/Filter/PropFilter.php',
'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\SearchTermFilter' => $baseDir . '/../lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php',
'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport' => $baseDir . '/../lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php',
- 'OCA\\DAV\\CalDAV\\Status\\Status' => $baseDir . '/../lib/CalDAV/Status/Status.php',
'OCA\\DAV\\CalDAV\\Status\\StatusService' => $baseDir . '/../lib/CalDAV/Status/StatusService.php',
'OCA\\DAV\\CalDAV\\TimezoneService' => $baseDir . '/../lib/CalDAV/TimezoneService.php',
'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObject' => $baseDir . '/../lib/CalDAV/Trashbin/DeletedCalendarObject.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 2456604a9cb..0d715f510f7 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -114,7 +114,6 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\PropFilter' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Filter/PropFilter.php',
'OCA\\DAV\\CalDAV\\Search\\Xml\\Filter\\SearchTermFilter' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php',
'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport' => __DIR__ . '/..' . '/../lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php',
- 'OCA\\DAV\\CalDAV\\Status\\Status' => __DIR__ . '/..' . '/../lib/CalDAV/Status/Status.php',
'OCA\\DAV\\CalDAV\\Status\\StatusService' => __DIR__ . '/..' . '/../lib/CalDAV/Status/StatusService.php',
'OCA\\DAV\\CalDAV\\TimezoneService' => __DIR__ . '/..' . '/../lib/CalDAV/TimezoneService.php',
'OCA\\DAV\\CalDAV\\Trashbin\\DeletedCalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/Trashbin/DeletedCalendarObject.php',
diff --git a/apps/dav/lib/CalDAV/Status/Status.php b/apps/dav/lib/CalDAV/Status/Status.php
deleted file mode 100644
index 46ddf7e47f3..00000000000
--- a/apps/dav/lib/CalDAV/Status/Status.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright 2023 Anna Larch <anna.larch@gmx.net>
- *
- * @author Anna Larch <anna.larch@gmx.net>
- *
- * @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\Status;
-
-class Status {
- public function __construct(private string $status = '', private ?string $message = null, private ?string $customMessage = null, private ?int $timestamp = null, private ?string $customEmoji = null) {
- }
-
- public function getStatus(): string {
- return $this->status;
- }
-
- public function setStatus(string $status): void {
- $this->status = $status;
- }
-
- public function getMessage(): ?string {
- return $this->message;
- }
-
- public function setMessage(?string $message): void {
- $this->message = $message;
- }
-
- public function getCustomMessage(): ?string {
- return $this->customMessage;
- }
-
- public function setCustomMessage(?string $customMessage): void {
- $this->customMessage = $customMessage;
- }
-
- public function setEndTime(?int $timestamp): void {
- $this->timestamp = $timestamp;
- }
-
- public function getEndTime(): ?int {
- return $this->timestamp;
- }
-
- public function getCustomEmoji(): ?string {
- return $this->customEmoji;
- }
-
- public function setCustomEmoji(?string $emoji): void {
- $this->customEmoji = $emoji;
- }
-}
diff --git a/apps/dav/lib/CalDAV/Status/StatusService.php b/apps/dav/lib/CalDAV/Status/StatusService.php
index add8a668f7a..11be9d8b2b8 100644
--- a/apps/dav/lib/CalDAV/Status/StatusService.php
+++ b/apps/dav/lib/CalDAV/Status/StatusService.php
@@ -25,83 +25,123 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CalDAV\Status;
+use DateTimeImmutable;
use OC\Calendar\CalendarQuery;
use OCA\DAV\CalDAV\CalendarImpl;
-use OCA\DAV\CalDAV\FreeBusy\FreeBusyGenerator;
-use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
-use OCA\DAV\CalDAV\Schedule\Plugin as SchedulePlugin;
+use OCA\UserStatus\Service\StatusService as UserStatusService;
+use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Calendar\IManager;
-use OCP\IL10N;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IUser as User;
+use OCP\IUserManager;
+use OCP\User\IAvailabilityCoordinator;
use OCP\UserStatus\IUserStatus;
+use Psr\Log\LoggerInterface;
use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
-use Sabre\DAV\Exception\NotAuthenticated;
-use Sabre\DAVACL\Exception\NeedPrivileges;
-use Sabre\DAVACL\Plugin as AclPlugin;
-use Sabre\VObject\Component;
-use Sabre\VObject\Component\VEvent;
-use Sabre\VObject\Parameter;
-use Sabre\VObject\Property;
class StatusService {
+ private ICache $cache;
public function __construct(private ITimeFactory $timeFactory,
private IManager $calendarManager,
- private InvitationResponseServer $server,
- private IL10N $l10n,
- private FreeBusyGenerator $generator) {
+ private IUserManager $userManager,
+ private UserStatusService $userStatusService,
+ private IAvailabilityCoordinator $availabilityCoordinator,
+ private ICacheFactory $cacheFactory,
+ private LoggerInterface $logger) {
+ $this->cache = $cacheFactory->createLocal('CalendarStatusService');
}
- public function processCalendarAvailability(User $user): ?Status {
- $userId = $user->getUID();
- $email = $user->getEMailAddress();
- if($email === null) {
- return null;
+ public function processCalendarStatus(string $userId): void {
+ $user = $this->userManager->get($userId);
+ if($user === null) {
+ return;
}
- $server = $this->server->getServer();
+ $availability = $this->availabilityCoordinator->getCurrentOutOfOfficeData($user);
+ if($availability !== null && $this->availabilityCoordinator->isInEffect($availability)) {
+ $this->logger->debug('An Absence is in effect, skipping calendar status check', ['user' => $userId]);
+ return;
+ }
- /** @var SchedulePlugin $schedulingPlugin */
- $schedulingPlugin = $server->getPlugin('caldav-schedule');
- $caldavNS = '{'.$schedulingPlugin::NS_CALDAV.'}';
+ $calendarEvents = $this->cache->get($userId);
+ if($calendarEvents === null) {
+ $calendarEvents = $this->getCalendarEvents($user);
+ $this->cache->set($userId, $calendarEvents, 300);
+ }
- /** @var AclPlugin $aclPlugin */
- $aclPlugin = $server->getPlugin('acl');
- if ('mailto:' === substr($email, 0, 7)) {
- $email = substr($email, 7);
+ if(empty($calendarEvents)) {
+ $this->userStatusService->revertUserStatus($userId, IUserStatus::MESSAGE_CALENDAR_BUSY);
+ $this->logger->debug('No calendar events found for status check', ['user' => $userId]);
+ return;
}
- $result = $aclPlugin->principalSearch(
- ['{http://sabredav.org/ns}email-address' => $email],
- [
- '{DAV:}principal-URL',
- $caldavNS.'calendar-home-set',
- $caldavNS.'schedule-inbox-URL',
- '{http://sabredav.org/ns}email-address',
- ]
- );
+ $userStatusTimestamp = null;
+ $currentStatus = null;
+ try {
+ $currentStatus = $this->userStatusService->findByUserId($userId);
+ $userStatusTimestamp = $currentStatus->getIsUserDefined() ? $currentStatus->getStatusTimestamp() : null;
+ } catch (DoesNotExistException) {
+ }
- if (!count($result) || !isset($result[0][200][$caldavNS.'schedule-inbox-URL'])) {
- return null;
+ if($currentStatus !== null && $currentStatus->getMessageId() === IUserStatus::MESSAGE_CALL
+ || $currentStatus !== null && $currentStatus->getStatus() === IUserStatus::DND
+ || $currentStatus !== null && $currentStatus->getStatus() === IUserStatus::INVISIBLE) {
+ // We don't overwrite the call status, DND status or Invisible status
+ $this->logger->debug('Higher priority status detected, skipping calendar status change', ['user' => $userId]);
+ return;
}
- $inboxUrl = $result[0][200][$caldavNS.'schedule-inbox-URL']->getHref();
+ // Filter events to see if we have any that apply to the calendar status
+ $applicableEvents = array_filter($calendarEvents, function (array $calendarEvent) use ($userStatusTimestamp) {
+ $component = $calendarEvent['objects'][0];
+ if(isset($component['X-NEXTCLOUD-OUT-OF-OFFICE'])) {
+ return false;
+ }
+ if(isset($component['DTSTART']) && $userStatusTimestamp !== null) {
+ /** @var DateTimeImmutable $dateTime */
+ $dateTime = $component['DTSTART'][0];
+ $timestamp = $dateTime->getTimestamp();
+ if($userStatusTimestamp > $timestamp) {
+ return false;
+ }
+ }
+ // Ignore events that are transparent
+ if(isset($component['TRANSP']) && strcasecmp($component['TRANSP'][0], 'TRANSPARENT') === 0) {
+ return false;
+ }
+ return true;
+ });
- // Do we have permission?
- try {
- $aclPlugin->checkPrivileges($inboxUrl, $caldavNS.'schedule-query-freebusy');
- } catch (NeedPrivileges | NotAuthenticated $exception) {
- return null;
+ if(empty($applicableEvents)) {
+ $this->userStatusService->revertUserStatus($userId, IUserStatus::MESSAGE_CALENDAR_BUSY);
+ $this->logger->debug('No status relevant events found, skipping calendar status change', ['user' => $userId]);
+ return;
}
- $now = $this->timeFactory->now();
- $calendarTimeZone = $now->getTimezone();
- $calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId);
+ // One event that fulfills all status conditions is enough
+ // 1. Not an OOO event
+ // 2. Current user status was not set after the start of this event
+ // 3. Event is not set to be transparent
+ $count = count($applicableEvents);
+ $this->logger->debug("Found $count applicable event(s), changing user status", ['user' => $userId]);
+ $this->userStatusService->setUserStatus(
+ $userId,
+ IUserStatus::AWAY,
+ IUserStatus::MESSAGE_CALENDAR_BUSY,
+ true
+ );
+
+ }
+
+ private function getCalendarEvents(User $user): array {
+ $calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $user->getUID());
if(empty($calendars)) {
- return null;
+ return [];
}
- $query = $this->calendarManager->newQuery('principals/users/' . $userId);
+ $query = $this->calendarManager->newQuery('principals/users/' . $user->getUID());
foreach ($calendars as $calendarObject) {
// We can only work with a calendar if it exposes its scheduling information
if (!$calendarObject instanceof CalendarImpl) {
@@ -114,83 +154,20 @@ class StatusService {
// ignore it for free-busy purposes.
continue;
}
-
- /** @var Component\VTimeZone|null $ctz */
- $ctz = $calendarObject->getSchedulingTimezone();
- if ($ctz !== null) {
- $calendarTimeZone = $ctz->getTimeZone();
- }
$query->addSearchCalendar($calendarObject->getUri());
}
- $calendarEvents = [];
- $dtStart = $now;
- $dtEnd = \DateTimeImmutable::createFromMutable($this->timeFactory->getDateTime('+10 minutes'));
+ $dtStart = DateTimeImmutable::createFromMutable($this->timeFactory->getDateTime());
+ $dtEnd = DateTimeImmutable::createFromMutable($this->timeFactory->getDateTime('+5 minutes'));
// Only query the calendars when there's any to search
if($query instanceof CalendarQuery && !empty($query->getCalendarUris())) {
// Query the next hour
$query->setTimerangeStart($dtStart);
$query->setTimerangeEnd($dtEnd);
- $calendarEvents = $this->calendarManager->searchForPrincipal($query);
+ return $this->calendarManager->searchForPrincipal($query);
}
- // @todo we can cache that
- if(empty($calendarEvents)) {
- return null;
- }
-
- $calendar = $this->generator->getVCalendar();
- foreach ($calendarEvents as $calendarEvent) {
- $vEvent = new VEvent($calendar, 'VEVENT');
- foreach($calendarEvent['objects'] as $component) {
- foreach ($component as $key => $value) {
- $vEvent->add($key, $value[0]);
- }
- }
- $calendar->add($vEvent);
- }
-
- $calendar->METHOD = 'REQUEST';
-
- $this->generator->setObjects($calendar);
- $this->generator->setTimeRange($dtStart, $dtEnd);
- $this->generator->setTimeZone($calendarTimeZone);
- $result = $this->generator->getResult();
-
- if (!isset($result->VFREEBUSY)) {
- return null;
- }
-
- /** @var Component $freeBusyComponent */
- $freeBusyComponent = $result->VFREEBUSY;
- $freeBusyProperties = $freeBusyComponent->select('FREEBUSY');
- // If there is no FreeBusy property, the time-range is empty and available
- if (count($freeBusyProperties) === 0) {
- return null;
- }
-
- /** @var Property $freeBusyProperty */
- $freeBusyProperty = $freeBusyProperties[0];
- if (!$freeBusyProperty->offsetExists('FBTYPE')) {
- // If there is no FBTYPE, it means it's busy from a regular event
- return new Status(IUserStatus::BUSY, IUserStatus::MESSAGE_CALENDAR_BUSY);
- }
-
- // If we can't deal with the FBTYPE (custom properties are a possibility)
- // we should ignore it and leave the current status
- $fbTypeParameter = $freeBusyProperty->offsetGet('FBTYPE');
- if (!($fbTypeParameter instanceof Parameter)) {
- return null;
- }
- $fbType = $fbTypeParameter->getValue();
- switch ($fbType) {
- // Ignore BUSY-UNAVAILABLE, that's for the automation
- case 'BUSY':
- case 'BUSY-TENTATIVE':
- return new Status(IUserStatus::BUSY, IUserStatus::MESSAGE_CALENDAR_BUSY, $this->l10n->t('In a meeting'));
- default:
- return null;
- }
+ return [];
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
index 705298de125..7073c02b8e4 100644
--- a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
@@ -24,31 +24,31 @@ namespace OCA\DAV\Tests\unit\CalDAV\Status;
use OC\Calendar\CalendarQuery;
use OCA\DAV\CalDAV\CalendarImpl;
-use OCA\DAV\CalDAV\FreeBusy\FreeBusyGenerator;
-use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
-use OCA\DAV\CalDAV\Schedule\Plugin;
use OCA\DAV\CalDAV\Status\StatusService;
-use OCA\DAV\Connector\Sabre\Server;
+use OCA\UserStatus\Db\UserStatus;
+use OCA\UserStatus\Service\StatusService as UserStatusService;
+use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Calendar\IManager;
-use OCP\IL10N;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IUser;
+use OCP\IUserManager;
+use OCP\User\IAvailabilityCoordinator;
+use OCP\User\IOutOfOfficeData;
+use OCP\UserStatus\IUserStatus;
use PHPUnit\Framework\MockObject\MockObject;
-use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
-use Sabre\DAV\Exception\NotAuthenticated;
-use Sabre\DAV\Xml\Property\LocalHref;
-use Sabre\DAVACL\Exception\NeedPrivileges;
-use Sabre\VObject\Component\VCalendar;
-use Sabre\VObject\Component\VTimeZone;
-use Sabre\VObject\Reader;
+use Psr\Log\LoggerInterface;
use Test\TestCase;
class StatusServiceTest extends TestCase {
private ITimeFactory|MockObject $timeFactory;
private IManager|MockObject $calendarManager;
- private InvitationResponseServer|MockObject $server;
- private IL10N|MockObject $l10n;
- private FreeBusyGenerator|MockObject $generator;
+ private IUserManager|MockObject $userManager;
+ private UserStatusService|MockObject $userStatusService;
+ private IAvailabilityCoordinator|MockObject $availabilityCoordinator;
+ private ICacheFactory|MockObject $cacheFactory;
+ private LoggerInterface|MockObject $logger;
private StatusService $service;
protected function setUp(): void {
@@ -56,644 +56,360 @@ class StatusServiceTest extends TestCase {
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->calendarManager = $this->createMock(IManager::class);
- $this->server = $this->createMock(InvitationResponseServer::class);
- $this->l10n = $this->createMock(IL10N::class);
- $this->generator = $this->createMock(FreeBusyGenerator::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userStatusService = $this->createMock(UserStatusService::class);
+ $this->availabilityCoordinator = $this->createMock(IAvailabilityCoordinator::class);
+ $this->cacheFactory = $this->createMock(ICacheFactory::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->cache = $this->createMock(ICache::class);
+ $this->cacheFactory->expects(self::once())
+ ->method('createLocal')
+ ->with('CalendarStatusService')
+ ->willReturn($this->cache);
$this->service = new StatusService($this->timeFactory,
$this->calendarManager,
- $this->server,
- $this->l10n,
- $this->generator);
+ $this->userManager,
+ $this->userStatusService,
+ $this->availabilityCoordinator,
+ $this->cacheFactory,
+ $this->logger,
+ );
}
- public function testNoEmail(): void {
- $user = $this->createConfiguredMock(IUser::class, [
- 'getUID' => 'admin',
- 'getEMailAddress' => null,
- ]);
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
+ public function testNoUser(): void {
+ $this->userManager->expects(self::once())
+ ->method('get')
->willReturn(null);
- $this->server->expects(self::never())
- ->method('getServer');
- $this->timeFactory->expects(self::never())
- ->method('now');
- $this->timeFactory->expects(self::never())
- ->method('getDateTime');
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('getCurrentOutOfOfficeData');
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->logger->expects(self::never())
+ ->method('debug');
+ $this->cache->expects(self::never())
+ ->method('get');
+ $this->cache->expects(self::never())
+ ->method('set');
$this->calendarManager->expects(self::never())
->method('getCalendarsForPrincipal');
$this->calendarManager->expects(self::never())
->method('newQuery');
+ $this->timeFactory->expects(self::never())
+ ->method('getDateTime');
$this->calendarManager->expects(self::never())
->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('findByUserId');
+
+ $this->service->processCalendarStatus('admin');
}
- public function testNoAcl(): void {
+ public function testOOOInEffect(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn([]);
- $aclPlugin->expects(self::never())
- ->method('checkPrivileges');
- $this->timeFactory->expects(self::never())
- ->method('now');
- $this->timeFactory->expects(self::never())
- ->method('getDateTime');
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn($this->createMock(IOutOfOfficeData::class));
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('isInEffect')
+ ->willReturn(true);
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->cache->expects(self::never())
+ ->method('get');
+ $this->cache->expects(self::never())
+ ->method('set');
$this->calendarManager->expects(self::never())
->method('getCalendarsForPrincipal');
$this->calendarManager->expects(self::never())
->method('newQuery');
+ $this->timeFactory->expects(self::never())
+ ->method('getDateTime');
$this->calendarManager->expects(self::never())
->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('findByUserId');
+
+ $this->service->processCalendarStatus('admin');
}
- public function testNoInbox(): void {
+ public function testNoCalendars(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
+ $this->calendarManager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
->willReturn([]);
- $aclPlugin->expects(self::never())
- ->method('checkPrivileges');
- $this->timeFactory->expects(self::never())
- ->method('now');
- $this->timeFactory->expects(self::never())
- ->method('getDateTime');
- $this->calendarManager->expects(self::never())
- ->method('getCalendarsForPrincipal');
$this->calendarManager->expects(self::never())
->method('newQuery');
- $this->calendarManager->expects(self::never())
- ->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
- }
-
- public function testNoPrivilegesAcl(): void {
- $user = $this->createConfiguredMock(IUser::class, [
- 'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
- ]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $principal = 'principals/users/admin';
- $calendarHome = $this->createMock(LocalHref::class);
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willThrowException(new NeedPrivileges($principal, ['{DAV:}all']));
- $this->timeFactory->expects(self::never())
- ->method('now');
$this->timeFactory->expects(self::never())
->method('getDateTime');
$this->calendarManager->expects(self::never())
- ->method('getCalendarsForPrincipal');
- $this->calendarManager->expects(self::never())
- ->method('newQuery');
- $this->calendarManager->expects(self::never())
->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ $this->userStatusService->expects(self::once())
+ ->method('revertUserStatus');
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('findByUserId');
+
+ $this->service->processCalendarStatus('admin');
}
- public function testNotAuthenticated(): void {
+ public function testNoCalendarEvents(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $calendarHome = $this->createMock(LocalHref::class);
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willThrowException(new NotAuthenticated());
- $this->timeFactory->expects(self::never())
- ->method('now');
- $this->timeFactory->expects(self::never())
- ->method('getDateTime');
- $this->calendarManager->expects(self::never())
- ->method('getCalendarsForPrincipal');
- $this->calendarManager->expects(self::never())
- ->method('newQuery');
- $this->calendarManager->expects(self::never())
- ->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
+ $this->calendarManager->expects(self::once())
+ ->method('getCalendarsForPrincipal')
+ ->willReturn([$this->createMock(CalendarImpl::class)]);
+ $this->calendarManager->expects(self::once())
+ ->method('newQuery')
+ ->willReturn(new CalendarQuery('admin'));
+ $this->timeFactory->expects(self::exactly(2))
+ ->method('getDateTime')
+ ->willReturn(new \DateTime());
+ $this->calendarManager->expects(self::once())
+ ->method('searchForPrincipal')
+ ->willReturn([]);
+ $this->userStatusService->expects(self::once())
+ ->method('revertUserStatus');
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('findByUserId');
+
+ $this->service->processCalendarStatus('admin');
}
- public function testNoCalendars(): void {
+ public function testCalendarEvent(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $calendarHome = $this->createMock(LocalHref::class);
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
- $now = new \DateTimeImmutable('1970-1-1', new \DateTimeZone('UTC'));
- $principal = 'principals/users/admin';
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willReturn(true);
- $this->timeFactory->expects(self::once())
- ->method('now')
- ->willReturn($now);
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
$this->calendarManager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->with($principal)
- ->willReturn([]);
- $this->timeFactory->expects(self::never())
- ->method('getDateTime');
- $this->calendarManager->expects(self::never())
- ->method('newQuery');
- $this->calendarManager->expects(self::never())
- ->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ ->willReturn([$this->createMock(CalendarImpl::class)]);
+ $this->calendarManager->expects(self::once())
+ ->method('newQuery')
+ ->willReturn(new CalendarQuery('admin'));
+ $this->timeFactory->expects(self::exactly(2))
+ ->method('getDateTime')
+ ->willReturn(new \DateTime());
+ $this->userStatusService->expects(self::once())
+ ->method('findByUserId')
+ ->willThrowException(new DoesNotExistException(''));
+ $this->calendarManager->expects(self::once())
+ ->method('searchForPrincipal')
+ ->willReturn([['objects' => [[]]]]);
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::once())
+ ->method('setUserStatus');
+
+
+ $this->service->processCalendarStatus('admin');
}
- public function testEmptyAvailabilityAndNoSearchCalendars(): void {
+ public function testCallStatus(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $calendarHome = $this->createMock(LocalHref::class);
- $now = new \DateTimeImmutable('1970-1-1', new \DateTimeZone('UTC'));
- $inTenMinutes = new \DateTime('1970-1-1 01:00');
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
- $principal = 'principals/users/admin';
- $calendar = $this->createMock(CalendarImpl::class);
- $query = $this->createMock(CalendarQuery::class);
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with([ '{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willReturn(true);
- $this->timeFactory->expects(self::once())
- ->method('now')
- ->willReturn($now);
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
$this->calendarManager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->with($principal)
- ->willReturn([$calendar]);
+ ->willReturn([$this->createMock(CalendarImpl::class)]);
$this->calendarManager->expects(self::once())
->method('newQuery')
- ->with($principal)
- ->willReturn($query);
- $calendar->expects(self::once())
- ->method('getSchedulingTransparency')
- ->willReturn(new ScheduleCalendarTransp('transparent'));
- $this->timeFactory->expects(self::once())
+ ->willReturn(new CalendarQuery('admin'));
+ $this->timeFactory->expects(self::exactly(2))
->method('getDateTime')
- ->with('+10 minutes')
- ->willReturn($inTenMinutes);
- $this->calendarManager->expects(self::never())
- ->method('searchForPrincipal');
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ ->willReturn(new \DateTime());
+ $this->calendarManager->expects(self::once())
+ ->method('searchForPrincipal')
+ ->willReturn([['objects' => [[]]]]);
+ $userStatus = new UserStatus();
+ $userStatus->setMessageId(IUserStatus::MESSAGE_CALL);
+ $userStatus->setStatusTimestamp(123456);
+ $this->userStatusService->expects(self::once())
+ ->method('findByUserId')
+ ->willReturn($userStatus);
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+
+
+ $this->service->processCalendarStatus('admin');
}
- public function testEmptyAvailabilityAndSearchCalendarsNoResults(): void {
+ public function testInvisibleStatus(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $availability = '';
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $calendarHome = $this->createMock(LocalHref::class);
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
- $now = new \DateTimeImmutable('1970-1-1 00:00', new \DateTimeZone('UTC'));
- $inTenMinutes = new \DateTime('1970-1-1 01:00');
- $immutableInTenMinutes = \DateTimeImmutable::createFromMutable($inTenMinutes);
- $principal = 'principals/users/admin';
- $query = $this->createMock(CalendarQuery::class);
- $timezone = new \DateTimeZone('UTC');
- $timezoneObj = $this->createMock(VTimeZone::class);
- $calendar = $this->createMock(CalendarImpl::class);
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with(['{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willReturn(true);
- $this->timeFactory->expects(self::once())
- ->method('now')
- ->willReturn($now);
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
$this->calendarManager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->with($principal)
- ->willReturn([$calendar]);
+ ->willReturn([$this->createMock(CalendarImpl::class)]);
$this->calendarManager->expects(self::once())
->method('newQuery')
- ->with($principal)
- ->willReturn($query);
- $calendar->expects(self::once())
- ->method('getSchedulingTransparency')
- ->willReturn(new ScheduleCalendarTransp('opaque'));
- $calendar->expects(self::once())
- ->method('getSchedulingTimezone')
- ->willReturn($timezoneObj);
- $timezoneObj->expects(self::once())
- ->method('getTimeZone')
- ->willReturn($timezone);
- $calendar->expects(self::once())
- ->method('getUri');
- $query->expects(self::once())
- ->method('addSearchCalendar');
- $query->expects(self::once())
- ->method('getCalendarUris')
- ->willReturn([$calendar]);
- $this->timeFactory->expects(self::once())
+ ->willReturn(new CalendarQuery('admin'));
+ $this->timeFactory->expects(self::exactly(2))
->method('getDateTime')
- ->with('+10 minutes')
- ->willReturn($inTenMinutes);
- $query->expects(self::once())
- ->method('setTimerangeStart')
- ->with($now);
- $query->expects(self::once())
- ->method('setTimerangeEnd')
- ->with($immutableInTenMinutes);
+ ->willReturn(new \DateTime());
$this->calendarManager->expects(self::once())
->method('searchForPrincipal')
- ->with($query)
- ->willReturn([]);
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ ->willReturn([['objects' => [[]]]]);
+ $userStatus = new UserStatus();
+ $userStatus->setStatus(IUserStatus::INVISIBLE);
+ $userStatus->setStatusTimestamp(123456);
+ $this->userStatusService->expects(self::once())
+ ->method('findByUserId')
+ ->willReturn($userStatus);
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+
+
+ $this->service->processCalendarStatus('admin');
}
- public function testSearchCalendarsNoResults(): void {
+ public function testDNDStatus(): void {
$user = $this->createConfiguredMock(IUser::class, [
'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
]);
- $server = $this->createMock(Server::class);
- $schedulingPlugin = $this->createMock(Plugin::class);
- $aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $calendarHome = $this->createMock(LocalHref::class);
- $acl = [[200 => ['{urn:ietf:params:xml:ns:caldav}schedule-inbox-URL' => $calendarHome]]];
- $now = new \DateTimeImmutable('1970-1-1 00:00', new \DateTimeZone('UTC'));
- $inTenMinutes = new \DateTime('1970-1-1 01:00');
- $immutableInTenMinutes = \DateTimeImmutable::createFromMutable($inTenMinutes);
- $principal = 'principals/users/admin';
- $query = $this->createMock(CalendarQuery::class);
- $timezone = new \DateTimeZone('UTC');
- $timezoneObj = $this->createMock(VTimeZone::class);
- $calendar = $this->createMock(CalendarImpl::class);
- $vCalendar = $this->createMock(VCalendar::class);
- $result = Reader::read('BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Sabre//Sabre VObject 4.5.3//EN
- CALSCALE:GREGORIAN
-METHOD:REQUEST
-END:VCALENDAR');
-
- $user->expects(self::once())
- ->method('getUID')
- ->willReturn('admin');
- $user->expects(self::once())
- ->method('getEMailAddress')
- ->willReturn('test@test.com');
- $this->server->expects(self::once())
- ->method('getServer')
- ->willReturn($server);
- $server->expects(self::exactly(2))
- ->method('getPlugin')
- ->withConsecutive(
- ['caldav-schedule'],
- ['acl'],
- )->willReturnOnConsecutiveCalls($schedulingPlugin, $aclPlugin);
- $aclPlugin->expects(self::once())
- ->method('principalSearch')
- ->with(['{http://sabredav.org/ns}email-address' => 'test@test.com'])
- ->willReturn($acl);
- $calendarHome->expects(self::once())
- ->method('getHref')
- ->willReturn('calendars/admin/inbox/');
- $aclPlugin->expects(self::once())
- ->method('checkPrivileges')
- ->willReturn(true);
- $this->timeFactory->expects(self::once())
- ->method('now')
- ->willReturn($now);
+
+ $this->userManager->expects(self::once())
+ ->method('get')
+ ->willReturn($user);
+ $this->availabilityCoordinator->expects(self::once())
+ ->method('getCurrentOutOfOfficeData')
+ ->willReturn(null);
+ $this->availabilityCoordinator->expects(self::never())
+ ->method('isInEffect');
+ $this->cache->expects(self::once())
+ ->method('get')
+ ->willReturn(null);
+ $this->cache->expects(self::once())
+ ->method('set');
$this->calendarManager->expects(self::once())
->method('getCalendarsForPrincipal')
- ->with($principal)
- ->willReturn([$calendar]);
+ ->willReturn([$this->createMock(CalendarImpl::class)]);
$this->calendarManager->expects(self::once())
->method('newQuery')
- ->with($principal)
- ->willReturn($query);
- $calendar->expects(self::once())
- ->method('getSchedulingTransparency')
- ->willReturn(new ScheduleCalendarTransp('opaque'));
- $calendar->expects(self::once())
- ->method('getSchedulingTimezone')
- ->willReturn($timezoneObj);
- $timezoneObj->expects(self::once())
- ->method('getTimeZone')
- ->willReturn($timezone);
- $calendar->expects(self::once())
- ->method('getUri');
- $query->expects(self::once())
- ->method('addSearchCalendar');
- $query->expects(self::once())
- ->method('getCalendarUris')
- ->willReturn([$calendar]);
- $this->timeFactory->expects(self::once())
+ ->willReturn(new CalendarQuery('admin'));
+ $this->timeFactory->expects(self::exactly(2))
->method('getDateTime')
- ->with('+10 minutes')
- ->willReturn($inTenMinutes);
- $query->expects(self::once())
- ->method('setTimerangeStart')
- ->with($now);
- $query->expects(self::once())
- ->method('setTimerangeEnd')
- ->with($immutableInTenMinutes);
+ ->willReturn(new \DateTime());
$this->calendarManager->expects(self::once())
->method('searchForPrincipal')
- ->with($query)
- ->willReturn([]);
- $this->generator->expects(self::never())
- ->method('getVCalendar');
- $vCalendar->expects(self::never())
- ->method('add');
- $this->generator->expects(self::never())
- ->method('setObjects');
- $this->generator->expects(self::never())
- ->method('setTimeRange');
- $this->generator->expects(self::never())
- ->method('setTimeZone');
- $this->generator->expects(self::never())
- ->method('getResult');
-
- $status = $this->service->processCalendarAvailability($user);
- $this->assertNull($status);
+ ->willReturn([['objects' => [[]]]]);
+ $userStatus = new UserStatus();
+ $userStatus->setStatus(IUserStatus::DND);
+ $userStatus->setStatusTimestamp(123456);
+ $this->userStatusService->expects(self::once())
+ ->method('findByUserId')
+ ->willReturn($userStatus);
+ $this->logger->expects(self::once())
+ ->method('debug');
+ $this->userStatusService->expects(self::never())
+ ->method('revertUserStatus');
+ $this->userStatusService->expects(self::never())
+ ->method('setUserStatus');
+
+
+ $this->service->processCalendarStatus('admin');
}
}
diff --git a/apps/user_status/lib/Controller/UserStatusController.php b/apps/user_status/lib/Controller/UserStatusController.php
index f2b1537e4f7..3beb8abc3ab 100644
--- a/apps/user_status/lib/Controller/UserStatusController.php
+++ b/apps/user_status/lib/Controller/UserStatusController.php
@@ -28,6 +28,7 @@ declare(strict_types=1);
*/
namespace OCA\UserStatus\Controller;
+use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Exception\InvalidClearAtException;
use OCA\UserStatus\Exception\InvalidMessageIdException;
@@ -55,6 +56,7 @@ class UserStatusController extends OCSController {
private string $userId,
private LoggerInterface $logger,
private StatusService $service,
+ private CalendarStatusService $calendarStatusService,
) {
parent::__construct($appName, $request);
}
@@ -71,6 +73,7 @@ class UserStatusController extends OCSController {
*/
public function getStatus(): DataResponse {
try {
+ $this->calendarStatusService->processCalendarStatus($this->userId);
$userStatus = $this->service->findByUserId($this->userId);
} catch (DoesNotExistException $ex) {
throw new OCSNotFoundException('No status for the current user');
diff --git a/apps/user_status/lib/Listener/UserLiveStatusListener.php b/apps/user_status/lib/Listener/UserLiveStatusListener.php
index 0d0e6e3ebf0..b999c51d72f 100644
--- a/apps/user_status/lib/Listener/UserLiveStatusListener.php
+++ b/apps/user_status/lib/Listener/UserLiveStatusListener.php
@@ -25,6 +25,7 @@ declare(strict_types=1);
*/
namespace OCA\UserStatus\Listener;
+use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Connector\UserStatus as ConnectorUserStatus;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Db\UserStatusMapper;
@@ -48,7 +49,8 @@ class UserLiveStatusListener implements IEventListener {
public function __construct(UserStatusMapper $mapper,
StatusService $statusService,
- ITimeFactory $timeFactory) {
+ ITimeFactory $timeFactory,
+ private CalendarStatusService $calendarStatusService) {
$this->mapper = $mapper;
$this->statusService = $statusService;
$this->timeFactory = $timeFactory;
@@ -65,6 +67,7 @@ class UserLiveStatusListener implements IEventListener {
$user = $event->getUser();
try {
+ $this->calendarStatusService->processCalendarStatus($user->getUID());
$userStatus = $this->statusService->findByUserId($user->getUID());
} catch (DoesNotExistException $ex) {
$userStatus = new UserStatus();
@@ -81,6 +84,12 @@ class UserLiveStatusListener implements IEventListener {
return;
}
+ // Don't overwrite the "away" calendar status if it's set
+ if($userStatus->getMessageId() === IUserStatus::MESSAGE_CALENDAR_BUSY) {
+ $event->setUserStatus(new ConnectorUserStatus($userStatus));
+ return;
+ }
+
$needsUpdate = false;
// If the current status is older than 5 minutes,
diff --git a/apps/user_status/lib/Service/StatusService.php b/apps/user_status/lib/Service/StatusService.php
index 9582c403329..c623262eec6 100644
--- a/apps/user_status/lib/Service/StatusService.php
+++ b/apps/user_status/lib/Service/StatusService.php
@@ -27,8 +27,6 @@ declare(strict_types=1);
*/
namespace OCA\UserStatus\Service;
-use OCA\DAV\CalDAV\Status\Status as CalendarStatus;
-use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Db\UserStatusMapper;
use OCA\UserStatus\Exception\InvalidClearAtException;
@@ -89,8 +87,7 @@ class StatusService {
private PredefinedStatusService $predefinedStatusService,
private IEmojiHelper $emojiHelper,
private IConfig $config,
- private IUserManager $userManager,
- private CalendarStatusService $calendarStatusService) {
+ private IUserManager $userManager) {
$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareeEnumerationInGroupOnly = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes';
$this->shareeEnumerationPhone = $this->shareeEnumeration && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes';
@@ -558,30 +555,4 @@ class StatusService {
// For users that matched restore the previous status
$this->mapper->restoreBackupStatuses($restoreIds);
}
-
- /**
- * Calculate a users' status according to their calendar events
- *
- * There are 4 predefined types of FBTYPE - 'FREE', 'BUSY', 'BUSY-UNAVAILABLE', 'BUSY-TENTATIVE',
- * but 'X-' properties are possible
- *
- * @link https://icalendar.org/iCalendar-RFC-5545/3-2-9-free-busy-time-type.html
- *
- * The status will be changed for types
- * - 'BUSY'
- * - 'BUSY-TENTATIVE' (ex.: an event has been accepted tentatively)
- * and all FREEBUSY components without a type (implicitly a 'BUSY' status)
- *
- * 'X-' properties and BUSY-UNAVAILABLE is not handled
- *
- * @param string $userId
- * @return CalendarStatus|null
- */
- public function getCalendarStatus(string $userId): ?CalendarStatus {
- $user = $this->userManager->get($userId);
- if ($user === null) {
- return null;
- }
- return $this->calendarStatusService->processCalendarAvailability($user);
- }
}
diff --git a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
index cabcc63b291..6161eb100ec 100644
--- a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
+++ b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
*/
namespace OCA\UserStatus\Tests\Controller;
+use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Controller\UserStatusController;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Exception\InvalidClearAtException;
@@ -47,7 +48,10 @@ class UserStatusControllerTest extends TestCase {
private $logger;
/** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $service;
+ private $statusService;
+
+ /** @var CalendarStatusService|\PHPUnit\Framework\MockObject\MockObject $calendarStatusService */
+ private $calendarStatusService;
/** @var UserStatusController */
private $controller;
@@ -58,15 +62,23 @@ class UserStatusControllerTest extends TestCase {
$request = $this->createMock(IRequest::class);
$userId = 'john.doe';
$this->logger = $this->createMock(LoggerInterface::class);
- $this->service = $this->createMock(StatusService::class);
-
- $this->controller = new UserStatusController('user_status', $request, $userId, $this->logger, $this->service);
+ $this->statusService = $this->createMock(StatusService::class);
+ $this->calendarStatusService = $this->createMock(CalendarStatusService::class);
+
+ $this->controller = new UserStatusController(
+ 'user_status',
+ $request,
+ $userId,
+ $this->logger,
+ $this->statusService,
+ $this->calendarStatusService,
+ );
}
public function testGetStatus(): void {
$userStatus = $this->getUserStatus();
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('findByUserId')
->with('john.doe')
->willReturn($userStatus);
@@ -85,7 +97,10 @@ class UserStatusControllerTest extends TestCase {
}
public function testGetStatusDoesNotExist(): void {
- $this->service->expects($this->once())
+ $this->calendarStatusService->expects(self::once())
+ ->method('processCalendarStatus')
+ ->with('john.doe');
+ $this->statusService->expects($this->once())
->method('findByUserId')
->with('john.doe')
->willThrowException(new DoesNotExistException(''));
@@ -121,12 +136,12 @@ class UserStatusControllerTest extends TestCase {
$userStatus = $this->getUserStatus();
if ($expectException) {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setStatus')
->with('john.doe', $statusType, null, true)
->willThrowException($exception);
} else {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setStatus')
->with('john.doe', $statusType, null, true)
->willReturn($userStatus);
@@ -187,12 +202,12 @@ class UserStatusControllerTest extends TestCase {
$userStatus = $this->getUserStatus();
if ($expectException) {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setPredefinedMessage')
->with('john.doe', $messageId, $clearAt)
->willThrowException($exception);
} else {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setPredefinedMessage')
->with('john.doe', $messageId, $clearAt)
->willReturn($userStatus);
@@ -259,28 +274,28 @@ class UserStatusControllerTest extends TestCase {
$userStatus = $this->getUserStatus();
if ($expectException) {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setCustomMessage')
->with('john.doe', $statusIcon, $message, $clearAt)
->willThrowException($exception);
} else {
if ($expectSuccessAsReset) {
- $this->service->expects($this->never())
+ $this->statusService->expects($this->never())
->method('setCustomMessage');
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('clearMessage')
->with('john.doe');
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('findByUserId')
->with('john.doe')
->willReturn($userStatus);
} else {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('setCustomMessage')
->with('john.doe', $statusIcon, $message, $clearAt)
->willReturn($userStatus);
- $this->service->expects($this->never())
+ $this->statusService->expects($this->never())
->method('clearMessage');
}
}
@@ -326,7 +341,7 @@ class UserStatusControllerTest extends TestCase {
}
public function testClearMessage(): void {
- $this->service->expects($this->once())
+ $this->statusService->expects($this->once())
->method('clearMessage')
->with('john.doe');
diff --git a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
index 5bc60ca71f9..0f637b75411 100644
--- a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
+++ b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
*/
namespace OCA\UserStatus\Tests\Listener;
+use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Db\UserStatusMapper;
use OCA\UserStatus\Listener\UserDeletedListener;
@@ -36,27 +37,37 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\EventDispatcher\GenericEvent;
use OCP\IUser;
use OCP\User\Events\UserLiveStatusEvent;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class UserLiveStatusListenerTest extends TestCase {
- /** @var UserStatusMapper|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var UserStatusMapper|MockObject */
private $mapper;
- /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var StatusService|MockObject */
private $statusService;
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var ITimeFactory|MockObject */
private $timeFactory;
/** @var UserDeletedListener */
private $listener;
+ private CalendarStatusService|MockObject $calendarStatusService;
+
protected function setUp(): void {
parent::setUp();
$this->mapper = $this->createMock(UserStatusMapper::class);
$this->statusService = $this->createMock(StatusService::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->listener = new UserLiveStatusListener($this->mapper, $this->statusService, $this->timeFactory);
+ $this->calendarStatusService = $this->createMock(CalendarStatusService::class);
+
+ $this->listener = new UserLiveStatusListener(
+ $this->mapper,
+ $this->statusService,
+ $this->timeFactory,
+ $this->calendarStatusService,
+ );
}
/**
diff --git a/apps/user_status/tests/Unit/Service/StatusServiceTest.php b/apps/user_status/tests/Unit/Service/StatusServiceTest.php
index 2de041712bd..da11ec0943b 100644
--- a/apps/user_status/tests/Unit/Service/StatusServiceTest.php
+++ b/apps/user_status/tests/Unit/Service/StatusServiceTest.php
@@ -28,9 +28,6 @@ namespace OCA\UserStatus\Tests\Service;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OC\DB\Exceptions\DbalException;
-use OC\User\User;
-use OCA\DAV\CalDAV\Status\Status;
-use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Db\UserStatusMapper;
use OCA\UserStatus\Exception\InvalidClearAtException;
@@ -45,7 +42,6 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\Exception;
use OCP\IConfig;
use OCP\IEmojiHelper;
-use OCP\IUser;
use OCP\IUserManager;
use OCP\UserStatus\IUserStatus;
use PHPUnit\Framework\MockObject\MockObject;
@@ -71,9 +67,6 @@ class StatusServiceTest extends TestCase {
/** @var IUserManager|MockObject */
private $userManager;
- /** @var CalendarStatusService|MockObject */
- private $calendarStatusService;
-
private StatusService $service;
protected function setUp(): void {
@@ -84,8 +77,6 @@ class StatusServiceTest extends TestCase {
$this->predefinedStatusService = $this->createMock(PredefinedStatusService::class);
$this->emojiHelper = $this->createMock(IEmojiHelper::class);
$this->userManager = $this->createMock(IUserManager::class);
- $this->calendarStatusService = $this->createMock(CalendarStatusService::class);
-
$this->config = $this->createMock(IConfig::class);
$this->config->method('getAppValue')
@@ -99,8 +90,7 @@ class StatusServiceTest extends TestCase {
$this->predefinedStatusService,
$this->emojiHelper,
$this->config,
- $this->userManager,
- $this->calendarStatusService,
+ $this->userManager
);
}
@@ -156,8 +146,7 @@ class StatusServiceTest extends TestCase {
$this->predefinedStatusService,
$this->emojiHelper,
$this->config,
- $this->userManager,
- $this->calendarStatusService,
+ $this->userManager
);
$this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50));
@@ -176,8 +165,7 @@ class StatusServiceTest extends TestCase {
$this->predefinedStatusService,
$this->emojiHelper,
$this->config,
- $this->userManager,
- $this->calendarStatusService,
+ $this->userManager
);
$this->assertEquals([], $this->service->findAllRecentStatusChanges(20, 50));
@@ -837,35 +825,4 @@ class StatusServiceTest extends TestCase {
$this->service->revertMultipleUserStatus(['john', 'nobackup', 'backuponly', 'nobackupanddnd'], 'call');
}
-
- public function testCalendarAvailabilityNoUser(): void {
- $userId = 'admin';
-
- $this->userManager->expects(self::once())
- ->method('get')
- ->with($userId)
- ->willReturn(null);
- $this->calendarStatusService->expects(self::never())
- ->method('processCalendarAvailability');
-
- $this->service->getCalendarStatus($userId);
- }
-
- public function testCalendarAvailabilityNoStatus(): void {
- $user = $this->createConfiguredMock(IUser::class, [
- 'getUID' => 'admin',
- 'getEMailAddress' => 'test@test.com',
- ]);
-
- $this->userManager->expects(self::once())
- ->method('get')
- ->with($user->getUID())
- ->willReturn($user);
- $this->calendarStatusService->expects(self::once())
- ->method('processCalendarAvailability')
- ->with($user)
- ->willReturn(null);
-
- $this->service->getCalendarStatus($user->getUID());
- }
}