PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/DevApp/library/Zend/Config/Xml.php

http://firephp.googlecode.com/
PHP | 230 lines | 124 code | 26 blank | 80 comment | 35 complexity | 100329add971d73339ae5ff4d8d73a84 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  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.
  14. *
  15. * @category Zend
  16. * @package Zend_Config
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Xml.php 11428 2008-09-18 16:14:39Z doctorrock83 $
  20. */
  21. /**
  22. * @see Zend_Config
  23. */
  24. require_once 'Zend/Config.php';
  25. /**
  26. * XML Adapter for Zend_Config
  27. *
  28. * @category Zend
  29. * @package Zend_Config
  30. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Config_Xml extends Zend_Config
  34. {
  35. /**
  36. * Loads the section $section from the config file $filename for
  37. * access facilitated by nested object properties.
  38. *
  39. * Sections are defined in the XML as children of the root element.
  40. *
  41. * In order to extend another section, a section defines the "extends"
  42. * attribute having a value of the section name from which the extending
  43. * section inherits values.
  44. *
  45. * Note that the keys in $section will override any keys of the same
  46. * name in the sections that have been included via "extends".
  47. *
  48. * @param string $filename File to process
  49. * @param mixed $section Section to process
  50. * @param boolean $allowModifications Wether modifiacations are allowed at runtime
  51. * @throws Zend_Config_Exception When filename is not set
  52. * @throws Zend_Config_Exception When section $sectionName cannot be found in $filename
  53. */
  54. public function __construct($filename, $section = null, $allowModifications = false)
  55. {
  56. if (empty($filename)) {
  57. require_once 'Zend/Config/Exception.php';
  58. throw new Zend_Config_Exception('Filename is not set');
  59. }
  60. set_error_handler(array($this, '_loadFileErrorHandler'));
  61. $config = simplexml_load_file($filename); // Warnings and errors are suppressed
  62. restore_error_handler();
  63. // Check if there was a error while loading file
  64. if ($this->_loadFileErrorStr !== null) {
  65. require_once 'Zend/Config/Exception.php';
  66. throw new Zend_Config_Exception($this->_loadFileErrorStr);
  67. }
  68. if ($section === null) {
  69. $dataArray = array();
  70. foreach ($config as $sectionName => $sectionData) {
  71. $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
  72. }
  73. parent::__construct($dataArray, $allowModifications);
  74. } else if (is_array($section)) {
  75. $dataArray = array();
  76. foreach ($section as $sectionName) {
  77. if (!isset($config->$sectionName)) {
  78. require_once 'Zend/Config/Exception.php';
  79. throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $filename");
  80. }
  81. $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
  82. }
  83. parent::__construct($dataArray, $allowModifications);
  84. } else {
  85. if (!isset($config->$section)) {
  86. require_once 'Zend/Config/Exception.php';
  87. throw new Zend_Config_Exception("Section '$section' cannot be found in $filename");
  88. }
  89. $dataArray = $this->_processExtends($config, $section);
  90. if (!is_array($dataArray)) {
  91. // Section in the XML file contains just one top level string
  92. $dataArray = array($section => $dataArray);
  93. }
  94. parent::__construct($dataArray, $allowModifications);
  95. }
  96. $this->_loadedSection = $section;
  97. }
  98. /**
  99. * Helper function to process each element in the section and handle
  100. * the "extends" inheritance attribute.
  101. *
  102. * @param SimpleXMLElement $element XML Element to process
  103. * @param string $section Section to process
  104. * @param array $config Configuration which was parsed yet
  105. * @throws Zend_Config_Exception When $section cannot be found
  106. * @return array
  107. */
  108. protected function _processExtends(SimpleXMLElement $element, $section, array $config = array())
  109. {
  110. if (!isset($element->$section)) {
  111. require_once 'Zend/Config/Exception.php';
  112. throw new Zend_Config_Exception("Section '$section' cannot be found");
  113. }
  114. $thisSection = $element->$section;
  115. if (isset($thisSection['extends'])) {
  116. $extendedSection = (string) $thisSection['extends'];
  117. $this->_assertValidExtend($section, $extendedSection);
  118. $config = $this->_processExtends($element, $extendedSection, $config);
  119. }
  120. $config = $this->_arrayMergeRecursive($config, $this->_toArray($thisSection));
  121. return $config;
  122. }
  123. /**
  124. * Returns a string or an associative and possibly multidimensional array from
  125. * a SimpleXMLElement.
  126. *
  127. * @param SimpleXMLElement $xmlObject Convert a SimpleXMLElement into an array
  128. * @return array|string
  129. */
  130. protected function _toArray(SimpleXMLElement $xmlObject)
  131. {
  132. $config = array();
  133. // Search for parent node values
  134. if (count($xmlObject->attributes()) > 0) {
  135. foreach ($xmlObject->attributes() as $key => $value) {
  136. if ($key === 'extends') {
  137. continue;
  138. }
  139. $value = (string) $value;
  140. if (array_key_exists($key, $config)) {
  141. if (!is_array($config[$key])) {
  142. $config[$key] = array($config[$key]);
  143. }
  144. $config[$key][] = $value;
  145. } else {
  146. $config[$key] = $value;
  147. }
  148. }
  149. }
  150. // Search for children
  151. if (count($xmlObject->children()) > 0) {
  152. foreach ($xmlObject->children() as $key => $value) {
  153. if (count($value->children()) > 0) {
  154. $value = $this->_toArray($value);
  155. } else if (count($value->attributes()) > 0) {
  156. $attributes = $value->attributes();
  157. if (isset($attributes['value'])) {
  158. $value = (string) $attributes['value'];
  159. } else {
  160. $value = $this->_toArray($value);
  161. }
  162. } else {
  163. $value = (string) $value;
  164. }
  165. if (array_key_exists($key, $config)) {
  166. if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) {
  167. $config[$key] = array($config[$key]);
  168. }
  169. $config[$key][] = $value;
  170. } else {
  171. $config[$key] = $value;
  172. }
  173. }
  174. } else if (!isset($xmlObject['extends']) && (count($config) === 0)) {
  175. // Object has no children nor attributes and doesn't use the extends
  176. // attribute: it's a string
  177. $config = (string) $xmlObject;
  178. }
  179. return $config;
  180. }
  181. /**
  182. * Merge two arrays recursively, overwriting keys of the same name
  183. * in $array1 with the value in $array2.
  184. *
  185. * @param mixed $firstArray First array
  186. * @param mixed $secondArray Second array to merge into first array
  187. * @return array
  188. */
  189. protected function _arrayMergeRecursive($firstArray, $secondArray)
  190. {
  191. if (is_array($firstArray) && is_array($secondArray)) {
  192. foreach ($secondArray as $key => $value) {
  193. if (isset($firstArray[$key])) {
  194. $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
  195. } else {
  196. $firstArray[$key] = $value;
  197. }
  198. }
  199. } else {
  200. $firstArray = $secondArray;
  201. }
  202. return $firstArray;
  203. }
  204. }