Skip to content

Commit d6cb465

Browse files
committed
FIX: Make IsFirst and IsLast work as expected for PaginatedList (fixes silverstripe#11465)
1 parent dae7320 commit d6cb465

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

src/View/SSViewer_Scope.php

+15-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use SilverStripe\ORM\FieldType\DBFloat;
1111
use SilverStripe\ORM\FieldType\DBInt;
1212
use SilverStripe\ORM\FieldType\DBField;
13+
use SilverStripe\ORM\PaginatedList;
1314

1415
/**
1516
* This tracks the current scope for an SSViewer instance. It has three goals:
@@ -173,7 +174,7 @@ public function resetLocalScope()
173174
$this->popIndex,
174175
$this->upIndex,
175176
$this->currentIndex
176-
) = end($this->itemStack);
177+
) = end($this->itemStack);
177178
}
178179

179180
/**
@@ -305,8 +306,8 @@ public function next()
305306
}
306307

307308
if (!$this->itemIterator) {
308-
// Note: it is important that getIterator() is called before count() as implemenations may rely on
309-
// this to efficiency get both the number of records and an iterator (e.g. DataList does this)
309+
// Note: it is important that getIterator() is called before count() as implementations may rely on
310+
// this to efficiently get both the number of records and an iterator (e.g. DataList does this)
310311

311312
// Item may be an array or a regular IteratorAggregate
312313
if (is_array($this->item)) {
@@ -319,11 +320,19 @@ public function next()
319320
$this->itemIterator->rewind();
320321
}
321322

322-
// If the item implements Countable, use that to fetch the count, otherwise we have to inspect the
323-
// iterator and then rewind it.
324-
if ($this->item instanceof Countable) {
323+
// Special case: we *don't* want to use count() on PaginatedList. This is because it'll call
324+
// PaginatedList::count(), which currently returns the full list count rather than the count of items
325+
// on the current page (which is what we need for the iterator count)
326+
if ($this->item instanceof PaginatedList) {
327+
// We have to re-fetch the iterator before calling getInnerIterator(): we need to count a copy of the
328+
// inner iterator because it's a generator so can't be rewound or cloned
329+
$innerIterator = $this->item->getIterator()->getInnerIterator();
330+
$this->itemIteratorTotal = iterator_count($innerIterator);
331+
} elseif ($this->item instanceof Countable) {
332+
// If the item implements Countable, use that to fetch the count
325333
$this->itemIteratorTotal = count($this->item);
326334
} else {
335+
// Otherwise we have to inspect the iterator and then rewind it
327336
$this->itemIteratorTotal = iterator_count($this->itemIterator);
328337
$this->itemIterator->rewind();
329338
}

0 commit comments

Comments
 (0)