*/ class LazyCollection implements \IteratorAggregate { /** * @var callable */ private $source; /** * @param callable $source */ public function __construct($source) { $this->source = $source; } /** * Get all items in the collection. * * @return array */ public function all() : array { return \iterator_to_array($this->getIterator()); } /** * Get an item from the collection by key. * * @param TKey $key * @return TValue|null */ public function get($key) { foreach ($this as $outerKey => $outerValue) { if ($outerKey == $key) { return $outerValue; } } return null; } /** * Run a filter over each of the items. * * @param (callable(TValue, TKey): bool) $callback * @return self */ public function filter(callable $callback) : self { return new self(function () use($callback) { foreach ($this as $key => $value) { if ($callback($value, $key)) { (yield $key => $value); } } }); } /** * Get the first item from the collection passing the given truth test. * * @param (callable(TValue, TKey): bool)|null $callback * @return TValue|null */ public function first(?callable $callback = null) { $iterator = $this->getIterator(); if (\is_null($callback)) { if (!$iterator->valid()) { return null; } return $iterator->current(); } foreach ($iterator as $key => $value) { if ($callback($value, $key)) { return $value; } } return null; } /** * Run a map over each of the items. * * @template TMapValue * * @param callable(TValue, TKey): TMapValue $callback * @return static */ public function map(callable $callback) : self { return new self(function () use($callback) { foreach ($this as $key => $value) { (yield $key => $callback($value, $key)); } }); } /** * Take the first {$limit} items. * * @param int $limit * @return static */ public function take(int $limit) : self { return new self(function () use($limit) { $iterator = $this->getIterator(); while ($limit--) { if (!$iterator->valid()) { break; } (yield $iterator->key() => $iterator->current()); if ($limit) { $iterator->next(); } } }); } /** * Determine if all items pass the given truth test. * * @param (callable(TValue, TKey): bool) $callback * @return bool */ public function every(callable $callback) : bool { $iterator = $this->getIterator(); foreach ($iterator as $key => $value) { if (!$callback($value, $key)) { return \false; } } return \true; } /** * Count the number of items in the collection. * * @return int */ public function count() : int { return \iterator_count($this->getIterator()); } /** * Get an iterator for the items. * * @return Iterator */ public function getIterator() : \Iterator { return $this->makeIterator($this->source); } /** * Get an iterator for the given value. * * @template TIteratorKey of array-key * @template TIteratorValue * * @param IteratorAggregate|(callable(): \Generator) $source * @return Iterator */ protected function makeIterator($source) : \Iterator { if ($source instanceof \IteratorAggregate) { return $source->getIterator(); } return $source(); } }