File indexing completed on 2024-12-22 05:37:15
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Config 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 0023 /** 0024 * @category Zend 0025 * @package Zend_Config 0026 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0027 * @license http://framework.zend.com/license/new-bsd New BSD License 0028 */ 0029 class Zend_Config implements Countable, Iterator 0030 { 0031 /** 0032 * Whether in-memory modifications to configuration data are allowed 0033 * 0034 * @var boolean 0035 */ 0036 protected $_allowModifications; 0037 0038 /** 0039 * Iteration index 0040 * 0041 * @var integer 0042 */ 0043 protected $_index; 0044 0045 /** 0046 * Number of elements in configuration data 0047 * 0048 * @var integer 0049 */ 0050 protected $_count; 0051 0052 /** 0053 * Contains array of configuration data 0054 * 0055 * @var array 0056 */ 0057 protected $_data; 0058 0059 /** 0060 * Used when unsetting values during iteration to ensure we do not skip 0061 * the next element 0062 * 0063 * @var boolean 0064 */ 0065 protected $_skipNextIteration; 0066 0067 /** 0068 * Contains which config file sections were loaded. This is null 0069 * if all sections were loaded, a string name if one section is loaded 0070 * and an array of string names if multiple sections were loaded. 0071 * 0072 * @var mixed 0073 */ 0074 protected $_loadedSection; 0075 0076 /** 0077 * This is used to track section inheritance. The keys are names of sections that 0078 * extend other sections, and the values are the extended sections. 0079 * 0080 * @var array 0081 */ 0082 protected $_extends = array(); 0083 0084 /** 0085 * Load file error string. 0086 * 0087 * Is null if there was no error while file loading 0088 * 0089 * @var string 0090 */ 0091 protected $_loadFileErrorStr = null; 0092 0093 /** 0094 * Zend_Config provides a property based interface to 0095 * an array. The data are read-only unless $allowModifications 0096 * is set to true on construction. 0097 * 0098 * Zend_Config also implements Countable and Iterator to 0099 * facilitate easy access to the data. 0100 * 0101 * @param array $array 0102 * @param boolean $allowModifications 0103 * @return void 0104 */ 0105 public function __construct(array $array, $allowModifications = false) 0106 { 0107 $this->_allowModifications = (boolean) $allowModifications; 0108 $this->_loadedSection = null; 0109 $this->_index = 0; 0110 $this->_data = array(); 0111 foreach ($array as $key => $value) { 0112 if (is_array($value)) { 0113 $this->_data[$key] = new self($value, $this->_allowModifications); 0114 } else { 0115 $this->_data[$key] = $value; 0116 } 0117 } 0118 $this->_count = count($this->_data); 0119 } 0120 0121 /** 0122 * Retrieve a value and return $default if there is no element set. 0123 * 0124 * @param string $name 0125 * @param mixed $default 0126 * @return mixed 0127 */ 0128 public function get($name, $default = null) 0129 { 0130 $result = $default; 0131 if (array_key_exists($name, $this->_data)) { 0132 $result = $this->_data[$name]; 0133 } 0134 return $result; 0135 } 0136 0137 /** 0138 * Magic function so that $obj->value will work. 0139 * 0140 * @param string $name 0141 * @return mixed 0142 */ 0143 public function __get($name) 0144 { 0145 return $this->get($name); 0146 } 0147 0148 /** 0149 * Only allow setting of a property if $allowModifications 0150 * was set to true on construction. Otherwise, throw an exception. 0151 * 0152 * @param string $name 0153 * @param mixed $value 0154 * @throws Zend_Config_Exception 0155 * @return void 0156 */ 0157 public function __set($name, $value) 0158 { 0159 if ($this->_allowModifications) { 0160 if (is_array($value)) { 0161 $this->_data[$name] = new self($value, true); 0162 } else { 0163 $this->_data[$name] = $value; 0164 } 0165 $this->_count = count($this->_data); 0166 } else { 0167 /** @see Zend_Config_Exception */ 0168 // require_once 'Zend/Config/Exception.php'; 0169 throw new Zend_Config_Exception('Zend_Config is read only'); 0170 } 0171 } 0172 0173 /** 0174 * Deep clone of this instance to ensure that nested Zend_Configs 0175 * are also cloned. 0176 * 0177 * @return void 0178 */ 0179 public function __clone() 0180 { 0181 $array = array(); 0182 foreach ($this->_data as $key => $value) { 0183 if ($value instanceof Zend_Config) { 0184 $array[$key] = clone $value; 0185 } else { 0186 $array[$key] = $value; 0187 } 0188 } 0189 $this->_data = $array; 0190 } 0191 0192 /** 0193 * Return an associative array of the stored data. 0194 * 0195 * @return array 0196 */ 0197 public function toArray() 0198 { 0199 $array = array(); 0200 $data = $this->_data; 0201 foreach ($data as $key => $value) { 0202 if ($value instanceof Zend_Config) { 0203 $array[$key] = $value->toArray(); 0204 } else { 0205 $array[$key] = $value; 0206 } 0207 } 0208 return $array; 0209 } 0210 0211 /** 0212 * Support isset() overloading on PHP 5.1 0213 * 0214 * @param string $name 0215 * @return boolean 0216 */ 0217 public function __isset($name) 0218 { 0219 return isset($this->_data[$name]); 0220 } 0221 0222 /** 0223 * Support unset() overloading on PHP 5.1 0224 * 0225 * @param string $name 0226 * @throws Zend_Config_Exception 0227 * @return void 0228 */ 0229 public function __unset($name) 0230 { 0231 if ($this->_allowModifications) { 0232 unset($this->_data[$name]); 0233 $this->_count = count($this->_data); 0234 $this->_skipNextIteration = true; 0235 } else { 0236 /** @see Zend_Config_Exception */ 0237 // require_once 'Zend/Config/Exception.php'; 0238 throw new Zend_Config_Exception('Zend_Config is read only'); 0239 } 0240 0241 } 0242 0243 /** 0244 * Defined by Countable interface 0245 * 0246 * @return int 0247 */ 0248 public function count() 0249 { 0250 return $this->_count; 0251 } 0252 0253 /** 0254 * Defined by Iterator interface 0255 * 0256 * @return mixed 0257 */ 0258 public function current() 0259 { 0260 $this->_skipNextIteration = false; 0261 return current($this->_data); 0262 } 0263 0264 /** 0265 * Defined by Iterator interface 0266 * 0267 * @return mixed 0268 */ 0269 public function key() 0270 { 0271 return key($this->_data); 0272 } 0273 0274 /** 0275 * Defined by Iterator interface 0276 * 0277 */ 0278 public function next() 0279 { 0280 if ($this->_skipNextIteration) { 0281 $this->_skipNextIteration = false; 0282 return; 0283 } 0284 next($this->_data); 0285 $this->_index++; 0286 } 0287 0288 /** 0289 * Defined by Iterator interface 0290 * 0291 */ 0292 public function rewind() 0293 { 0294 $this->_skipNextIteration = false; 0295 reset($this->_data); 0296 $this->_index = 0; 0297 } 0298 0299 /** 0300 * Defined by Iterator interface 0301 * 0302 * @return boolean 0303 */ 0304 public function valid() 0305 { 0306 return $this->_index < $this->_count; 0307 } 0308 0309 /** 0310 * Returns the section name(s) loaded. 0311 * 0312 * @return mixed 0313 */ 0314 public function getSectionName() 0315 { 0316 if(is_array($this->_loadedSection) && count($this->_loadedSection) == 1) { 0317 $this->_loadedSection = $this->_loadedSection[0]; 0318 } 0319 return $this->_loadedSection; 0320 } 0321 0322 /** 0323 * Returns true if all sections were loaded 0324 * 0325 * @return boolean 0326 */ 0327 public function areAllSectionsLoaded() 0328 { 0329 return $this->_loadedSection === null; 0330 } 0331 0332 0333 /** 0334 * Merge another Zend_Config with this one. The items 0335 * in $merge will override the same named items in 0336 * the current config. 0337 * 0338 * @param Zend_Config $merge 0339 * @return Zend_Config 0340 */ 0341 public function merge(Zend_Config $merge) 0342 { 0343 foreach($merge as $key => $item) { 0344 if(array_key_exists($key, $this->_data)) { 0345 if($item instanceof Zend_Config && $this->$key instanceof Zend_Config) { 0346 $this->$key = $this->$key->merge(new Zend_Config($item->toArray(), !$this->readOnly())); 0347 } else { 0348 $this->$key = $item; 0349 } 0350 } else { 0351 if($item instanceof Zend_Config) { 0352 $this->$key = new Zend_Config($item->toArray(), !$this->readOnly()); 0353 } else { 0354 $this->$key = $item; 0355 } 0356 } 0357 } 0358 0359 return $this; 0360 } 0361 0362 /** 0363 * Prevent any more modifications being made to this instance. Useful 0364 * after merge() has been used to merge multiple Zend_Config objects 0365 * into one object which should then not be modified again. 0366 * 0367 */ 0368 public function setReadOnly() 0369 { 0370 $this->_allowModifications = false; 0371 foreach ($this->_data as $key => $value) { 0372 if ($value instanceof Zend_Config) { 0373 $value->setReadOnly(); 0374 } 0375 } 0376 } 0377 0378 /** 0379 * Returns if this Zend_Config object is read only or not. 0380 * 0381 * @return boolean 0382 */ 0383 public function readOnly() 0384 { 0385 return !$this->_allowModifications; 0386 } 0387 0388 /** 0389 * Get the current extends 0390 * 0391 * @return array 0392 */ 0393 public function getExtends() 0394 { 0395 return $this->_extends; 0396 } 0397 0398 /** 0399 * Set an extend for Zend_Config_Writer 0400 * 0401 * @param string $extendingSection 0402 * @param string $extendedSection 0403 * @return void 0404 */ 0405 public function setExtend($extendingSection, $extendedSection = null) 0406 { 0407 if ($extendedSection === null && isset($this->_extends[$extendingSection])) { 0408 unset($this->_extends[$extendingSection]); 0409 } else if ($extendedSection !== null) { 0410 $this->_extends[$extendingSection] = $extendedSection; 0411 } 0412 } 0413 0414 /** 0415 * Throws an exception if $extendingSection may not extend $extendedSection, 0416 * and tracks the section extension if it is valid. 0417 * 0418 * @param string $extendingSection 0419 * @param string $extendedSection 0420 * @throws Zend_Config_Exception 0421 * @return void 0422 */ 0423 protected function _assertValidExtend($extendingSection, $extendedSection) 0424 { 0425 // detect circular section inheritance 0426 $extendedSectionCurrent = $extendedSection; 0427 while (array_key_exists($extendedSectionCurrent, $this->_extends)) { 0428 if ($this->_extends[$extendedSectionCurrent] == $extendingSection) { 0429 /** @see Zend_Config_Exception */ 0430 // require_once 'Zend/Config/Exception.php'; 0431 throw new Zend_Config_Exception('Illegal circular inheritance detected'); 0432 } 0433 $extendedSectionCurrent = $this->_extends[$extendedSectionCurrent]; 0434 } 0435 // remember that this section extends another section 0436 $this->_extends[$extendingSection] = $extendedSection; 0437 } 0438 0439 /** 0440 * Handle any errors from simplexml_load_file or parse_ini_file 0441 * 0442 * @param integer $errno 0443 * @param string $errstr 0444 * @param string $errfile 0445 * @param integer $errline 0446 */ 0447 public function _loadFileErrorHandler($errno, $errstr, $errfile, $errline) 0448 { 0449 if ($this->_loadFileErrorStr === null) { 0450 $this->_loadFileErrorStr = $errstr; 0451 } else { 0452 $this->_loadFileErrorStr .= (PHP_EOL . $errstr); 0453 } 0454 } 0455 0456 /** 0457 * Merge two arrays recursively, overwriting keys of the same name 0458 * in $firstArray with the value in $secondArray. 0459 * 0460 * @param mixed $firstArray First array 0461 * @param mixed $secondArray Second array to merge into first array 0462 * @return array 0463 */ 0464 protected function _arrayMergeRecursive($firstArray, $secondArray) 0465 { 0466 if (is_array($firstArray) && is_array($secondArray)) { 0467 foreach ($secondArray as $key => $value) { 0468 if (isset($firstArray[$key])) { 0469 $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value); 0470 } else { 0471 if($key === 0) { 0472 $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value)); 0473 } else { 0474 $firstArray[$key] = $value; 0475 } 0476 } 0477 } 0478 } else { 0479 $firstArray = $secondArray; 0480 } 0481 0482 return $firstArray; 0483 } 0484 }