-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45435 from nextcloud/feat/dav/upcoming-events-api
feat(dav): Add an API for upcoming events
- Loading branch information
Showing
11 changed files
with
525 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
)), | ||
]); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.