diff options
Diffstat (limited to 'apps/dav/lib/CalDAV/Trashbin/Plugin.php')
-rw-r--r-- | apps/dav/lib/CalDAV/Trashbin/Plugin.php | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/apps/dav/lib/CalDAV/Trashbin/Plugin.php b/apps/dav/lib/CalDAV/Trashbin/Plugin.php new file mode 100644 index 00000000000..6f58b1f3110 --- /dev/null +++ b/apps/dav/lib/CalDAV/Trashbin/Plugin.php @@ -0,0 +1,114 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\DAV\CalDAV\Trashbin; + +use Closure; +use DateTimeImmutable; +use DateTimeInterface; +use OCA\DAV\CalDAV\Calendar; +use OCA\DAV\CalDAV\RetentionService; +use OCP\IRequest; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\INode; +use Sabre\DAV\PropFind; +use Sabre\DAV\Server; +use Sabre\DAV\ServerPlugin; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; +use function array_slice; +use function implode; + +class Plugin extends ServerPlugin { + public const PROPERTY_DELETED_AT = '{http://nextcloud.com/ns}deleted-at'; + public const PROPERTY_CALENDAR_URI = '{http://nextcloud.com/ns}calendar-uri'; + public const PROPERTY_RETENTION_DURATION = '{http://nextcloud.com/ns}trash-bin-retention-duration'; + + /** @var bool */ + private $disableTrashbin; + + /** @var Server */ + private $server; + + public function __construct( + IRequest $request, + private RetentionService $retentionService, + ) { + $this->disableTrashbin = $request->getHeader('X-NC-CalDAV-No-Trashbin') === '1'; + } + + public function initialize(Server $server): void { + $this->server = $server; + $server->on('beforeMethod:*', [$this, 'beforeMethod']); + $server->on('propFind', Closure::fromCallable([$this, 'propFind'])); + } + + public function beforeMethod(RequestInterface $request, ResponseInterface $response): void { + if (!$this->disableTrashbin) { + return; + } + + $path = $request->getPath(); + $pathParts = explode('/', ltrim($path, '/')); + if (\count($pathParts) < 3) { + // We are looking for a path like calendars/username/calendarname + return; + } + + // $calendarPath will look like calendars/username/calendarname + $calendarPath = implode( + '/', + array_slice($pathParts, 0, 3) + ); + try { + $calendar = $this->server->tree->getNodeForPath($calendarPath); + if (!($calendar instanceof Calendar)) { + // This is odd + return; + } + + /** @var Calendar $calendar */ + $calendar->disableTrashbin(); + } catch (NotFound $ex) { + return; + } + } + + private function propFind( + PropFind $propFind, + INode $node): void { + if ($node instanceof DeletedCalendarObject) { + $propFind->handle(self::PROPERTY_DELETED_AT, function () use ($node) { + $ts = $node->getDeletedAt(); + if ($ts === null) { + return null; + } + + return (new DateTimeImmutable()) + ->setTimestamp($ts) + ->format(DateTimeInterface::ATOM); + }); + $propFind->handle(self::PROPERTY_CALENDAR_URI, function () use ($node) { + return $node->getCalendarUri(); + }); + } + if ($node instanceof TrashbinHome) { + $propFind->handle(self::PROPERTY_RETENTION_DURATION, function () use ($node) { + return $this->retentionService->getDuration(); + }); + } + } + + public function getFeatures(): array { + return ['nc-calendar-trashbin']; + } + + public function getPluginName(): string { + return 'nc-calendar-trashbin'; + } +} |