Configure.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 1.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Core;
  16. use Cake\Cache\Cache;
  17. use Cake\Core\Configure\ConfigEngineInterface;
  18. use Cake\Core\Configure\Engine\PhpConfig;
  19. use Cake\Core\Exception\Exception;
  20. use Cake\Utility\Hash;
  21. use RuntimeException;
  22. /**
  23. * Configuration class. Used for managing runtime configuration information.
  24. *
  25. * Provides features for reading and writing to the runtime configuration, as well
  26. * as methods for loading additional configuration files or storing runtime configuration
  27. * for future use.
  28. *
  29. * @link https://book.cakephp.org/3.0/en/development/configuration.html
  30. */
  31. class Configure
  32. {
  33. /**
  34. * Array of values currently stored in Configure.
  35. *
  36. * @var array
  37. */
  38. protected static $_values = [
  39. 'debug' => false
  40. ];
  41. /**
  42. * Configured engine classes, used to load config files from resources
  43. *
  44. * @see \Cake\Core\Configure::load()
  45. * @var \Cake\Core\Configure\ConfigEngineInterface[]
  46. */
  47. protected static $_engines = [];
  48. /**
  49. * Flag to track whether or not ini_set exists.
  50. *
  51. * @var bool|null
  52. */
  53. protected static $_hasIniSet;
  54. /**
  55. * Used to store a dynamic variable in Configure.
  56. *
  57. * Usage:
  58. * ```
  59. * Configure::write('One.key1', 'value of the Configure::One[key1]');
  60. * Configure::write(['One.key1' => 'value of the Configure::One[key1]']);
  61. * Configure::write('One', [
  62. * 'key1' => 'value of the Configure::One[key1]',
  63. * 'key2' => 'value of the Configure::One[key2]'
  64. * ]);
  65. *
  66. * Configure::write([
  67. * 'One.key1' => 'value of the Configure::One[key1]',
  68. * 'One.key2' => 'value of the Configure::One[key2]'
  69. * ]);
  70. * ```
  71. *
  72. * @param string|array $config The key to write, can be a dot notation value.
  73. * Alternatively can be an array containing key(s) and value(s).
  74. * @param mixed $value Value to set for var
  75. * @return bool True if write was successful
  76. * @link https://book.cakephp.org/3.0/en/development/configuration.html#writing-configuration-data
  77. */
  78. public static function write($config, $value = null)
  79. {
  80. if (!is_array($config)) {
  81. $config = [$config => $value];
  82. }
  83. foreach ($config as $name => $value) {
  84. static::$_values = Hash::insert(static::$_values, $name, $value);
  85. }
  86. if (isset($config['debug'])) {
  87. if (static::$_hasIniSet === null) {
  88. static::$_hasIniSet = function_exists('ini_set');
  89. }
  90. if (static::$_hasIniSet) {
  91. ini_set('display_errors', $config['debug'] ? '1' : '0');
  92. }
  93. }
  94. return true;
  95. }
  96. /**
  97. * Used to read information stored in Configure. It's not
  98. * possible to store `null` values in Configure.
  99. *
  100. * Usage:
  101. * ```
  102. * Configure::read('Name'); will return all values for Name
  103. * Configure::read('Name.key'); will return only the value of Configure::Name[key]
  104. * ```
  105. *
  106. * @param string|null $var Variable to obtain. Use '.' to access array elements.
  107. * @param mixed $default The return value when the configure does not exist
  108. * @return mixed Value stored in configure, or null.
  109. * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-configuration-data
  110. */
  111. public static function read($var = null, $default = null)
  112. {
  113. if ($var === null) {
  114. return static::$_values;
  115. }
  116. return Hash::get(static::$_values, $var, $default);
  117. }
  118. /**
  119. * Returns true if given variable is set in Configure.
  120. *
  121. * @param string $var Variable name to check for
  122. * @return bool True if variable is there
  123. */
  124. public static function check($var)
  125. {
  126. if (empty($var)) {
  127. return false;
  128. }
  129. return static::read($var) !== null;
  130. }
  131. /**
  132. * Used to get information stored in Configure. It's not
  133. * possible to store `null` values in Configure.
  134. *
  135. * Acts as a wrapper around Configure::read() and Configure::check().
  136. * The configure key/value pair fetched via this method is expected to exist.
  137. * In case it does not an exception will be thrown.
  138. *
  139. * Usage:
  140. * ```
  141. * Configure::readOrFail('Name'); will return all values for Name
  142. * Configure::readOrFail('Name.key'); will return only the value of Configure::Name[key]
  143. * ```
  144. *
  145. * @param string $var Variable to obtain. Use '.' to access array elements.
  146. * @return mixed Value stored in configure.
  147. * @throws \RuntimeException if the requested configuration is not set.
  148. * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-configuration-data
  149. */
  150. public static function readOrFail($var)
  151. {
  152. if (static::check($var) === false) {
  153. throw new RuntimeException(sprintf('Expected configuration key "%s" not found.', $var));
  154. }
  155. return static::read($var);
  156. }
  157. /**
  158. * Used to delete a variable from Configure.
  159. *
  160. * Usage:
  161. * ```
  162. * Configure::delete('Name'); will delete the entire Configure::Name
  163. * Configure::delete('Name.key'); will delete only the Configure::Name[key]
  164. * ```
  165. *
  166. * @param string $var the var to be deleted
  167. * @return void
  168. * @link https://book.cakephp.org/3.0/en/development/configuration.html#deleting-configuration-data
  169. */
  170. public static function delete($var)
  171. {
  172. static::$_values = Hash::remove(static::$_values, $var);
  173. }
  174. /**
  175. * Used to consume information stored in Configure. It's not
  176. * possible to store `null` values in Configure.
  177. *
  178. * Acts as a wrapper around Configure::consume() and Configure::check().
  179. * The configure key/value pair consumed via this method is expected to exist.
  180. * In case it does not an exception will be thrown.
  181. *
  182. * @param string $var Variable to consume. Use '.' to access array elements.
  183. * @return mixed Value stored in configure.
  184. * @throws \RuntimeException if the requested configuration is not set.
  185. * @since 3.6.0
  186. */
  187. public static function consumeOrFail($var)
  188. {
  189. if (static::check($var) === false) {
  190. throw new RuntimeException(sprintf('Expected configuration key "%s" not found.', $var));
  191. }
  192. return static::consume($var);
  193. }
  194. /**
  195. * Used to read and delete a variable from Configure.
  196. *
  197. * This is primarily used during bootstrapping to move configuration data
  198. * out of configure into the various other classes in CakePHP.
  199. *
  200. * @param string $var The key to read and remove.
  201. * @return array|string|null
  202. */
  203. public static function consume($var)
  204. {
  205. if (strpos($var, '.') === false) {
  206. if (!isset(static::$_values[$var])) {
  207. return null;
  208. }
  209. $value = static::$_values[$var];
  210. unset(static::$_values[$var]);
  211. return $value;
  212. }
  213. $value = Hash::get(static::$_values, $var);
  214. static::delete($var);
  215. return $value;
  216. }
  217. /**
  218. * Add a new engine to Configure. Engines allow you to read configuration
  219. * files in various formats/storage locations. CakePHP comes with two built-in engines
  220. * PhpConfig and IniConfig. You can also implement your own engine classes in your application.
  221. *
  222. * To add a new engine to Configure:
  223. *
  224. * ```
  225. * Configure::config('ini', new IniConfig());
  226. * ```
  227. *
  228. * @param string $name The name of the engine being configured. This alias is used later to
  229. * read values from a specific engine.
  230. * @param \Cake\Core\Configure\ConfigEngineInterface $engine The engine to append.
  231. * @return void
  232. */
  233. public static function config($name, ConfigEngineInterface $engine)
  234. {
  235. static::$_engines[$name] = $engine;
  236. }
  237. /**
  238. * Gets the names of the configured Engine objects.
  239. *
  240. * Checking if a specific engine has been configured with this method is deprecated.
  241. * Use Configure::isConfigured() instead.
  242. *
  243. * @param string|null $name Engine name.
  244. * @return string[]|bool Array of the configured Engine objects, bool for specific name.
  245. */
  246. public static function configured($name = null)
  247. {
  248. if ($name !== null) {
  249. deprecationWarning(
  250. 'Checking for a named engine with configured() is deprecated. ' .
  251. 'Use Configure::isConfigured() instead.'
  252. );
  253. return isset(static::$_engines[$name]);
  254. }
  255. return array_keys(static::$_engines);
  256. }
  257. /**
  258. * Returns true if the Engine objects is configured.
  259. *
  260. * @param string $name Engine name.
  261. * @return bool
  262. */
  263. public static function isConfigured($name)
  264. {
  265. return isset(static::$_engines[$name]);
  266. }
  267. /**
  268. * Remove a configured engine. This will unset the engine
  269. * and make any future attempts to use it cause an Exception.
  270. *
  271. * @param string $name Name of the engine to drop.
  272. * @return bool Success
  273. */
  274. public static function drop($name)
  275. {
  276. if (!isset(static::$_engines[$name])) {
  277. return false;
  278. }
  279. unset(static::$_engines[$name]);
  280. return true;
  281. }
  282. /**
  283. * Loads stored configuration information from a resource. You can add
  284. * config file resource engines with `Configure::config()`.
  285. *
  286. * Loaded configuration information will be merged with the current
  287. * runtime configuration. You can load configuration files from plugins
  288. * by preceding the filename with the plugin name.
  289. *
  290. * `Configure::load('Users.user', 'default')`
  291. *
  292. * Would load the 'user' config file using the default config engine. You can load
  293. * app config files by giving the name of the resource you want loaded.
  294. *
  295. * ```
  296. * Configure::load('setup', 'default');
  297. * ```
  298. *
  299. * If using `default` config and no engine has been configured for it yet,
  300. * one will be automatically created using PhpConfig
  301. *
  302. * @param string $key name of configuration resource to load.
  303. * @param string $config Name of the configured engine to use to read the resource identified by $key.
  304. * @param bool $merge if config files should be merged instead of simply overridden
  305. * @return bool False if file not found, true if load successful.
  306. * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-and-writing-configuration-files
  307. */
  308. public static function load($key, $config = 'default', $merge = true)
  309. {
  310. $engine = static::_getEngine($config);
  311. if (!$engine) {
  312. return false;
  313. }
  314. $values = $engine->read($key);
  315. if ($merge) {
  316. $values = Hash::merge(static::$_values, $values);
  317. }
  318. return static::write($values);
  319. }
  320. /**
  321. * Dump data currently in Configure into $key. The serialization format
  322. * is decided by the config engine attached as $config. For example, if the
  323. * 'default' adapter is a PhpConfig, the generated file will be a PHP
  324. * configuration file loadable by the PhpConfig.
  325. *
  326. * ### Usage
  327. *
  328. * Given that the 'default' engine is an instance of PhpConfig.
  329. * Save all data in Configure to the file `my_config.php`:
  330. *
  331. * ```
  332. * Configure::dump('my_config', 'default');
  333. * ```
  334. *
  335. * Save only the error handling configuration:
  336. *
  337. * ```
  338. * Configure::dump('error', 'default', ['Error', 'Exception'];
  339. * ```
  340. *
  341. * @param string $key The identifier to create in the config adapter.
  342. * This could be a filename or a cache key depending on the adapter being used.
  343. * @param string $config The name of the configured adapter to dump data with.
  344. * @param array $keys The name of the top-level keys you want to dump.
  345. * This allows you save only some data stored in Configure.
  346. * @return bool Success
  347. * @throws \Cake\Core\Exception\Exception if the adapter does not implement a `dump` method.
  348. */
  349. public static function dump($key, $config = 'default', $keys = [])
  350. {
  351. $engine = static::_getEngine($config);
  352. if (!$engine) {
  353. throw new Exception(sprintf('There is no "%s" config engine.', $config));
  354. }
  355. $values = static::$_values;
  356. if (!empty($keys) && is_array($keys)) {
  357. $values = array_intersect_key($values, array_flip($keys));
  358. }
  359. return (bool)$engine->dump($key, $values);
  360. }
  361. /**
  362. * Get the configured engine. Internally used by `Configure::load()` and `Configure::dump()`
  363. * Will create new PhpConfig for default if not configured yet.
  364. *
  365. * @param string $config The name of the configured adapter
  366. * @return \Cake\Core\Configure\ConfigEngineInterface|false Engine instance or false
  367. */
  368. protected static function _getEngine($config)
  369. {
  370. if (!isset(static::$_engines[$config])) {
  371. if ($config !== 'default') {
  372. return false;
  373. }
  374. static::config($config, new PhpConfig());
  375. }
  376. return static::$_engines[$config];
  377. }
  378. /**
  379. * Used to determine the current version of CakePHP.
  380. *
  381. * Usage
  382. * ```
  383. * Configure::version();
  384. * ```
  385. *
  386. * @return string Current version of CakePHP
  387. */
  388. public static function version()
  389. {
  390. if (!isset(static::$_values['Cake']['version'])) {
  391. $config = require CORE_PATH . 'config/config.php';
  392. static::write($config);
  393. }
  394. return static::$_values['Cake']['version'];
  395. }
  396. /**
  397. * Used to write runtime configuration into Cache. Stored runtime configuration can be
  398. * restored using `Configure::restore()`. These methods can be used to enable configuration managers
  399. * frontends, or other GUI type interfaces for configuration.
  400. *
  401. * @param string $name The storage name for the saved configuration.
  402. * @param string $cacheConfig The cache configuration to save into. Defaults to 'default'
  403. * @param array|null $data Either an array of data to store, or leave empty to store all values.
  404. * @return bool Success
  405. */
  406. public static function store($name, $cacheConfig = 'default', $data = null)
  407. {
  408. if ($data === null) {
  409. $data = static::$_values;
  410. }
  411. if (!class_exists(Cache::class)) {
  412. throw new RuntimeException('You must install cakephp/cache to use Configure::store()');
  413. }
  414. return Cache::write($name, $data, $cacheConfig);
  415. }
  416. /**
  417. * Restores configuration data stored in the Cache into configure. Restored
  418. * values will overwrite existing ones.
  419. *
  420. * @param string $name Name of the stored config file to load.
  421. * @param string $cacheConfig Name of the Cache configuration to read from.
  422. * @return bool Success.
  423. */
  424. public static function restore($name, $cacheConfig = 'default')
  425. {
  426. if (!class_exists(Cache::class)) {
  427. throw new RuntimeException('You must install cakephp/cache to use Configure::restore()');
  428. }
  429. $values = Cache::read($name, $cacheConfig);
  430. if ($values) {
  431. return static::write($values);
  432. }
  433. return false;
  434. }
  435. /**
  436. * Clear all values stored in Configure.
  437. *
  438. * @return bool success.
  439. */
  440. public static function clear()
  441. {
  442. static::$_values = [];
  443. return true;
  444. }
  445. }