* @implements ArrayAccess * @implements Iterator */ class Collection implements ArrayAccess, Iterator, Countable, JsonSerializable { /** * Collection data. * * @var array */ private array $data; /** * Constructor. * * @param array $data Initial data */ public function __construct(array $data = []) { $this->data = $data; } /** * Gets an item. * * @return mixed Value if `$key` exists in collection data, otherwise returns `NULL` */ public function __get(string $key) { return $this->data[$key] ?? null; } /** * Set an item. * * @param mixed $value Value */ public function __set(string $key, $value): void { $this->data[$key] = $value; } /** * Checks if an item exists. */ public function __isset(string $key): bool { return isset($this->data[$key]); } /** * Removes an item. */ public function __unset(string $key): void { unset($this->data[$key]); } /** * Gets an item at the offset. * * @param string $offset Offset * * @return mixed Value */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->data[$offset] ?? null; } /** * Sets an item at the offset. * * @param ?string $offset Offset * @param mixed $value Value */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value): void { if ($offset === null) { $this->data[] = $value; } else { $this->data[$offset] = $value; } } /** * Checks if an item exists at the offset. * * @param string $offset */ public function offsetExists($offset): bool { return isset($this->data[$offset]); } /** * Removes an item at the offset. * * @param string $offset */ public function offsetUnset($offset): void { unset($this->data[$offset]); } /** * Resets the collection. */ public function rewind(): void { reset($this->data); } /** * Gets current collection item. * * @return mixed Value */ #[\ReturnTypeWillChange] public function current() { return current($this->data); } /** * Gets current collection key. * * @return mixed Value */ #[\ReturnTypeWillChange] public function key() { return key($this->data); } /** * Gets the next collection value. */ #[\ReturnTypeWillChange] public function next(): void { next($this->data); } /** * Checks if the current collection key is valid. */ public function valid(): bool { return key($this->data) !== null; } /** * Gets the size of the collection. */ public function count(): int { return \count($this->data); } /** * Gets the item keys. * * @return array Collection keys */ public function keys(): array { return array_keys($this->data); } /** * Gets the collection data. * * @return array Collection data */ public function getData(): array { return $this->data; } /** * Sets the collection data. * * @param array $data New collection data */ public function setData(array $data): void { $this->data = $data; } #[\ReturnTypeWillChange] public function jsonSerialize() { return $this->data; } /** * Removes all items from the collection. */ public function clear(): void { $this->data = []; } }