1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4: * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * Redistributions of files must retain the above copyright notice.
8: *
9: * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
10: * @link http://cakephp.org CakePHP(tm) Project
11: * @package Cake.Core
12: * @since CakePHP(tm) v 1.0.0.2363
13: * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
14: */
15:
16: App::uses('Set', 'Utility');
17: App::uses('ConfigReaderInterface', 'Configure');
18:
19: /**
20: * Configuration class. Used for managing runtime configuration information.
21: *
22: * Provides features for reading and writing to the runtime configuration, as well
23: * as methods for loading additional configuration files or storing runtime configuration
24: * for future use.
25: *
26: * @package Cake.Core
27: * @link http://book.cakephp.org/2.0/en/development/configuration.html#configure-class
28: */
29: class Configure {
30:
31: /**
32: * Array of values currently stored in Configure.
33: *
34: * @var array
35: */
36: protected static $_values = array(
37: 'debug' => 0
38: );
39:
40: /**
41: * Configured reader classes, used to load config files from resources
42: *
43: * @var array
44: * @see Configure::load()
45: */
46: protected static $_readers = array();
47:
48: /**
49: * Initializes configure and runs the bootstrap process.
50: * Bootstrapping includes the following steps:
51: *
52: * - Setup App array in Configure.
53: * - Include app/Config/core.php.
54: * - Configure core cache configurations.
55: * - Load App cache files.
56: * - Include app/Config/bootstrap.php.
57: * - Setup error/exception handlers.
58: *
59: * @param boolean $boot
60: * @return void
61: */
62: public static function bootstrap($boot = true) {
63: if ($boot) {
64: self::write('App', array(
65: 'base' => false,
66: 'baseUrl' => false,
67: 'dir' => APP_DIR,
68: 'webroot' => WEBROOT_DIR,
69: 'www_root' => WWW_ROOT
70: ));
71:
72: if (!include APP . 'Config' . DS . 'core.php') {
73: trigger_error(__d('cake_dev', "Can't find application core file. Please create %score.php, and make sure it is readable by PHP.", APP . 'Config' . DS), E_USER_ERROR);
74: }
75: App::$bootstrapping = false;
76: App::init();
77: App::build();
78:
79: $exception = array(
80: 'handler' => 'ErrorHandler::handleException',
81: );
82: $error = array(
83: 'handler' => 'ErrorHandler::handleError',
84: 'level' => E_ALL & ~E_DEPRECATED,
85: );
86: self::_setErrorHandlers($error, $exception);
87:
88: if (!include APP . 'Config' . DS . 'bootstrap.php') {
89: trigger_error(__d('cake_dev', "Can't find application bootstrap file. Please create %sbootstrap.php, and make sure it is readable by PHP.", APP . 'Config' . DS), E_USER_ERROR);
90: }
91: restore_error_handler();
92:
93: self::_setErrorHandlers(
94: self::$_values['Error'],
95: self::$_values['Exception']
96: );
97: unset($error, $exception);
98: }
99: }
100:
101: /**
102: * Used to store a dynamic variable in Configure.
103: *
104: * Usage:
105: * {{{
106: * Configure::write('One.key1', 'value of the Configure::One[key1]');
107: * Configure::write(array('One.key1' => 'value of the Configure::One[key1]'));
108: * Configure::write('One', array(
109: * 'key1' => 'value of the Configure::One[key1]',
110: * 'key2' => 'value of the Configure::One[key2]'
111: * );
112: *
113: * Configure::write(array(
114: * 'One.key1' => 'value of the Configure::One[key1]',
115: * 'One.key2' => 'value of the Configure::One[key2]'
116: * ));
117: * }}}
118: *
119: * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::write
120: * @param array $config Name of var to write
121: * @param mixed $value Value to set for var
122: * @return boolean True if write was successful
123: */
124: public static function write($config, $value = null) {
125: if (!is_array($config)) {
126: $config = array($config => $value);
127: }
128:
129: foreach ($config as $name => $value) {
130: $pointer = &self::$_values;
131: foreach (explode('.', $name) as $key) {
132: $pointer = &$pointer[$key];
133: }
134: $pointer = $value;
135: unset($pointer);
136: }
137:
138: if (isset($config['debug']) && function_exists('ini_set')) {
139: if (self::$_values['debug']) {
140: ini_set('display_errors', 1);
141: } else {
142: ini_set('display_errors', 0);
143: }
144: }
145: return true;
146: }
147:
148: /**
149: * Used to read information stored in Configure. Its not
150: * possible to store `null` values in Configure.
151: *
152: * Usage:
153: * {{{
154: * Configure::read('Name'); will return all values for Name
155: * Configure::read('Name.key'); will return only the value of Configure::Name[key]
156: * }}}
157: *
158: * @linkhttp://book.cakephp.org/2.0/en/development/configuration.html#Configure::read
159: * @param string $var Variable to obtain. Use '.' to access array elements.
160: * @return mixed value stored in configure, or null.
161: */
162: public static function read($var = null) {
163: if ($var === null) {
164: return self::$_values;
165: }
166: if (isset(self::$_values[$var])) {
167: return self::$_values[$var];
168: }
169: $pointer = &self::$_values;
170: foreach (explode('.', $var) as $key) {
171: if (isset($pointer[$key])) {
172: $pointer = &$pointer[$key];
173: } else {
174: return null;
175: }
176: }
177: return $pointer;
178: }
179:
180: /**
181: * Used to delete a variable from Configure.
182: *
183: * Usage:
184: * {{{
185: * Configure::delete('Name'); will delete the entire Configure::Name
186: * Configure::delete('Name.key'); will delete only the Configure::Name[key]
187: * }}}
188: *
189: * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::delete
190: * @param string $var the var to be deleted
191: * @return void
192: */
193: public static function delete($var = null) {
194: $keys = explode('.', $var);
195: $last = array_pop($keys);
196: $pointer = &self::$_values;
197: foreach ($keys as $key) {
198: $pointer = &$pointer[$key];
199: }
200: unset($pointer[$last]);
201: }
202:
203: /**
204: * Add a new reader to Configure. Readers allow you to read configuration
205: * files in various formats/storage locations. CakePHP comes with two built-in readers
206: * PhpReader and IniReader. You can also implement your own reader classes in your application.
207: *
208: * To add a new reader to Configure:
209: *
210: * `Configure::config('ini', new IniReader());`
211: *
212: * @param string $name The name of the reader being configured. This alias is used later to
213: * read values from a specific reader.
214: * @param ConfigReaderInterface $reader The reader to append.
215: * @return void
216: */
217: public static function config($name, ConfigReaderInterface $reader) {
218: self::$_readers[$name] = $reader;
219: }
220:
221: /**
222: * Gets the names of the configured reader objects.
223: *
224: * @param string $name
225: * @return array Array of the configured reader objects.
226: */
227: public static function configured($name = null) {
228: if ($name) {
229: return isset(self::$_readers[$name]);
230: }
231: return array_keys(self::$_readers);
232: }
233:
234: /**
235: * Remove a configured reader. This will unset the reader
236: * and make any future attempts to use it cause an Exception.
237: *
238: * @param string $name Name of the reader to drop.
239: * @return boolean Success
240: */
241: public static function drop($name) {
242: if (!isset(self::$_readers[$name])) {
243: return false;
244: }
245: unset(self::$_readers[$name]);
246: return true;
247: }
248:
249: /**
250: * Loads stored configuration information from a resource. You can add
251: * config file resource readers with `Configure::config()`.
252: *
253: * Loaded configuration information will be merged with the current
254: * runtime configuration. You can load configuration files from plugins
255: * by preceding the filename with the plugin name.
256: *
257: * `Configure::load('Users.user', 'default')`
258: *
259: * Would load the 'user' config file using the default config reader. You can load
260: * app config files by giving the name of the resource you want loaded.
261: *
262: * `Configure::load('setup', 'default');`
263: *
264: * If using `default` config and no reader has been configured for it yet,
265: * one will be automatically created using PhpReader
266: *
267: * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::load
268: * @param string $key name of configuration resource to load.
269: * @param string $config Name of the configured reader to use to read the resource identified by $key.
270: * @param boolean $merge if config files should be merged instead of simply overridden
271: * @return mixed false if file not found, void if load successful.
272: * @throws ConfigureException Will throw any exceptions the reader raises.
273: */
274: public static function load($key, $config = 'default', $merge = true) {
275: if (!isset(self::$_readers[$config])) {
276: if ($config === 'default') {
277: App::uses('PhpReader', 'Configure');
278: self::$_readers[$config] = new PhpReader();
279: } else {
280: return false;
281: }
282: }
283: $values = self::$_readers[$config]->read($key);
284:
285: if ($merge) {
286: $keys = array_keys($values);
287: foreach ($keys as $key) {
288: if (($c = self::read($key)) && is_array($values[$key]) && is_array($c)) {
289: $values[$key] = Set::merge($c, $values[$key]);
290: }
291: }
292: }
293:
294: return self::write($values);
295: }
296:
297: /**
298: * Used to determine the current version of CakePHP.
299: *
300: * Usage `Configure::version();`
301: *
302: * @return string Current version of CakePHP
303: */
304: public static function version() {
305: if (!isset(self::$_values['Cake']['version'])) {
306: require CAKE . 'Config' . DS . 'config.php';
307: self::write($config);
308: }
309: return self::$_values['Cake']['version'];
310: }
311:
312: /**
313: * Used to write runtime configuration into Cache. Stored runtime configuration can be
314: * restored using `Configure::restore()`. These methods can be used to enable configuration managers
315: * frontends, or other GUI type interfaces for configuration.
316: *
317: * @param string $name The storage name for the saved configuration.
318: * @param string $cacheConfig The cache configuration to save into. Defaults to 'default'
319: * @param array $data Either an array of data to store, or leave empty to store all values.
320: * @return boolean Success
321: */
322: public static function store($name, $cacheConfig = 'default', $data = null) {
323: if ($data === null) {
324: $data = self::$_values;
325: }
326: return Cache::write($name, $data, $cacheConfig);
327: }
328:
329: /**
330: * Restores configuration data stored in the Cache into configure. Restored
331: * values will overwrite existing ones.
332: *
333: * @param string $name Name of the stored config file to load.
334: * @param string $cacheConfig Name of the Cache configuration to read from.
335: * @return boolean Success.
336: */
337: public static function restore($name, $cacheConfig = 'default') {
338: $values = Cache::read($name, $cacheConfig);
339: if ($values) {
340: return self::write($values);
341: }
342: return false;
343: }
344:
345: /**
346: * Set the error and exception handlers.
347: *
348: * @param array $error The Error handling configuration.
349: * @param array $exception The exception handling configuration.
350: * @return void
351: */
352: protected static function _setErrorHandlers($error, $exception) {
353: $level = -1;
354: if (isset($error['level'])) {
355: error_reporting($error['level']);
356: $level = $error['level'];
357: }
358: if (!empty($error['handler'])) {
359: set_error_handler($error['handler'], $level);
360: }
361: if (!empty($exception['handler'])) {
362: set_exception_handler($exception['handler']);
363: }
364: }
365: }
366: