<?php /** * RouterOS API client implementation. * * RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts. * * PHP version 5 * * @category Net * @package PEAR2_Net_RouterOS * @author Vasil Rangelov <boen.robot@gmail.com> * @copyright 2011 Vasil Rangelov * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @version 1.0.0b4 * @link http://pear2.php.net/PEAR2_Net_RouterOS */ /** * The namespace declaration. */ namespace PEAR2\Net\RouterOS; /** * Represents a collection of RouterOS responses. * * @category Net * @package PEAR2_Net_RouterOS * @author Vasil Rangelov <boen.robot@gmail.com> * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 * @link http://pear2.php.net/PEAR2_Net_RouterOS */ class ResponseCollection implements \ArrayAccess, \SeekableIterator, \Countable { /** * @var array An array with all {@link Response} objects. */ protected $responses = array(); /** * @var array An array with each {@link Response} object's type. */ protected $responseTypes = array(); /** * @var array An array with each {@link Response} object's tag. */ protected $responseTags = array(); /** * @var array An array with all distinct arguments across all * {@link Response} objects. Created at the first call of * {@link getArgumentMap()}. */ protected $argumentMap = null; /** * @var int A pointer, as required by SeekableIterator. */ protected $position = 0; /** * Creates a new collection. * * @param array $responses An array of responses, in network order. */ public function __construct(array $responses) { $index = 0; foreach ($responses as $response) { if ($response instanceof Response) { $this->responseTypes[$index] = $response->getType(); $this->responseTags[$index] = $response->getTag(); $this->responses[$index++] = $response; } } } /** * A shorthand gateway. * * This is a magic PHP method that allows you to call the object as a * function. Depending on the argument given, one of the other functions in * the class is invoked and its returned value is returned by this function. * * @param int $offset The offset of the response to seek to. Setting NULL * will seek to the last response. * * @return Response The {@link Response} at the specified index, last * reponse if no index is provided or FALSE if the index is invalid or the * collection is empty. */ public function __invoke($offset = null) { return null === $offset ? $this->end() : $this->seek($offset); } /** * Gets the whole collection as an array. * * @return array An array with all responses, in network order. */ public function toArray() { return $this->responses; } /** * Counts the responses in the collection. * * @return int The number of responses in the collection. */ public function count() { return count($this->responses); } /** * Checks if an offset exists. * * @param int $offset The offset to check. * * @return bool TRUE if the offset exists, FALSE otherwise. */ public function offsetExists($offset) { return array_key_exists($offset, $this->responses); } /** * Gets a {@link Response} from a specified offset. * * @param int $offset The offset of the desired response. * * @return Response The response at the specified offset. */ public function offsetGet($offset) { return $this->responses[$offset]; } /** * N/A * * This method exists only because it is required for ArrayAccess. The * collection is read only. * * @param int $offset N/A * @param Response $value N/A * * @return void */ public function offsetSet($offset, $value) { } /** * N/A * * This method exists only because it is required for ArrayAccess. The * collection is read only. * * @param int $offset N/A * * @return void */ public function offsetUnset($offset) { } /** * Resets the pointer to 0, and returns the first response. * * @return Response The first response in the collection, or FALSE if the * collection is empty. */ public function rewind() { return $this->seek(0); } /** * Moves the position pointer to a specified position. * * @param int $position The position to move to. * * @return Response The {@link Response} at the specified position, or FALSE * if the specified position is not valid. */ public function seek($position) { $this->position = $position; return $this->current(); } /** * Moves the pointer forward by 1, and gets the next response. * * @return Response The next {@link Response} object, or FALSE if the * position is not valid. */ public function next() { ++$this->position; return $this->current(); } /** * Gets the response at the current pointer position. * * @return Response The response at the current pointer position, or FALSE * if the position is not valid. */ public function current() { return $this->valid() ? $this->responses[$this->position] : false; } /** * Moves the pointer backwards by 1, and gets the previous response. * * @return Response The next {@link Response} object, or FALSE if the * position is not valid. */ public function prev() { --$this->position; return $this->current(); } /** * Moves the pointer to the last valid position, and returns the last * response. * * @return Response The last response in the collection, or FALSE if the * collection is empty. */ public function end() { $this->position = count($this->responses) - 1; return $this->current(); } /** * Gets the key at the current pointer position. * * @return int The key at the current pointer position, i.e. the pointer * position itself, or FALSE if the position is not valid. */ public function key() { return $this->valid() ? $this->position : false; } /** * Checks if the pointer is still pointing to an existing offset. * * @return bool TRUE if the pointer is valid, FALSE otherwise. */ public function valid() { return $this->offsetExists($this->position); } /** * Gets all distinct argument names. * * Gets all distinct argument names across all responses. * * @return array An array with all distinct argument names as keys, and the * indexes at which they occur as values. */ public function getArgumentMap() { if (null === $this->argumentMap) { $arguments = array(); foreach ($this->responses as $index => $response) { foreach (array_keys($response->getAllArguments()) as $name) { if (!isset($arguments[$name])) { $arguments[$name] = array(); } $arguments[$name][] = $index; } } $this->argumentMap = $arguments; } return $this->argumentMap; } /** * Gets all responses of a specified type. * * @param string $type The response type to filter by. Valid values are the * Response::TYPE_* constants. * * @return ResponseCollection A new collection with responses of the * specified type. */ public function getAllOfType($type) { $result = array(); foreach (array_keys($this->responseTypes, $type, true) as $index) { $result[] = $this->responses[$index]; } return new ResponseCollection($result); } /** * Gets all responses with a specified tag. * * @param string $tag The tag to filter by. * * @return ResponseCollection A new collection with responses having the * specified tag. */ public function getAllTagged($tag) { $result = array(); foreach (array_keys($this->responseTags, $tag, true) as $index) { $result[] = $this->responses[$index]; } return new ResponseCollection($result); } /** * Gets the last {@link Response} in the collection. * * @return Response The last response in the collection or FALSE if the * collection is empty. */ public function getLast() { $offset = count($this->responses) - 1; return $offset >= 0 ? $this->responses[$offset] : false; } /** * Calls a method of the response pointed by the pointer. * * Calls a method of the response pointed by the pointer. This is a magic * PHP method, thanks to which any function you call on the collection that * is not defined will be redirected to the response. * * @param string $method The name of the method to call. * @param array $args The arguments to pass to the method. * * @return mixed Whatever the called function returns. */ public function __call($method, array $args) { return call_user_func_array( array($this->current(), $method), $args ); } }