|
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-2009 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Json.php 23294 2010-11-05 00:27:34Z ramon $ |
|
20 */ |
|
21 |
|
22 /** |
|
23 * @see Zend_Config |
|
24 */ |
|
25 require_once 'Zend/Config.php'; |
|
26 |
|
27 /** |
|
28 * @see Zend_Json |
|
29 */ |
|
30 require_once 'Zend/Json.php'; |
|
31 |
|
32 /** |
|
33 * JSON Adapter for Zend_Config |
|
34 * |
|
35 * @category Zend |
|
36 * @package Zend_Config |
|
37 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com) |
|
38 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
39 */ |
|
40 class Zend_Config_Json extends Zend_Config |
|
41 { |
|
42 /** |
|
43 * Name of object key indicating section current section extends |
|
44 */ |
|
45 const EXTENDS_NAME = "_extends"; |
|
46 |
|
47 /** |
|
48 * Whether or not to ignore constants in the JSON string |
|
49 * |
|
50 * Note: if you do not have constant names in quotations in your JSON |
|
51 * string, they may lead to syntax errors when parsing. |
|
52 * |
|
53 * @var bool |
|
54 */ |
|
55 protected $_ignoreConstants = false; |
|
56 |
|
57 /** |
|
58 * Whether to skip extends or not |
|
59 * |
|
60 * @var boolean |
|
61 */ |
|
62 protected $_skipExtends = false; |
|
63 |
|
64 /** |
|
65 * Loads the section $section from the config file encoded as JSON |
|
66 * |
|
67 * Sections are defined as properties of the main object |
|
68 * |
|
69 * In order to extend another section, a section defines the "_extends" |
|
70 * property having a value of the section name from which the extending |
|
71 * section inherits values. |
|
72 * |
|
73 * Note that the keys in $section will override any keys of the same |
|
74 * name in the sections that have been included via "_extends". |
|
75 * |
|
76 * @param string $json JSON file or string to process |
|
77 * @param mixed $section Section to process |
|
78 * @param boolean $options Whether modifiacations are allowed at runtime |
|
79 * @throws Zend_Config_Exception When JSON text is not set or cannot be loaded |
|
80 * @throws Zend_Config_Exception When section $sectionName cannot be found in $json |
|
81 */ |
|
82 public function __construct($json, $section = null, $options = false) |
|
83 { |
|
84 if (empty($json)) { |
|
85 require_once 'Zend/Config/Exception.php'; |
|
86 throw new Zend_Config_Exception('Filename is not set'); |
|
87 } |
|
88 |
|
89 $allowModifications = false; |
|
90 if (is_bool($options)) { |
|
91 $allowModifications = $options; |
|
92 } elseif (is_array($options)) { |
|
93 foreach ($options as $key => $value) { |
|
94 switch (strtolower($key)) { |
|
95 case 'allow_modifications': |
|
96 case 'allowmodifications': |
|
97 $allowModifications = (bool) $value; |
|
98 break; |
|
99 case 'skip_extends': |
|
100 case 'skipextends': |
|
101 $this->_skipExtends = (bool) $value; |
|
102 break; |
|
103 case 'ignore_constants': |
|
104 case 'ignoreconstants': |
|
105 $this->_ignoreConstants = (bool) $value; |
|
106 break; |
|
107 default: |
|
108 break; |
|
109 } |
|
110 } |
|
111 } |
|
112 |
|
113 set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed |
|
114 if ($json[0] != '{') { |
|
115 $json = file_get_contents($json); |
|
116 } |
|
117 restore_error_handler(); |
|
118 |
|
119 // Check if there was a error while loading file |
|
120 if ($this->_loadFileErrorStr !== null) { |
|
121 require_once 'Zend/Config/Exception.php'; |
|
122 throw new Zend_Config_Exception($this->_loadFileErrorStr); |
|
123 } |
|
124 |
|
125 // Replace constants |
|
126 if (!$this->_ignoreConstants) { |
|
127 $json = $this->_replaceConstants($json); |
|
128 } |
|
129 |
|
130 // Parse/decode |
|
131 $config = Zend_Json::decode($json); |
|
132 |
|
133 if (null === $config) { |
|
134 // decode failed |
|
135 require_once 'Zend/Config/Exception.php'; |
|
136 throw new Zend_Config_Exception("Error parsing JSON data"); |
|
137 } |
|
138 |
|
139 if ($section === null) { |
|
140 $dataArray = array(); |
|
141 foreach ($config as $sectionName => $sectionData) { |
|
142 $dataArray[$sectionName] = $this->_processExtends($config, $sectionName); |
|
143 } |
|
144 |
|
145 parent::__construct($dataArray, $allowModifications); |
|
146 } elseif (is_array($section)) { |
|
147 $dataArray = array(); |
|
148 foreach ($section as $sectionName) { |
|
149 if (!isset($config[$sectionName])) { |
|
150 require_once 'Zend/Config/Exception.php'; |
|
151 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName)); |
|
152 } |
|
153 |
|
154 $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray); |
|
155 } |
|
156 |
|
157 parent::__construct($dataArray, $allowModifications); |
|
158 } else { |
|
159 if (!isset($config[$section])) { |
|
160 require_once 'Zend/Config/Exception.php'; |
|
161 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); |
|
162 } |
|
163 |
|
164 $dataArray = $this->_processExtends($config, $section); |
|
165 if (!is_array($dataArray)) { |
|
166 // Section in the JSON data contains just one top level string |
|
167 $dataArray = array($section => $dataArray); |
|
168 } |
|
169 |
|
170 parent::__construct($dataArray, $allowModifications); |
|
171 } |
|
172 |
|
173 $this->_loadedSection = $section; |
|
174 } |
|
175 |
|
176 /** |
|
177 * Helper function to process each element in the section and handle |
|
178 * the "_extends" inheritance attribute. |
|
179 * |
|
180 * @param array $data Data array to process |
|
181 * @param string $section Section to process |
|
182 * @param array $config Configuration which was parsed yet |
|
183 * @throws Zend_Config_Exception When $section cannot be found |
|
184 * @return array |
|
185 */ |
|
186 protected function _processExtends(array $data, $section, array $config = array()) |
|
187 { |
|
188 if (!isset($data[$section])) { |
|
189 require_once 'Zend/Config/Exception.php'; |
|
190 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section)); |
|
191 } |
|
192 |
|
193 $thisSection = $data[$section]; |
|
194 |
|
195 if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) { |
|
196 if (is_array($thisSection[self::EXTENDS_NAME])) { |
|
197 require_once 'Zend/Config/Exception.php'; |
|
198 throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received'); |
|
199 } |
|
200 $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]); |
|
201 |
|
202 if (!$this->_skipExtends) { |
|
203 $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config); |
|
204 } |
|
205 unset($thisSection[self::EXTENDS_NAME]); |
|
206 } |
|
207 |
|
208 $config = $this->_arrayMergeRecursive($config, $thisSection); |
|
209 |
|
210 return $config; |
|
211 } |
|
212 |
|
213 /** |
|
214 * Replace any constants referenced in a string with their values |
|
215 * |
|
216 * @param string $value |
|
217 * @return string |
|
218 */ |
|
219 protected function _replaceConstants($value) |
|
220 { |
|
221 foreach ($this->_getConstants() as $constant) { |
|
222 if (strstr($value, $constant)) { |
|
223 $value = str_replace($constant, constant($constant), $value); |
|
224 } |
|
225 } |
|
226 return $value; |
|
227 } |
|
228 |
|
229 /** |
|
230 * Get (reverse) sorted list of defined constant names |
|
231 * |
|
232 * @return array |
|
233 */ |
|
234 protected function _getConstants() |
|
235 { |
|
236 $constants = array_keys(get_defined_constants()); |
|
237 rsort($constants, SORT_STRING); |
|
238 return $constants; |
|
239 } |
|
240 } |