diff --git a/apps/dav/lib/Paginate/LimitedCopyIterator.php b/apps/dav/lib/Paginate/LimitedCopyIterator.php index 7f19885bc7dea..c7bea43c54a56 100644 --- a/apps/dav/lib/Paginate/LimitedCopyIterator.php +++ b/apps/dav/lib/Paginate/LimitedCopyIterator.php @@ -20,6 +20,7 @@ class LimitedCopyIterator extends \AppendIterator { private array $skipped = []; private array $copy = []; + private readonly bool $hasOthers; public function __construct(\Traversable $iterator, int $count, int $offset = 0) { parent::__construct(); @@ -29,17 +30,17 @@ public function __construct(\Traversable $iterator, int $count, int $offset = 0) } $iterator = new \NoRewindIterator($iterator); - $i = 0; - while ($iterator->valid() && ++$i <= $offset) { - $this->skipped[] = $iterator->current(); + while ($iterator->valid() && count($this->skipped) < $offset) { + $this->skipped[$iterator->key()] = $iterator->current(); $iterator->next(); } while ($iterator->valid() && count($this->copy) < $count) { - $this->copy[] = $iterator->current(); + $this->copy[$iterator->key()] = $iterator->current(); $iterator->next(); } + $this->hasOthers = $iterator->valid() || count($this->skipped) > 0; $this->append(new \ArrayIterator($this->skipped)); $this->append($this->getRequestedItems()); $this->append($iterator); @@ -48,4 +49,11 @@ public function __construct(\Traversable $iterator, int $count, int $offset = 0) public function getRequestedItems(): \Iterator { return new \ArrayIterator($this->copy); } + + /** + * Are there any other items in the iterator aside from the requested ones + */ + public function hasOthers(): bool { + return $this->hasOthers; + } } diff --git a/apps/dav/lib/Paginate/PaginatePlugin.php b/apps/dav/lib/Paginate/PaginatePlugin.php index e1639189c15f7..234c7e25b75c6 100644 --- a/apps/dav/lib/Paginate/PaginatePlugin.php +++ b/apps/dav/lib/Paginate/PaginatePlugin.php @@ -59,17 +59,21 @@ public function onMultiStatus(&$fileProperties): void { $offset = (int)$request->getHeader(self::PAGINATE_OFFSET_HEADER); $copyIterator = new LimitedCopyIterator($fileProperties, $pageSize, $offset); - // wrap the iterator with another that renders XML, this way we - // cache XML, but we keep the first $pageSize elements as objects - // to use for the response of the first page. - $rendererGenerator = $this->getXmlRendererGenerator($copyIterator); - ['token' => $token, 'count' => $count] = $this->cache->store($url, $rendererGenerator); + + if ($copyIterator->hasOthers()) { + // wrap the iterator with another that renders XML, this way we + // cache XML, but we keep the first $pageSize elements as objects + // to use for the response of the first page. + $rendererGenerator = $this->getXmlRendererGenerator($copyIterator); + ['token' => $token, 'count' => $count] = $this->cache->store($url, $rendererGenerator); + + $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); + } $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); } } diff --git a/apps/dav/tests/unit/Paginate/LimitedCopyIteratorTest.php b/apps/dav/tests/unit/Paginate/LimitedCopyIteratorTest.php new file mode 100644 index 0000000000000..87dcc0175ed94 --- /dev/null +++ b/apps/dav/tests/unit/Paginate/LimitedCopyIteratorTest.php @@ -0,0 +1,34 @@ +assertEquals([1, 2, 3, 4, 5], iterator_to_array($copy->getRequestedItems())); + $this->assertTrue($copy->hasOthers()); + $this->assertEquals($data, iterator_to_array($copy)); + + $copy = new LimitedCopyIterator(new \ArrayIterator($data), 15, 0); + $this->assertEquals([1, 2, 3, 4, 5, 6, 7], iterator_to_array($copy->getRequestedItems())); + $this->assertFalse($copy->hasOthers()); + $this->assertEquals($data, iterator_to_array($copy)); + + $copy = new LimitedCopyIterator(new \ArrayIterator($data), 15, 1); + $this->assertEquals([1 => 2, 3, 4, 5, 6, 7], iterator_to_array($copy->getRequestedItems())); + $this->assertTrue($copy->hasOthers()); + $this->assertEquals($data, iterator_to_array($copy)); + } + +}