Simplify Loop code

This commit is contained in:
Fabien Potencier
2024-07-11 08:41:17 +02:00
parent d1a13da220
commit 0c2a69ceb3
2 changed files with 21 additions and 41 deletions
+12 -36
View File
@@ -23,11 +23,7 @@ use Twig\Error\RuntimeError;
final class Loop implements \Iterator final class Loop implements \Iterator
{ {
private \Iterator $seq; private \Iterator $seq;
private bool $iterated;
private int $index0; private int $index0;
private int $revindex0;
private bool $first;
private bool $last;
private int $length; private int $length;
public function __construct($seq, private $parent) public function __construct($seq, private $parent)
@@ -49,29 +45,13 @@ final class Loop implements \Iterator
public function next(): void public function next(): void
{ {
$this->seq->next(); $this->seq->next();
$this->iterated = true;
++$this->index0; ++$this->index0;
$this->first = false;
if (isset($this->length)) {
--$this->revindex0;
$this->last = 0 === $this->revindex0;
}
} }
public function rewind(): void public function rewind(): void
{ {
$this->seq->rewind(); $this->seq->rewind();
$this->iterated = false;
$this->index0 = 0; $this->index0 = 0;
$this->first = true;
if ($this->seq instanceof \Countable) {
$length = count($this->seq);
$this->revindex0 = $length - 1;
$this->length = $length;
$this->last = 1 === $length;
}
} }
public function valid(): bool public function valid(): bool
@@ -81,7 +61,7 @@ final class Loop implements \Iterator
public function iterated(): bool public function iterated(): bool
{ {
return $this->iterated; return 0 !== $this->index0;
} }
public function getParent(): mixed public function getParent(): mixed
@@ -91,11 +71,7 @@ final class Loop implements \Iterator
public function getRevindex0(): int public function getRevindex0(): int
{ {
if (!$this->seq instanceof \Countable) { return $this->getLength('revindex0') - $this->index0 - 1;
throw new RuntimeError('The "loop.revindex0" variable is not defined as the loop iterates on a non-countable iterator.');
}
return $this->revindex0;
} }
public function getIndex0(): int public function getIndex0(): int
@@ -103,26 +79,26 @@ final class Loop implements \Iterator
return $this->index0; return $this->index0;
} }
public function getLength(): int public function getLength($var = 'length'): int
{ {
if (!$this->seq instanceof \Countable) { if (isset($this->length)) {
throw new RuntimeError('The "loop.length" variable is not defined as the loop iterates on a non-countable iterator.'); return $this->length;
} }
return $this->length; if (!$this->seq instanceof \Countable) {
throw new RuntimeError(sprintf('The "loop.%s" variable is not defined as the loop iterates on a non-countable iterator.', $var));
}
return $this->length = count($this->seq);
} }
public function isFirst(): bool public function isFirst(): bool
{ {
return $this->first; return 0 === $this->index0;
} }
public function isLast(): bool public function isLast(): bool
{ {
if (!$this->seq instanceof \Countable) { return 0 === $this->getLength('last') - $this->index0 - 1;
throw new RuntimeError('The "loop.last" variable is not defined as the loop iterates on a non-countable iterator.');
}
return $this->last;
} }
} }
+9 -5
View File
@@ -4,16 +4,20 @@
{% for item in items %} {% for item in items %}
* {{ loop.index }}/{{ loop.index0 }} * {{ loop.index }}/{{ loop.index0 }}
* {{ loop.revindex }}/{{ loop.revindex0 }} * {{ loop.revindex }}/{{ loop.revindex0 }}
* {{ loop.first }}/{{ loop.last }}/{{ loop.length }} * {{ loop.first ? 'FIRST' : '-' }}/{{ loop.last ? 'LAST' : '-' }}/{{ loop.length }}
{% endfor %} {% endfor %}
--DATA-- --DATA--
return ['items' => ['a', 'b']] return ['items' => ['a', 'b', 'c']]
--EXPECT-- --EXPECT--
* 1/0 * 1/0
* 2/1 * 3/2
* 1//2 * FIRST/-/3
* 2/1 * 2/1
* 2/1
* -/-/3
* 3/2
* 1/0 * 1/0
* /1/2 * -/LAST/3