File indexing completed on 2024-12-22 05:36:32
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-2009 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 * @see Zend_Config 0024 */ 0025 // require_once 'Zend/Config.php'; 0026 0027 /** 0028 * @see Zend_Json 0029 */ 0030 // require_once 'Zend/Json.php'; 0031 0032 /** 0033 * JSON Adapter for Zend_Config 0034 * 0035 * @category Zend 0036 * @package Zend_Config 0037 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) 0038 * @license http://framework.zend.com/license/new-bsd New BSD License 0039 */ 0040 class Zend_Config_Json extends Zend_Config 0041 { 0042 /** 0043 * Name of object key indicating section current section extends 0044 */ 0045 const EXTENDS_NAME = "_extends"; 0046 0047 /** 0048 * Whether or not to ignore constants in the JSON string 0049 * 0050 * Note: if you do not have constant names in quotations in your JSON 0051 * string, they may lead to syntax errors when parsing. 0052 * 0053 * @var bool 0054 */ 0055 protected $_ignoreConstants = false; 0056 0057 /** 0058 * Whether to skip extends or not 0059 * 0060 * @var boolean 0061 */ 0062 protected $_skipExtends = false; 0063 0064 /** 0065 * Loads the section $section from the config file encoded as JSON 0066 * 0067 * Sections are defined as properties of the main object 0068 * 0069 * In order to extend another section, a section defines the "_extends" 0070 * property having a value of the section name from which the extending 0071 * section inherits values. 0072 * 0073 * Note that the keys in $section will override any keys of the same 0074 * name in the sections that have been included via "_extends". 0075 * 0076 * @param string $json JSON file or string to process 0077 * @param mixed $section Section to process 0078 * @param boolean $options Whether modifiacations are allowed at runtime 0079 * @throws Zend_Config_Exception When JSON text is not set or cannot be loaded 0080 * @throws Zend_Config_Exception When section $sectionName cannot be found in $json 0081 */ 0082 public function __construct($json, $section = null, $options = false) 0083 { 0084 if (empty($json)) { 0085 // require_once 'Zend/Config/Exception.php'; 0086 throw new Zend_Config_Exception('Filename is not set'); 0087 } 0088 0089 $allowModifications = false; 0090 if (is_bool($options)) { 0091 $allowModifications = $options; 0092 } elseif (is_array($options)) { 0093 foreach ($options as $key => $value) { 0094 switch (strtolower($key)) { 0095 case 'allow_modifications': 0096 case 'allowmodifications': 0097 $allowModifications = (bool) $value; 0098 break; 0099 case 'skip_extends': 0100 case 'skipextends': 0101 $this->_skipExtends = (bool) $value; 0102 break; 0103 case 'ignore_constants': 0104 case 'ignoreconstants': 0105 $this->_ignoreConstants = (bool) $value; 0106 break; 0107 default: 0108 break; 0109 } 0110 } 0111 } 0112 0113 set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed 0114 if ($json[0] != '{') { 0115 $json = file_get_contents($json); 0116 } 0117 restore_error_handler(); 0118 0119 // Check if there was a error while loading file 0120 if ($this->_loadFileErrorStr !== null) { 0121 // require_once 'Zend/Config/Exception.php'; 0122 throw new Zend_Config_Exception($this->_loadFileErrorStr); 0123 } 0124 0125 // Replace constants 0126 if (!$this->_ignoreConstants) { 0127 $json = $this->_replaceConstants($json); 0128 } 0129 0130 // Parse/decode 0131 try { 0132 $config = Zend_Json::decode($json); 0133 } catch (Zend_Json_Exception $e) { 0134 // decode failed 0135 // require_once 'Zend/Config/Exception.php'; 0136 throw new Zend_Config_Exception("Error parsing JSON data"); 0137 } 0138 0139 if ($section === null) { 0140 $dataArray = array(); 0141 foreach ($config as $sectionName => $sectionData) { 0142 $dataArray[$sectionName] = $this->_processExtends($config, $sectionName); 0143 } 0144 0145 parent::__construct($dataArray, $allowModifications); 0146 } elseif (is_array($section)) { 0147 $dataArray = array(); 0148 foreach ($section as $sectionName) { 0149 if (!isset($config[$sectionName])) { 0150 // require_once 'Zend/Config/Exception.php'; 0151 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName)); 0152 } 0153 0154 $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray); 0155 } 0156 0157 parent::__construct($dataArray, $allowModifications); 0158 } else { 0159 if (!isset($config[$section])) { 0160 // require_once 'Zend/Config/Exception.php'; 0161 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); 0162 } 0163 0164 $dataArray = $this->_processExtends($config, $section); 0165 if (!is_array($dataArray)) { 0166 // Section in the JSON data contains just one top level string 0167 $dataArray = array($section => $dataArray); 0168 } 0169 0170 parent::__construct($dataArray, $allowModifications); 0171 } 0172 0173 $this->_loadedSection = $section; 0174 } 0175 0176 /** 0177 * Helper function to process each element in the section and handle 0178 * the "_extends" inheritance attribute. 0179 * 0180 * @param array $data Data array to process 0181 * @param string $section Section to process 0182 * @param array $config Configuration which was parsed yet 0183 * @throws Zend_Config_Exception When $section cannot be found 0184 * @return array 0185 */ 0186 protected function _processExtends(array $data, $section, array $config = array()) 0187 { 0188 if (!isset($data[$section])) { 0189 // require_once 'Zend/Config/Exception.php'; 0190 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); 0191 } 0192 0193 $thisSection = $data[$section]; 0194 0195 if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) { 0196 if (is_array($thisSection[self::EXTENDS_NAME])) { 0197 // require_once 'Zend/Config/Exception.php'; 0198 throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received'); 0199 } 0200 $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]); 0201 0202 if (!$this->_skipExtends) { 0203 $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config); 0204 } 0205 unset($thisSection[self::EXTENDS_NAME]); 0206 } 0207 0208 $config = $this->_arrayMergeRecursive($config, $thisSection); 0209 0210 return $config; 0211 } 0212 0213 /** 0214 * Replace any constants referenced in a string with their values 0215 * 0216 * @param string $value 0217 * @return string 0218 */ 0219 protected function _replaceConstants($value) 0220 { 0221 foreach ($this->_getConstants() as $constant) { 0222 if (strstr($value, $constant)) { 0223 // handle backslashes that may represent windows path names for instance 0224 $replacement = str_replace('\\', '\\\\', constant($constant)); 0225 $value = str_replace($constant, $replacement, $value); 0226 } 0227 } 0228 return $value; 0229 } 0230 0231 /** 0232 * Get (reverse) sorted list of defined constant names 0233 * 0234 * @return array 0235 */ 0236 protected function _getConstants() 0237 { 0238 $constants = array_keys(get_defined_constants()); 0239 rsort($constants, SORT_STRING); 0240 return $constants; 0241 } 0242 }