diff options
Diffstat (limited to 'apps/dav/lib')
-rw-r--r-- | apps/dav/lib/CalDAV/UpcomingEvent.php | 67 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/UpcomingEventsService.php | 64 | ||||
-rw-r--r-- | apps/dav/lib/Controller/UpcomingEventsController.php | 62 | ||||
-rw-r--r-- | apps/dav/lib/ResponseDefinitions.php | 11 |
4 files changed, 204 insertions, 0 deletions
diff --git a/apps/dav/lib/CalDAV/UpcomingEvent.php b/apps/dav/lib/CalDAV/UpcomingEvent.php new file mode 100644 index 00000000000..26760ffedd5 --- /dev/null +++ b/apps/dav/lib/CalDAV/UpcomingEvent.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV; + +use JsonSerializable; +use OCA\DAV\ResponseDefinitions; + +class UpcomingEvent implements JsonSerializable { + public function __construct(private string $uri, + private ?int $recurrenceId, + private string $calendarUri, + private ?int $start, + private ?string $summary, + private ?string $location, + private ?string $calendarAppUrl) { + } + + public function getUri(): string { + return $this->uri; + } + + public function getRecurrenceId(): ?int { + return $this->recurrenceId; + } + + public function getCalendarUri(): string { + return $this->calendarUri; + } + + public function getStart(): ?int { + return $this->start; + } + + public function getSummary(): ?string { + return $this->summary; + } + + public function getLocation(): ?string { + return $this->location; + } + + public function getCalendarAppUrl(): ?string { + return $this->calendarAppUrl; + } + + /** + * @see ResponseDefinitions + */ + public function jsonSerialize(): array { + return [ + 'uri' => $this->uri, + 'recurrenceId' => $this->recurrenceId, + 'calendarUri' => $this->calendarUri, + 'start' => $this->start, + 'summary' => $this->summary, + 'location' => $this->location, + 'calendarAppUrl' => $this->calendarAppUrl, + ]; + } +} diff --git a/apps/dav/lib/CalDAV/UpcomingEventsService.php b/apps/dav/lib/CalDAV/UpcomingEventsService.php new file mode 100644 index 00000000000..04ab1be19b4 --- /dev/null +++ b/apps/dav/lib/CalDAV/UpcomingEventsService.php @@ -0,0 +1,64 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\CalDAV; + +use OCP\App\IAppManager; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Calendar\IManager; +use OCP\IURLGenerator; +use OCP\IUserManager; +use function array_map; + +class UpcomingEventsService { + public function __construct(private IManager $calendarManager, + private ITimeFactory $timeFactory, + private IUserManager $userManager, + private IAppManager $appManager, + private IURLGenerator $urlGenerator) { + } + + /** + * @return UpcomingEvent[] + */ + public function getEvents(string $userId, ?string $location = null): array { + $searchQuery = $this->calendarManager->newQuery('principals/users/' . $userId); + if ($location !== null) { + $searchQuery->addSearchProperty('LOCATION'); + $searchQuery->setSearchPattern($location); + } + $searchQuery->addType('VEVENT'); + $searchQuery->setLimit(3); + $now = $this->timeFactory->now(); + $searchQuery->setTimerangeStart($now->modify('-1 minute')); + $searchQuery->setTimerangeEnd($now->modify('+1 month')); + + $events = $this->calendarManager->searchForPrincipal($searchQuery); + $calendarAppEnabled = $this->appManager->isEnabledForUser( + 'calendar', + $this->userManager->get($userId), + ); + + return array_map(fn (array $event) => new UpcomingEvent( + $event['uri'], + ($event['objects'][0]['RECURRENCE-ID'][0] ?? null)?->getTimeStamp(), + $event['calendar-uri'], + $event['objects'][0]['DTSTART'][0]?->getTimestamp(), + $event['objects'][0]['SUMMARY'][0] ?? null, + $event['objects'][0]['LOCATION'][0] ?? null, + match ($calendarAppEnabled) { + // TODO: create a named, deep route in calendar + // TODO: it's a code smell to just assume this route exists, find an abstraction + true => $this->urlGenerator->linkToRouteAbsolute('calendar.view.index'), + false => null, + }, + ), $events); + } + +} diff --git a/apps/dav/lib/Controller/UpcomingEventsController.php b/apps/dav/lib/Controller/UpcomingEventsController.php new file mode 100644 index 00000000000..879fe05d613 --- /dev/null +++ b/apps/dav/lib/Controller/UpcomingEventsController.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\Controller; + +use OCA\DAV\AppInfo\Application; +use OCA\DAV\CalDAV\UpcomingEvent; +use OCA\DAV\CalDAV\UpcomingEventsService; +use OCA\DAV\ResponseDefinitions; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; +use OCP\IRequest; + +/** + * @psalm-import-type DAVUpcomingEvent from ResponseDefinitions + */ +class UpcomingEventsController extends OCSController { + private ?string $userId; + private UpcomingEventsService $service; + + public function __construct( + IRequest $request, + ?string $userId, + UpcomingEventsService $service) { + parent::__construct(Application::APP_ID, $request); + + $this->userId = $userId; + $this->service = $service; + } + + /** + * Get information about upcoming events + * + * @param string|null $location location/URL to filter by + * @return DataResponse<Http::STATUS_OK, array{events: DAVUpcomingEvent[]}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, null, array{}> + * + * 200: Upcoming events + * 401: When not authenticated + */ + #[NoAdminRequired] + public function getEvents(?string $location = null): DataResponse { + if ($this->userId === null) { + return new DataResponse(null, Http::STATUS_UNAUTHORIZED); + } + + return new DataResponse([ + 'events' => array_map(fn (UpcomingEvent $e) => $e->jsonSerialize(), $this->service->getEvents( + $this->userId, + $location, + )), + ]); + } + +} diff --git a/apps/dav/lib/ResponseDefinitions.php b/apps/dav/lib/ResponseDefinitions.php index 2dc0d4e8dbd..3deafad6704 100644 --- a/apps/dav/lib/ResponseDefinitions.php +++ b/apps/dav/lib/ResponseDefinitions.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace OCA\DAV; +use OCA\DAV\CalDAV\UpcomingEvent; + /** * @psalm-type DAVOutOfOfficeDataCommon = array{ * userId: string, @@ -31,6 +33,15 @@ namespace OCA\DAV; * endDate: int, * shortMessage: string, * } + * + * @see UpcomingEvent::jsonSerialize + * @psalm-type DAVUpcomingEvent = array{ + * uri: string, + * calendarUri: string, + * start: ?int, + * summary: ?string, + * location: ?string, + * } */ class ResponseDefinitions { } |