3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Config
;
17 * Provides a property based interface to an array.
18 * The data are read-only unless $allowModifications is set to true
21 * Implements Countable, Iterator and ArrayAccess
22 * to facilitate easy access to the data.
24 class Config
implements Countable
, Iterator
, ArrayAccess
27 * Whether modifications to configuration data are allowed.
31 protected $allowModifications;
34 * Number of elements in configuration data.
41 * Data within the configuration.
45 protected $data = array();
48 * Used when unsetting values during iteration to ensure we do not skip
53 protected $skipNextIteration;
58 * Data is read-only unless $allowModifications is set to true
62 * @param bool $allowModifications
64 public function __construct(array $array, $allowModifications = false)
66 $this->allowModifications
= (bool) $allowModifications;
68 foreach ($array as $key => $value) {
69 if (is_array($value)) {
70 $this->data
[$key] = new static($value, $this->allowModifications
);
72 $this->data
[$key] = $value;
80 * Retrieve a value and return $default if there is no element set.
83 * @param mixed $default
86 public function get($name, $default = null)
88 if (array_key_exists($name, $this->data
)) {
89 return $this->data
[$name];
96 * Magic function so that $obj->value will work.
101 public function __get($name)
103 return $this->get($name);
107 * Set a value in the config.
109 * Only allow setting of a property if $allowModifications was set to true
110 * on construction. Otherwise, throw an exception.
112 * @param string $name
113 * @param mixed $value
115 * @throws Exception\RuntimeException
117 public function __set($name, $value)
119 if ($this->allowModifications
) {
121 if (is_array($value)) {
122 $value = new static($value, true);
125 if (null === $name) {
126 $this->data
[] = $value;
128 $this->data
[$name] = $value;
133 throw new Exception\
RuntimeException('Config is read only');
138 * Deep clone of this instance to ensure that nested Zend\Configs are also
143 public function __clone()
147 foreach ($this->data
as $key => $value) {
148 if ($value instanceof self
) {
149 $array[$key] = clone $value;
151 $array[$key] = $value;
155 $this->data
= $array;
159 * Return an associative array of the stored data.
163 public function toArray()
168 /** @var self $value */
169 foreach ($data as $key => $value) {
170 if ($value instanceof self
) {
171 $array[$key] = $value->toArray();
173 $array[$key] = $value;
181 * isset() overloading
183 * @param string $name
186 public function __isset($name)
188 return isset($this->data
[$name]);
192 * unset() overloading
194 * @param string $name
196 * @throws Exception\InvalidArgumentException
198 public function __unset($name)
200 if (!$this->allowModifications
) {
201 throw new Exception\
InvalidArgumentException('Config is read only');
202 } elseif (isset($this->data
[$name])) {
203 unset($this->data
[$name]);
205 $this->skipNextIteration
= true;
210 * count(): defined by Countable interface.
212 * @see Countable::count()
215 public function count()
221 * current(): defined by Iterator interface.
223 * @see Iterator::current()
226 public function current()
228 $this->skipNextIteration
= false;
229 return current($this->data
);
233 * key(): defined by Iterator interface.
235 * @see Iterator::key()
238 public function key()
240 return key($this->data
);
244 * next(): defined by Iterator interface.
246 * @see Iterator::next()
249 public function next()
251 if ($this->skipNextIteration
) {
252 $this->skipNextIteration
= false;
260 * rewind(): defined by Iterator interface.
262 * @see Iterator::rewind()
265 public function rewind()
267 $this->skipNextIteration
= false;
272 * valid(): defined by Iterator interface.
274 * @see Iterator::valid()
277 public function valid()
279 return ($this->key() !== null);
283 * offsetExists(): defined by ArrayAccess interface.
285 * @see ArrayAccess::offsetExists()
286 * @param mixed $offset
289 public function offsetExists($offset)
291 return $this->__isset($offset);
295 * offsetGet(): defined by ArrayAccess interface.
297 * @see ArrayAccess::offsetGet()
298 * @param mixed $offset
301 public function offsetGet($offset)
303 return $this->__get($offset);
307 * offsetSet(): defined by ArrayAccess interface.
309 * @see ArrayAccess::offsetSet()
310 * @param mixed $offset
311 * @param mixed $value
314 public function offsetSet($offset, $value)
316 $this->__set($offset, $value);
320 * offsetUnset(): defined by ArrayAccess interface.
322 * @see ArrayAccess::offsetUnset()
323 * @param mixed $offset
326 public function offsetUnset($offset)
328 $this->__unset($offset);
332 * Merge another Config with this one.
334 * For duplicate keys, the following will be performed:
335 * - Nested Configs will be recursively merged.
336 * - Items in $merge with INTEGER keys will be appended.
337 * - Items in $merge with STRING keys will overwrite current values.
339 * @param Config $merge
342 public function merge(Config
$merge)
344 /** @var Config $value */
345 foreach ($merge as $key => $value) {
346 if (array_key_exists($key, $this->data
)) {
348 $this->data
[] = $value;
349 } elseif ($value instanceof self
&& $this->data
[$key] instanceof self
) {
350 $this->data
[$key]->merge($value);
352 if ($value instanceof self
) {
353 $this->data
[$key] = new static($value->toArray(), $this->allowModifications
);
355 $this->data
[$key] = $value;
359 if ($value instanceof self
) {
360 $this->data
[$key] = new static($value->toArray(), $this->allowModifications
);
362 $this->data
[$key] = $value;
373 * Prevent any more modifications being made to this instance.
375 * Useful after merge() has been used to merge multiple Config objects
376 * into one object which should then not be modified again.
380 public function setReadOnly()
382 $this->allowModifications
= false;
384 /** @var Config $value */
385 foreach ($this->data
as $value) {
386 if ($value instanceof self
) {
387 $value->setReadOnly();
393 * Returns whether this Config object is read only or not.
397 public function isReadOnly()
399 return !$this->allowModifications
;