diff --git a/Core/src/Iterator/PageIteratorTrait.php b/Core/src/Iterator/PageIteratorTrait.php index bbf0ff8e1bd6..db285296c318 100644 --- a/Core/src/Iterator/PageIteratorTrait.php +++ b/Core/src/Iterator/PageIteratorTrait.php @@ -83,6 +83,11 @@ trait PageIteratorTrait */ private $initialResultToken; + /** + * @var bool + */ + private $isInitialized = false; + /** * @param callable $resultMapper Maps a result. * @param callable $call The call to execute. @@ -142,15 +147,13 @@ public function nextResultToken() } /** - * Rewind the iterator. - * - * @return null + * Set up the initial pagination state and tokens. */ - #[\ReturnTypeWillChange] - public function rewind() + private function initialize() { - $this->itemCount = 0; - $this->position = 0; + if ($this->isInitialized) { + return; + } if ($this->config['firstPage']) { list($this->page, $shouldContinue) = $this->mapResults($this->config['firstPage']); @@ -163,6 +166,23 @@ public function rewind() if ($nextResultToken) { $this->set($this->resultTokenPath, $this->callOptions, $nextResultToken); } + + $this->isInitialized = true; + } + + /** + * Rewind the iterator. + * + * @return null + */ + #[\ReturnTypeWillChange] + public function rewind() + { + $this->isInitialized = false; + $this->initialize(); + + $this->itemCount = 0; + $this->position = 0; } /** @@ -173,6 +193,10 @@ public function rewind() #[\ReturnTypeWillChange] public function current() { + if (!$this->isInitialized) { + $this->initialize(); + } + if ($this->page === null) { $this->page = $this->executeCall(); } diff --git a/Core/tests/Unit/Iterator/PageIteratorTest.php b/Core/tests/Unit/Iterator/PageIteratorTest.php index 887268febca1..0d7fb3250cb4 100644 --- a/Core/tests/Unit/Iterator/PageIteratorTest.php +++ b/Core/tests/Unit/Iterator/PageIteratorTest.php @@ -137,6 +137,33 @@ public function iteratorDataProvider() ]; } + public function testCurrentWithoutRewindUsesFirstPage() + { + $hasCalledNetwork = false; + $call = function (array $options) use (&$hasCalledNetwork) { + $hasCalledNetwork = true; + return ['items' => ['should-not-reach-here']]; + }; + + $pages = new PageIterator( + function ($result) { + return strtoupper($result); + }, + $call, + ['itemsKey' => 'items'], + [ + 'firstPage' => [ + 'items' => self::$page1 + ] + ] + ); + + $currentPage = $pages->current(); + + $this->assertFalse($hasCalledNetwork); + $this->assertEquals(array_map('strtoupper', self::$page1), $currentPage); + } + public function theCall(array $options) { $options += [