Fix support for IteratorAggregate and EmptyIterator objects in loops

This commit is contained in:
Fabien Potencier
2024-07-16 18:24:17 +02:00
parent 05df869558
commit c93daeee73
2 changed files with 52 additions and 3 deletions
+19 -3
View File
@@ -34,7 +34,18 @@ final class LoopIterator implements \Iterator
public function __construct($seq)
{
$this->seq = is_iterable($seq) ? (is_array($seq) ? new \ArrayIterator($seq) : $seq) : new \ArrayIterator([]);
if (is_array($seq)) {
$this->seq = new \ArrayIterator($seq);
} elseif ($seq instanceof \IteratorAggregate) {
do {
$seq = $seq->getIterator();
} while ($seq instanceof \IteratorAggregate);
$this->seq = $seq;
} elseif (is_iterable($seq)) {
$this->seq = $seq;
} else {
$this->seq = new \EmptyIterator();
}
$this->rewind();
}
@@ -63,8 +74,13 @@ final class LoopIterator implements \Iterator
public function rewind(): void
{
$this->seq->rewind();
$this->previous = ['valid' => false, 'key' => null, 'value' => null];
$this->current = ['valid' => $this->seq->valid(), 'key' => $this->seq->key(), 'value' => $this->seq->current()];
if ($this->seq->valid()) {
$this->previous = ['valid' => false, 'key' => null, 'value' => null];
$this->current = ['valid' => $this->seq->valid(), 'key' => $this->seq->key(), 'value' => $this->seq->current()];
} else {
// EmptyIterator
$this->current = ['valid' => false, 'key' => null, 'value' => null];
}
$this->next = null;
$this->index0 = 0;
}
@@ -0,0 +1,33 @@
--TEST--
"for" tag supports IteratorAggregate
--TEMPLATE--
{% for item in items %}
{{ item }}
{% endfor %}
--DATA--
return ['items' => new class() implements IteratorAggregate {
public function getIterator(): Traversable
{
return new ArrayIterator(['a', 'b', 'c']);
}
}]
--EXPECT--
a
b
c
--DATA--
return ['items' => new class() implements IteratorAggregate {
public function getIterator(): Traversable
{
return new class() implements IteratorAggregate {
public function getIterator(): Traversable
{
return new ArrayIterator(['a', 'b', 'c']);
}
};
}
}]
--EXPECT--
a
b
c