diff --git a/src/CallbackFilterIterator.php b/src/CallbackFilterIterator.php new file mode 100644 index 0000000..d119e05 --- /dev/null +++ b/src/CallbackFilterIterator.php @@ -0,0 +1,70 @@ +started = true; + + parent::rewind(); + } + + public function valid(): bool + { + if ($this->started) { + return parent::valid(); + } + + // As per php-src, \CallbackFilterIterator::rewind() forwards the iterator to the first valid element + // (https://github.com/php/php-src/blob/5cba2a3dc59ef2a0e432b05ab27f2b3ab4da48d0/ext/spl/spl_iterators.c#L1686) + $this->rewind(); + + return parent::valid(); + } + + #[\ReturnTypeWillChange] + public function key() + { + if ($this->started) { + return parent::key(); + } + + $this->rewind(); + + return parent::key(); + } + + #[\ReturnTypeWillChange] + public function current() + { + if ($this->started) { + return parent::current(); + } + + $this->rewind(); + + return parent::current(); + } +} diff --git a/tests/CallbackFilterIteratorTest.php b/tests/CallbackFilterIteratorTest.php new file mode 100644 index 0000000..0e67a03 --- /dev/null +++ b/tests/CallbackFilterIteratorTest.php @@ -0,0 +1,70 @@ + $v) { + $this->assertSame(1, $k); + $this->assertSame(2, $v); + } + } + + public function testValidBeforeRewind() + { + $iterator = new CallbackFilterIterator(new \ArrayIterator([1, 2, 3]), function (int $i) { + return $i === 2; + }); + + $this->assertTrue($iterator->valid()); + + $iterator->rewind(); + + $this->assertTrue($iterator->valid()); + } + + public function testKeyBeforeRewind() + { + $iterator = new CallbackFilterIterator(new \ArrayIterator([1, 2, 3]), function (int $i) { + return $i === 2; + }); + + $this->assertSame(1, $iterator->key()); + + $iterator->rewind(); + + $this->assertSame(1, $iterator->key()); + } + + public function testCurrentBeforeRewind() + { + $iterator = new CallbackFilterIterator(new \ArrayIterator([1, 2, 3]), function (int $i) { + return $i === 2; + }); + + $this->assertSame(2, $iterator->current()); + + $iterator->rewind(); + + $this->assertSame(2, $iterator->current()); + } + + public function testInvalidBeforeRewind() + { + $iterator = new CallbackFilterIterator(new \ArrayIterator([1, 2, 3]), function (int $i) { + return $i === 4; + }); + + $this->assertFalse($iterator->valid()); + $this->assertNull($iterator->key()); + $this->assertNull($iterator->current()); + } +}