<?php namespace Xentral\Components\Exporter\Collection; use ArrayObject; use Closure; use Iterator; use IteratorAggregate; use Xentral\Components\Exporter\Exception\InvalidArgumentException; use Xentral\Components\Exporter\Exception\InvalidReturnTypeException; final class FormatterCollection implements Iterator { /** @var Iterator $data */ private $data; /** @var callable $callback */ private $callback; /** * @param array|Iterator $data * @param callable|Closure $callback * * @throws InvalidArgumentException */ public function __construct($data, $callback) { if (!is_callable($callback, false)) { throw new InvalidArgumentException('Callback is not callable'); } $this->callback = $callback; $type = gettype($data); if ($type === 'object') { $type = get_class($data); if ($data instanceof Iterator) { $type = 'Iterator'; } if ($data instanceof IteratorAggregate) { $type = 'IteratorAggregate'; } } switch ($type) { case 'array': $this->data = (new ArrayObject($data))->getIterator(); break; case 'Iterator': $this->data = $data; break; case 'IteratorAggregate': $this->data = $data->getIterator(); break; default: throw new InvalidArgumentException(sprintf('Unsupported type "%s".', $type)); break; } } /** * Return the current element * * @throws InvalidReturnTypeException * * @return mixed Can return any type. */ public function current() { $result = call_user_func($this->callback, $this->data->current()); if (!is_array($result)) { throw new InvalidReturnTypeException('Formatter return type is invalid . Callable must return an array.'); } return $result; } /** * Move forward to next element * * @return void */ public function next() { $this->data->next(); } /** * Return the key of the current element * * @return mixed scalar on success, or null on failure. */ public function key() { return $this->data->key(); } /** * Checks if current position is valid * * @return boolean Returns true on success or false on failure. */ public function valid() { return $this->data->valid(); } /** * Rewind the Iterator to the first element * * @return void */ public function rewind() { $this->data->rewind(); } }