aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/Paginate/PaginatePlugin.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav/lib/Paginate/PaginatePlugin.php')
-rw-r--r--apps/dav/lib/Paginate/PaginatePlugin.php95
1 files changed, 95 insertions, 0 deletions
diff --git a/apps/dav/lib/Paginate/PaginatePlugin.php b/apps/dav/lib/Paginate/PaginatePlugin.php
new file mode 100644
index 00000000000..c02eb9f21eb
--- /dev/null
+++ b/apps/dav/lib/Paginate/PaginatePlugin.php
@@ -0,0 +1,95 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+namespace OCA\DAV\Paginate;
+
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class PaginatePlugin extends ServerPlugin {
+ public const PAGINATE_HEADER = 'X-NC-Paginate';
+ public const PAGINATE_TOTAL_HEADER = 'X-NC-Paginate-Total';
+ public const PAGINATE_TOKEN_HEADER = 'X-NC-Paginate-Token';
+ public const PAGINATE_OFFSET_HEADER = 'X-NC-Paginate-Offset';
+ public const PAGINATE_COUNT_HEADER = 'X-NC-Paginate-Count';
+
+ /** @var Server */
+ private $server;
+
+ public function __construct(
+ private PaginateCache $cache,
+ private int $pageSize = 100,
+ ) {
+ }
+
+ public function initialize(Server $server): void {
+ $this->server = $server;
+ $server->on('beforeMultiStatus', [$this, 'onMultiStatus']);
+ $server->on('method:SEARCH', [$this, 'onMethod'], 1);
+ $server->on('method:PROPFIND', [$this, 'onMethod'], 1);
+ $server->on('method:REPORT', [$this, 'onMethod'], 1);
+ }
+
+ public function getFeatures(): array {
+ return ['nc-paginate'];
+ }
+
+ public function onMultiStatus(&$fileProperties): void {
+ $request = $this->server->httpRequest;
+ if (is_array($fileProperties)) {
+ $fileProperties = new \ArrayIterator($fileProperties);
+ }
+ $url = $request->getUrl();
+ if (
+ $request->hasHeader(self::PAGINATE_HEADER) &&
+ (!$request->hasHeader(self::PAGINATE_TOKEN_HEADER) || !$this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER)))
+ ) {
+ $pageSize = (int)$request->getHeader(self::PAGINATE_COUNT_HEADER) ?: $this->pageSize;
+ $offset = (int)$request->getHeader(self::PAGINATE_OFFSET_HEADER);
+ $copyIterator = new LimitedCopyIterator($fileProperties, $pageSize, $offset);
+ ['token' => $token, 'count' => $count] = $this->cache->store($url, $copyIterator);
+
+ $fileProperties = $copyIterator->getRequestedItems();
+ $this->server->httpResponse->addHeader(self::PAGINATE_HEADER, 'true');
+ $this->server->httpResponse->addHeader(self::PAGINATE_TOKEN_HEADER, $token);
+ $this->server->httpResponse->addHeader(self::PAGINATE_TOTAL_HEADER, (string)$count);
+ $request->setHeader(self::PAGINATE_TOKEN_HEADER, $token);
+ }
+ }
+
+ public function onMethod(RequestInterface $request, ResponseInterface $response) {
+ $url = $this->server->httpRequest->getUrl();
+ if (
+ $request->hasHeader(self::PAGINATE_TOKEN_HEADER) &&
+ $request->hasHeader(self::PAGINATE_OFFSET_HEADER) &&
+ $this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER))
+ ) {
+ $token = $request->getHeader(self::PAGINATE_TOKEN_HEADER);
+ $offset = (int)$request->getHeader(self::PAGINATE_OFFSET_HEADER);
+ $count = (int)$request->getHeader(self::PAGINATE_COUNT_HEADER) ?: $this->pageSize;
+
+ $items = $this->cache->get($url, $token, $offset, $count);
+
+ $response->setStatus(207);
+ $response->addHeader(self::PAGINATE_HEADER, 'true');
+ $response->setHeader('Content-Type', 'application/xml; charset=utf-8');
+ $response->setHeader('Vary', 'Brief,Prefer');
+
+ $prefer = $this->server->getHTTPPrefer();
+ $minimal = $prefer['return'] === 'minimal';
+
+ $data = $this->server->generateMultiStatus($items, $minimal);
+ $response->setBody($data);
+
+ return false;
+ }
+ }
+}