Skip to content

Commit 5d566da

Browse files
fix: PageIterator avoids making double calls on current (#9236)
1 parent 8fb12f2 commit 5d566da

2 files changed

Lines changed: 56 additions & 7 deletions

File tree

Core/src/Iterator/PageIteratorTrait.php

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ trait PageIteratorTrait
8383
*/
8484
private $initialResultToken;
8585

86+
/**
87+
* @var bool
88+
*/
89+
private $isInitialized = false;
90+
8691
/**
8792
* @param callable $resultMapper Maps a result.
8893
* @param callable $call The call to execute.
@@ -142,15 +147,13 @@ public function nextResultToken()
142147
}
143148

144149
/**
145-
* Rewind the iterator.
146-
*
147-
* @return null
150+
* Set up the initial pagination state and tokens.
148151
*/
149-
#[\ReturnTypeWillChange]
150-
public function rewind()
152+
private function initialize()
151153
{
152-
$this->itemCount = 0;
153-
$this->position = 0;
154+
if ($this->isInitialized) {
155+
return;
156+
}
154157

155158
if ($this->config['firstPage']) {
156159
list($this->page, $shouldContinue) = $this->mapResults($this->config['firstPage']);
@@ -163,6 +166,23 @@ public function rewind()
163166
if ($nextResultToken) {
164167
$this->set($this->resultTokenPath, $this->callOptions, $nextResultToken);
165168
}
169+
170+
$this->isInitialized = true;
171+
}
172+
173+
/**
174+
* Rewind the iterator.
175+
*
176+
* @return null
177+
*/
178+
#[\ReturnTypeWillChange]
179+
public function rewind()
180+
{
181+
$this->isInitialized = false;
182+
$this->initialize();
183+
184+
$this->itemCount = 0;
185+
$this->position = 0;
166186
}
167187

168188
/**
@@ -173,6 +193,8 @@ public function rewind()
173193
#[\ReturnTypeWillChange]
174194
public function current()
175195
{
196+
$this->initialize();
197+
176198
if ($this->page === null) {
177199
$this->page = $this->executeCall();
178200
}

Core/tests/Unit/Iterator/PageIteratorTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,33 @@ public function iteratorDataProvider()
137137
];
138138
}
139139

140+
public function testCurrentWithoutRewindUsesFirstPage()
141+
{
142+
$hasCalledNetwork = false;
143+
$call = function (array $options) use (&$hasCalledNetwork) {
144+
$hasCalledNetwork = true;
145+
return ['items' => ['should-not-reach-here']];
146+
};
147+
148+
$pages = new PageIterator(
149+
function ($result) {
150+
return strtoupper($result);
151+
},
152+
$call,
153+
['itemsKey' => 'items'],
154+
[
155+
'firstPage' => [
156+
'items' => self::$page1
157+
]
158+
]
159+
);
160+
161+
$currentPage = $pages->current();
162+
163+
$this->assertFalse($hasCalledNetwork);
164+
$this->assertEquals(array_map('strtoupper', self::$page1), $currentPage);
165+
}
166+
140167
public function theCall(array $options)
141168
{
142169
$options += [

0 commit comments

Comments
 (0)