123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- namespace Zend\Config;
- use ArrayAccess;
- use Countable;
- use Iterator;
- /**
- * Provides a property based interface to an array.
- * The data are read-only unless $allowModifications is set to true
- * on construction.
- *
- * Implements Countable, Iterator and ArrayAccess
- * to facilitate easy access to the data.
- */
- class Config implements Countable, Iterator, ArrayAccess
- {
- /**
- * Whether modifications to configuration data are allowed.
- *
- * @var bool
- */
- protected $allowModifications;
- /**
- * Number of elements in configuration data.
- *
- * @var int
- */
- protected $count;
- /**
- * Data within the configuration.
- *
- * @var array
- */
- protected $data = array();
- /**
- * Used when unsetting values during iteration to ensure we do not skip
- * the next element.
- *
- * @var bool
- */
- protected $skipNextIteration;
- /**
- * Constructor.
- *
- * Data is read-only unless $allowModifications is set to true
- * on construction.
- *
- * @param array $array
- * @param bool $allowModifications
- */
- public function __construct(array $array, $allowModifications = false)
- {
- $this->allowModifications = (bool) $allowModifications;
- foreach ($array as $key => $value) {
- if (is_array($value)) {
- $this->data[$key] = new static($value, $this->allowModifications);
- } else {
- $this->data[$key] = $value;
- }
- $this->count++;
- }
- }
- /**
- * Retrieve a value and return $default if there is no element set.
- *
- * @param string $name
- * @param mixed $default
- * @return mixed
- */
- public function get($name, $default = null)
- {
- if (array_key_exists($name, $this->data)) {
- return $this->data[$name];
- }
- return $default;
- }
- /**
- * Magic function so that $obj->value will work.
- *
- * @param string $name
- * @return mixed
- */
- public function __get($name)
- {
- return $this->get($name);
- }
- /**
- * Set a value in the config.
- *
- * Only allow setting of a property if $allowModifications was set to true
- * on construction. Otherwise, throw an exception.
- *
- * @param string $name
- * @param mixed $value
- * @return void
- * @throws Exception\RuntimeException
- */
- public function __set($name, $value)
- {
- if ($this->allowModifications) {
- if (is_array($value)) {
- $value = new static($value, true);
- }
- if (null === $name) {
- $this->data[] = $value;
- } else {
- $this->data[$name] = $value;
- }
- $this->count++;
- } else {
- throw new Exception\RuntimeException('Config is read only');
- }
- }
- /**
- * Deep clone of this instance to ensure that nested Zend\Configs are also
- * cloned.
- *
- * @return void
- */
- public function __clone()
- {
- $array = array();
- foreach ($this->data as $key => $value) {
- if ($value instanceof self) {
- $array[$key] = clone $value;
- } else {
- $array[$key] = $value;
- }
- }
- $this->data = $array;
- }
- /**
- * Return an associative array of the stored data.
- *
- * @return array
- */
- public function toArray()
- {
- $array = array();
- $data = $this->data;
- /** @var self $value */
- foreach ($data as $key => $value) {
- if ($value instanceof self) {
- $array[$key] = $value->toArray();
- } else {
- $array[$key] = $value;
- }
- }
- return $array;
- }
- /**
- * isset() overloading
- *
- * @param string $name
- * @return bool
- */
- public function __isset($name)
- {
- return isset($this->data[$name]);
- }
- /**
- * unset() overloading
- *
- * @param string $name
- * @return void
- * @throws Exception\InvalidArgumentException
- */
- public function __unset($name)
- {
- if (!$this->allowModifications) {
- throw new Exception\InvalidArgumentException('Config is read only');
- } elseif (isset($this->data[$name])) {
- unset($this->data[$name]);
- $this->count--;
- $this->skipNextIteration = true;
- }
- }
- /**
- * count(): defined by Countable interface.
- *
- * @see Countable::count()
- * @return int
- */
- public function count()
- {
- return $this->count;
- }
- /**
- * current(): defined by Iterator interface.
- *
- * @see Iterator::current()
- * @return mixed
- */
- public function current()
- {
- $this->skipNextIteration = false;
- return current($this->data);
- }
- /**
- * key(): defined by Iterator interface.
- *
- * @see Iterator::key()
- * @return mixed
- */
- public function key()
- {
- return key($this->data);
- }
- /**
- * next(): defined by Iterator interface.
- *
- * @see Iterator::next()
- * @return void
- */
- public function next()
- {
- if ($this->skipNextIteration) {
- $this->skipNextIteration = false;
- return;
- }
- next($this->data);
- }
- /**
- * rewind(): defined by Iterator interface.
- *
- * @see Iterator::rewind()
- * @return void
- */
- public function rewind()
- {
- $this->skipNextIteration = false;
- reset($this->data);
- }
- /**
- * valid(): defined by Iterator interface.
- *
- * @see Iterator::valid()
- * @return bool
- */
- public function valid()
- {
- return ($this->key() !== null);
- }
- /**
- * offsetExists(): defined by ArrayAccess interface.
- *
- * @see ArrayAccess::offsetExists()
- * @param mixed $offset
- * @return bool
- */
- public function offsetExists($offset)
- {
- return $this->__isset($offset);
- }
- /**
- * offsetGet(): defined by ArrayAccess interface.
- *
- * @see ArrayAccess::offsetGet()
- * @param mixed $offset
- * @return mixed
- */
- public function offsetGet($offset)
- {
- return $this->__get($offset);
- }
- /**
- * offsetSet(): defined by ArrayAccess interface.
- *
- * @see ArrayAccess::offsetSet()
- * @param mixed $offset
- * @param mixed $value
- * @return void
- */
- public function offsetSet($offset, $value)
- {
- $this->__set($offset, $value);
- }
- /**
- * offsetUnset(): defined by ArrayAccess interface.
- *
- * @see ArrayAccess::offsetUnset()
- * @param mixed $offset
- * @return void
- */
- public function offsetUnset($offset)
- {
- $this->__unset($offset);
- }
- /**
- * Merge another Config with this one.
- *
- * For duplicate keys, the following will be performed:
- * - Nested Configs will be recursively merged.
- * - Items in $merge with INTEGER keys will be appended.
- * - Items in $merge with STRING keys will overwrite current values.
- *
- * @param Config $merge
- * @return Config
- */
- public function merge(Config $merge)
- {
- /** @var Config $value */
- foreach ($merge as $key => $value) {
- if (array_key_exists($key, $this->data)) {
- if (is_int($key)) {
- $this->data[] = $value;
- } elseif ($value instanceof self && $this->data[$key] instanceof self) {
- $this->data[$key]->merge($value);
- } else {
- if ($value instanceof self) {
- $this->data[$key] = new static($value->toArray(), $this->allowModifications);
- } else {
- $this->data[$key] = $value;
- }
- }
- } else {
- if ($value instanceof self) {
- $this->data[$key] = new static($value->toArray(), $this->allowModifications);
- } else {
- $this->data[$key] = $value;
- }
- $this->count++;
- }
- }
- return $this;
- }
- /**
- * Prevent any more modifications being made to this instance.
- *
- * Useful after merge() has been used to merge multiple Config objects
- * into one object which should then not be modified again.
- *
- * @return void
- */
- public function setReadOnly()
- {
- $this->allowModifications = false;
- /** @var Config $value */
- foreach ($this->data as $value) {
- if ($value instanceof self) {
- $value->setReadOnly();
- }
- }
- }
- /**
- * Returns whether this Config object is read only or not.
- *
- * @return bool
- */
- public function isReadOnly()
- {
- return !$this->allowModifications;
- }
- }
|