[ZF-10089] Zend_Log
[zend/radio.git] / library / Zend / Config.php
blobc79c531bc941d3a577724a27b6b0554d3acf74e5
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
15 * @category Zend
16 * @package Zend_Config
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
19 * @version $Id$
23 /**
24 * @category Zend
25 * @package Zend_Config
26 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
27 * @license http://framework.zend.com/license/new-bsd New BSD License
29 class Zend_Config implements Countable, Iterator
31 /**
32 * Whether in-memory modifications to configuration data are allowed
34 * @var boolean
36 protected $_allowModifications;
38 /**
39 * Iteration index
41 * @var integer
43 protected $_index;
45 /**
46 * Number of elements in configuration data
48 * @var integer
50 protected $_count;
52 /**
53 * Contains array of configuration data
55 * @var array
57 protected $_data;
59 /**
60 * Used when unsetting values during iteration to ensure we do not skip
61 * the next element
63 * @var boolean
65 protected $_skipNextIteration;
67 /**
68 * Contains which config file sections were loaded. This is null
69 * if all sections were loaded, a string name if one section is loaded
70 * and an array of string names if multiple sections were loaded.
72 * @var mixed
74 protected $_loadedSection;
76 /**
77 * This is used to track section inheritance. The keys are names of sections that
78 * extend other sections, and the values are the extended sections.
80 * @var array
82 protected $_extends = array();
84 /**
85 * Load file error string.
87 * Is null if there was no error while file loading
89 * @var string
91 protected $_loadFileErrorStr = null;
93 /**
94 * Zend_Config provides a property based interface to
95 * an array. The data are read-only unless $allowModifications
96 * is set to true on construction.
98 * Zend_Config also implements Countable and Iterator to
99 * facilitate easy access to the data.
101 * @param array $array
102 * @param boolean $allowModifications
103 * @return void
105 public function __construct(array $array, $allowModifications = false)
107 $this->_allowModifications = (boolean) $allowModifications;
108 $this->_loadedSection = null;
109 $this->_index = 0;
110 $this->_data = array();
111 foreach ($array as $key => $value) {
112 if (is_array($value)) {
113 $this->_data[$key] = new self($value, $this->_allowModifications);
114 } else {
115 $this->_data[$key] = $value;
118 $this->_count = count($this->_data);
122 * Retrieve a value and return $default if there is no element set.
124 * @param string $name
125 * @param mixed $default
126 * @return mixed
128 public function get($name, $default = null)
130 $result = $default;
131 if (array_key_exists($name, $this->_data)) {
132 $result = $this->_data[$name];
134 return $result;
138 * Magic function so that $obj->value will work.
140 * @param string $name
141 * @return mixed
143 public function __get($name)
145 return $this->get($name);
149 * Only allow setting of a property if $allowModifications
150 * was set to true on construction. Otherwise, throw an exception.
152 * @param string $name
153 * @param mixed $value
154 * @throws Zend_Config_Exception
155 * @return void
157 public function __set($name, $value)
159 if ($this->_allowModifications) {
160 if (is_array($value)) {
161 $this->_data[$name] = new self($value, true);
162 } else {
163 $this->_data[$name] = $value;
165 $this->_count = count($this->_data);
166 } else {
167 /** @see Zend_Config_Exception */
168 require_once 'Zend/Config/Exception.php';
169 throw new Zend_Config_Exception('Zend_Config is read only');
174 * Deep clone of this instance to ensure that nested Zend_Configs
175 * are also cloned.
177 * @return void
179 public function __clone()
181 $array = array();
182 foreach ($this->_data as $key => $value) {
183 if ($value instanceof Zend_Config) {
184 $array[$key] = clone $value;
185 } else {
186 $array[$key] = $value;
189 $this->_data = $array;
193 * Return an associative array of the stored data.
195 * @return array
197 public function toArray()
199 $array = array();
200 $data = $this->_data;
201 foreach ($data as $key => $value) {
202 if ($value instanceof Zend_Config) {
203 $array[$key] = $value->toArray();
204 } else {
205 $array[$key] = $value;
208 return $array;
212 * Support isset() overloading on PHP 5.1
214 * @param string $name
215 * @return boolean
217 public function __isset($name)
219 return isset($this->_data[$name]);
223 * Support unset() overloading on PHP 5.1
225 * @param string $name
226 * @throws Zend_Config_Exception
227 * @return void
229 public function __unset($name)
231 if ($this->_allowModifications) {
232 unset($this->_data[$name]);
233 $this->_count = count($this->_data);
234 $this->_skipNextIteration = true;
235 } else {
236 /** @see Zend_Config_Exception */
237 require_once 'Zend/Config/Exception.php';
238 throw new Zend_Config_Exception('Zend_Config is read only');
244 * Defined by Countable interface
246 * @return int
248 public function count()
250 return $this->_count;
254 * Defined by Iterator interface
256 * @return mixed
258 public function current()
260 $this->_skipNextIteration = false;
261 return current($this->_data);
265 * Defined by Iterator interface
267 * @return mixed
269 public function key()
271 return key($this->_data);
275 * Defined by Iterator interface
278 public function next()
280 if ($this->_skipNextIteration) {
281 $this->_skipNextIteration = false;
282 return;
284 next($this->_data);
285 $this->_index++;
289 * Defined by Iterator interface
292 public function rewind()
294 $this->_skipNextIteration = false;
295 reset($this->_data);
296 $this->_index = 0;
300 * Defined by Iterator interface
302 * @return boolean
304 public function valid()
306 return $this->_index < $this->_count;
310 * Returns the section name(s) loaded.
312 * @return mixed
314 public function getSectionName()
316 if(is_array($this->_loadedSection) && count($this->_loadedSection) == 1) {
317 $this->_loadedSection = $this->_loadedSection[0];
319 return $this->_loadedSection;
323 * Returns true if all sections were loaded
325 * @return boolean
327 public function areAllSectionsLoaded()
329 return $this->_loadedSection === null;
334 * Merge another Zend_Config with this one. The items
335 * in $merge will override the same named items in
336 * the current config.
338 * @param Zend_Config $merge
339 * @return Zend_Config
341 public function merge(Zend_Config $merge)
343 foreach($merge as $key => $item) {
344 if(array_key_exists($key, $this->_data)) {
345 if($item instanceof Zend_Config && $this->$key instanceof Zend_Config) {
346 $this->$key = $this->$key->merge(new Zend_Config($item->toArray(), !$this->readOnly()));
347 } else {
348 $this->$key = $item;
350 } else {
351 if($item instanceof Zend_Config) {
352 $this->$key = new Zend_Config($item->toArray(), !$this->readOnly());
353 } else {
354 $this->$key = $item;
359 return $this;
363 * Prevent any more modifications being made to this instance. Useful
364 * after merge() has been used to merge multiple Zend_Config objects
365 * into one object which should then not be modified again.
368 public function setReadOnly()
370 $this->_allowModifications = false;
371 foreach ($this->_data as $key => $value) {
372 if ($value instanceof Zend_Config) {
373 $value->setReadOnly();
379 * Returns if this Zend_Config object is read only or not.
381 * @return boolean
383 public function readOnly()
385 return !$this->_allowModifications;
389 * Get the current extends
391 * @return array
393 public function getExtends()
395 return $this->_extends;
399 * Set an extend for Zend_Config_Writer
401 * @param string $extendingSection
402 * @param string $extendedSection
403 * @return void
405 public function setExtend($extendingSection, $extendedSection = null)
407 if ($extendedSection === null && isset($this->_extends[$extendingSection])) {
408 unset($this->_extends[$extendingSection]);
409 } else if ($extendedSection !== null) {
410 $this->_extends[$extendingSection] = $extendedSection;
415 * Throws an exception if $extendingSection may not extend $extendedSection,
416 * and tracks the section extension if it is valid.
418 * @param string $extendingSection
419 * @param string $extendedSection
420 * @throws Zend_Config_Exception
421 * @return void
423 protected function _assertValidExtend($extendingSection, $extendedSection)
425 // detect circular section inheritance
426 $extendedSectionCurrent = $extendedSection;
427 while (array_key_exists($extendedSectionCurrent, $this->_extends)) {
428 if ($this->_extends[$extendedSectionCurrent] == $extendingSection) {
429 /** @see Zend_Config_Exception */
430 require_once 'Zend/Config/Exception.php';
431 throw new Zend_Config_Exception('Illegal circular inheritance detected');
433 $extendedSectionCurrent = $this->_extends[$extendedSectionCurrent];
435 // remember that this section extends another section
436 $this->_extends[$extendingSection] = $extendedSection;
440 * Handle any errors from simplexml_load_file or parse_ini_file
442 * @param integer $errno
443 * @param string $errstr
444 * @param string $errfile
445 * @param integer $errline
447 protected function _loadFileErrorHandler($errno, $errstr, $errfile, $errline)
449 if ($this->_loadFileErrorStr === null) {
450 $this->_loadFileErrorStr = $errstr;
451 } else {
452 $this->_loadFileErrorStr .= (PHP_EOL . $errstr);
457 * Merge two arrays recursively, overwriting keys of the same name
458 * in $firstArray with the value in $secondArray.
460 * @param mixed $firstArray First array
461 * @param mixed $secondArray Second array to merge into first array
462 * @return array
464 protected function _arrayMergeRecursive($firstArray, $secondArray)
466 if (is_array($firstArray) && is_array($secondArray)) {
467 foreach ($secondArray as $key => $value) {
468 if (isset($firstArray[$key])) {
469 $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
470 } else {
471 if($key === 0) {
472 $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value));
473 } else {
474 $firstArray[$key] = $value;
478 } else {
479 $firstArray = $secondArray;
482 return $firstArray;