PageRenderTime 63ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/configure.php

https://github.com/msadouni/cakephp2x
PHP | 1241 lines | 716 code | 102 blank | 423 comment | 159 complexity | efe23ab86e96f093f53801f99cd577e2 MD5 | raw file
  1. <?php
  2. /**
  3. * Short description for file.
  4. *
  5. * Long description for file.
  6. *
  7. * PHP Version 5.x
  8. *
  9. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  10. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. *
  12. * Licensed under The MIT License
  13. * Redistributions of files must retain the above copyright notice.
  14. *
  15. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  16. * @link http://cakephp.org CakePHP(tm) Project
  17. * @package cake
  18. * @subpackage cake.cake.libs
  19. * @since CakePHP(tm) v 1.0.0.2363
  20. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  21. */
  22. /**
  23. * Include required libraries
  24. */
  25. App::import('Core', array('Set'));
  26. /**
  27. * Configuration class (singleton). Used for managing runtime configuration information.
  28. *
  29. * @package cake
  30. * @subpackage cake.cake.libs
  31. * @link http://book.cakephp.org/view/42/The-Configuration-Class
  32. */
  33. final class Configure extends Object {
  34. /**
  35. * Array of values written and read
  36. *
  37. * @var array
  38. * @access private
  39. */
  40. private static $__values = array('debug' => null);
  41. /**
  42. * Initialization of required libraries
  43. *
  44. * @return void
  45. * @access private
  46. */
  47. public static function init() {
  48. self::__loadBootstrap(true);
  49. }
  50. /**
  51. * Used to store a dynamic variable in the Configure instance.
  52. *
  53. * Usage:
  54. * {{{
  55. * Configure::write('One.key1', 'value of the Configure::One[key1]');
  56. * Configure::write(array('One.key1' => 'value of the Configure::One[key1]'));
  57. * Configure::write('One', array(
  58. * 'key1' => 'value of the Configure::One[key1]',
  59. * 'key2' => 'value of the Configure::One[key2]'
  60. * );
  61. *
  62. * Configure::write(array(
  63. * 'One.key1' => 'value of the Configure::One[key1]',
  64. * 'One.key2' => 'value of the Configure::One[key2]'
  65. * ));
  66. * }}}
  67. *
  68. * @link http://book.cakephp.org/view/412/write
  69. * @param array $config Name of var to write
  70. * @param mixed $value Value to set for var
  71. * @return void
  72. * @access public
  73. */
  74. public static function write($config, $value = null) {
  75. if (!is_array($config)) {
  76. $config = array($config => $value);
  77. }
  78. foreach ($config as $name => $value) {
  79. if (strpos($name, '.') === false) {
  80. self::$__values[$name] = $value;
  81. } else {
  82. $names = explode('.', $name, 4);
  83. switch (count($names)) {
  84. case 2:
  85. self::${$names[0]}[$names[1]] = $value;
  86. break;
  87. case 3:
  88. self::${$names[0]}[$names[1]][$names[2]] = $value;
  89. case 4:
  90. $names = explode('.', $name, 2);
  91. if (!isset(self::${$names[0]})) {
  92. self::${$names[0]} = array();
  93. }
  94. self::${$names[0]} = Set::insert(self::${$names[0]}, $names[1], $value);
  95. break;
  96. }
  97. }
  98. }
  99. if (isset($config['debug'])) {
  100. $reporting = 0;
  101. if (self::$__values['debug']) {
  102. if (!class_exists('Debugger')) {
  103. require LIBS . 'debugger.php';
  104. }
  105. $reporting = E_ALL & ~E_DEPRECATED;
  106. if (function_exists('ini_set')) {
  107. ini_set('display_errors', 1);
  108. }
  109. } elseif (function_exists('ini_set')) {
  110. ini_set('display_errors', 0);
  111. }
  112. if (isset(self::$__values['log']) && self::$__values['log']) {
  113. if (!class_exists('CakeLog')) {
  114. require LIBS . 'cake_log.php';
  115. }
  116. if (is_integer(self::$__values['log']) && !self::$__values['debug']) {
  117. $reporting = self::$__values['log'];
  118. } else {
  119. $reporting = E_ALL & ~E_DEPRECATED;
  120. }
  121. }
  122. error_reporting($reporting);
  123. }
  124. }
  125. /**
  126. * Used to read information stored in the Configure instance.
  127. *
  128. * Usage:
  129. * {{{
  130. * Configure::read('Name'); will return all values for Name
  131. * Configure::read('Name.key'); will return only the value of Configure::Name[key]
  132. * }}}
  133. *
  134. * @link http://book.cakephp.org/view/413/read
  135. * @param string $var Variable to obtain. Use '.' to access array elements.
  136. * @return string value of Configure::$var
  137. * @access public
  138. */
  139. public static function read($var = 'debug') {
  140. if (strpos($var, '.') !== false) {
  141. $names = explode('.', $var, 3);
  142. $var = $names[0];
  143. }
  144. if (!isset(self::$__values[$var])) {
  145. return null;
  146. }
  147. if (!isset($names[1])) {
  148. return self::${$var};
  149. }
  150. switch (count($names)) {
  151. case 2:
  152. if (isset(self::${$var}[$names[1]])) {
  153. return self::${$var}[$names[1]];
  154. }
  155. break;
  156. case 3:
  157. if (isset(self::${$var}[$names[1]][$names[2]])) {
  158. return self::${$var}[$names[1]][$names[2]];
  159. }
  160. if (!isset(self::${$var}[$names[1]])) {
  161. return null;
  162. }
  163. return Set::classicExtract(self::${$var}[$names[1]], $names[2]);
  164. break;
  165. }
  166. return null;
  167. }
  168. /**
  169. * Used to delete a variable from the Configure instance.
  170. *
  171. * Usage:
  172. * {{{
  173. * Configure::delete('Name'); will delete the entire Configure::Name
  174. * Configure::delete('Name.key'); will delete only the Configure::Name[key]
  175. * }}}
  176. *
  177. * @link http://book.cakephp.org/view/414/delete
  178. * @param string $var the var to be deleted
  179. * @return void
  180. * @access public
  181. */
  182. public static function delete($var = null) {
  183. if (strpos($var, '.') === false) {
  184. unset(self::$__values[$var]);
  185. return;
  186. }
  187. $names = explode('.', $var, 2);
  188. self::$__values[$names[0]] = Set::remove(self::$__values[$names[0]], $names[1]);
  189. }
  190. /**
  191. * Loads a file from app/config/configure_file.php.
  192. * Config file variables should be formated like:
  193. * `$config['name'] = 'value';`
  194. * These will be used to create dynamic Configure vars. load() is also used to
  195. * load stored config files created with Configure::store()
  196. *
  197. * - To load config files from app/config use `Configure::load('configure_file');`.
  198. * - To load config files from a plugin `Configure::load('plugin.configure_file');`.
  199. *
  200. * @link http://book.cakephp.org/view/415/load
  201. * @param string $fileName name of file to load, extension must be .php and only the name
  202. * should be used, not the extenstion
  203. * @return mixed false if file not found, void if load successful
  204. * @access public
  205. */
  206. public function load($fileName) {
  207. $found = $plugin = $pluginPath = false;
  208. list($plugin, $fileName) = pluginSplit($fileName);
  209. if ($plugin) {
  210. $pluginPath = App::pluginPath($plugin);
  211. }
  212. $pos = strpos($fileName, '..');
  213. if ($pos === false) {
  214. if ($pluginPath && file_exists($pluginPath . 'config' . DS . $fileName . '.php')) {
  215. include($pluginPath . 'config' . DS . $fileName . '.php');
  216. $found = true;
  217. } elseif (file_exists(CONFIGS . $fileName . '.php')) {
  218. include(CONFIGS . $fileName . '.php');
  219. $found = true;
  220. } elseif (file_exists(CACHE . 'persistent' . DS . $fileName . '.php')) {
  221. include(CACHE . 'persistent' . DS . $fileName . '.php');
  222. $found = true;
  223. } else {
  224. foreach (App::core('cake') as $key => $path) {
  225. if (file_exists($path . DS . 'config' . DS . $fileName . '.php')) {
  226. include($path . DS . 'config' . DS . $fileName . '.php');
  227. $found = true;
  228. break;
  229. }
  230. }
  231. }
  232. }
  233. if (!$found) {
  234. return false;
  235. }
  236. if (!isset($config)) {
  237. $error = __("Configure::load() - no variable \$config found in %s.php", true);
  238. trigger_error(sprintf($error, $fileName), E_USER_WARNING);
  239. return false;
  240. }
  241. return Configure::write($config);
  242. }
  243. /**
  244. * Used to determine the current version of CakePHP.
  245. *
  246. * Usage `Configure::version();`
  247. *
  248. * @link http://book.cakephp.org/view/416/version
  249. * @return string Current version of CakePHP
  250. * @access public
  251. */
  252. public static function version() {
  253. if (!isset(self::$__values['Cake']['version'])) {
  254. require(CORE_PATH . 'cake' . DS . 'config' . DS . 'config.php');
  255. self::write($config);
  256. }
  257. return self::$__values['Cake']['version'];
  258. }
  259. /**
  260. * Used to write a config file to disk.
  261. *
  262. * {{{
  263. * Configure::store('Model', 'class_paths', array('Users' => array(
  264. * 'path' => 'users', 'plugin' => true
  265. * )));
  266. * }}}
  267. *
  268. * @param string $type Type of config file to write, ex: Models, Controllers, Helpers, Components
  269. * @param string $name file name.
  270. * @param array $data array of values to store.
  271. * @return void
  272. * @access public
  273. */
  274. public static function store($type, $name, $data = array()) {
  275. $write = true;
  276. $content = '';
  277. foreach ($data as $key => $value) {
  278. $content .= "\$config['$type']['$key'] = " . var_export($value, true) . ";\n";
  279. }
  280. if (is_null($type)) {
  281. $write = false;
  282. }
  283. Configure::__writeConfig($content, $name, $write);
  284. }
  285. /**
  286. * Creates a cached version of a configuration file.
  287. * Appends values passed from Configure::store() to the cached file
  288. *
  289. * @param string $content Content to write on file
  290. * @param string $name Name to use for cache file
  291. * @param boolean $write true if content should be written, false otherwise
  292. * @return void
  293. * @access private
  294. */
  295. private static function __writeConfig($content, $name, $write = true) {
  296. $file = CACHE . 'persistent' . DS . $name . '.php';
  297. if (Configure::read() > 0) {
  298. $expires = "+10 seconds";
  299. } else {
  300. $expires = "+999 days";
  301. }
  302. $cache = cache('persistent' . DS . $name . '.php', null, $expires);
  303. if ($cache === null) {
  304. cache('persistent' . DS . $name . '.php', "<?php\n\$config = array();\n", $expires);
  305. }
  306. if ($write === true) {
  307. if (!class_exists('File')) {
  308. require LIBS . 'file.php';
  309. }
  310. $fileClass = new File($file);
  311. if ($fileClass->writable()) {
  312. $fileClass->append($content);
  313. }
  314. }
  315. }
  316. /**
  317. * Loads app/config/bootstrap.php.
  318. * If the alternative paths are set in this file
  319. * they will be added to the paths vars.
  320. *
  321. * @param boolean $boot Load application bootstrap (if true)
  322. * @return void
  323. * @access private
  324. */
  325. private function __loadBootstrap($boot) {
  326. $libPaths = $modelPaths = $behaviorPaths = $controllerPaths = $componentPaths = $viewPaths = $helperPaths = $pluginPaths = $vendorPaths = $localePaths = $shellPaths = null;
  327. if ($boot) {
  328. self::write('App', array('base' => false, 'baseUrl' => false, 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'www_root' => WWW_ROOT));
  329. if (!include(CONFIGS . 'core.php')) {
  330. trigger_error(sprintf(__("Can't find application core file. Please create %score.php, and make sure it is readable by PHP.", true), CONFIGS), E_USER_ERROR);
  331. }
  332. if (self::read('Cache.disable') !== true) {
  333. $cache = Cache::config('default');
  334. if (empty($cache['settings'])) {
  335. trigger_error('Cache not configured properly. Please check Cache::config(); in APP/config/core.php', E_USER_WARNING);
  336. $cache = Cache::config('default', array('engine' => 'File'));
  337. }
  338. $path = $prefix = $duration = null;
  339. if (!empty($cache['settings']['path'])) {
  340. $path = realpath($cache['settings']['path']);
  341. } else {
  342. $prefix = $cache['settings']['prefix'];
  343. }
  344. if (self::read() >= 1) {
  345. $duration = '+10 seconds';
  346. } else {
  347. $duration = '+999 days';
  348. }
  349. if (Cache::config('_cake_core_') === false) {
  350. Cache::config('_cake_core_', array_merge((array)$cache['settings'], array(
  351. 'prefix' => $prefix . 'cake_core_', 'path' => $path . DS . 'persistent' . DS,
  352. 'serialize' => true, 'duration' => $duration
  353. )));
  354. }
  355. if (Cache::config('_cake_model_') === false) {
  356. Cache::config('_cake_model_', array_merge((array)$cache['settings'], array(
  357. 'prefix' => $prefix . 'cake_model_', 'path' => $path . DS . 'models' . DS,
  358. 'serialize' => true, 'duration' => $duration
  359. )));
  360. }
  361. Cache::config('default');
  362. }
  363. if (!include(CONFIGS . 'bootstrap.php')) {
  364. trigger_error(sprintf(__("Can't find application bootstrap file. Please create %sbootstrap.php, and make sure it is readable by PHP.", true), CONFIGS), E_USER_ERROR);
  365. }
  366. if (App::path('controllers') == array()) {
  367. App::build(array(
  368. 'models' => $modelPaths, 'views' => $viewPaths, 'controllers' => $controllerPaths,
  369. 'helpers' => $helperPaths, 'components' => $componentPaths, 'behaviors' => $behaviorPaths,
  370. 'plugins' => $pluginPaths, 'vendors' => $vendorPaths, 'locales' => $localePaths,
  371. 'shells' => $shellPaths, 'libs' => $libPaths
  372. ));
  373. }
  374. }
  375. }
  376. }
  377. /**
  378. * Class and file loader.
  379. *
  380. * @link http://book.cakephp.org/view/499/The-App-Class
  381. * @since CakePHP(tm) v 1.2.0.6001
  382. * @package cake
  383. * @subpackage cake.cake.libs
  384. */
  385. class App extends Object {
  386. /**
  387. * List of object types and their properties
  388. *
  389. * @var array
  390. * @access public
  391. */
  392. private static $types = array(
  393. 'class' => array('suffix' => '.php', 'extends' => null, 'core' => true),
  394. 'file' => array('suffix' => '.php', 'extends' => null, 'core' => true),
  395. 'model' => array('suffix' => '.php', 'extends' => 'AppModel', 'core' => false),
  396. 'behavior' => array('suffix' => '.php', 'extends' => 'ModelBehavior', 'core' => true),
  397. 'controller' => array('suffix' => '_controller.php', 'extends' => 'AppController', 'core' => true),
  398. 'component' => array('suffix' => '.php', 'extends' => null, 'core' => true),
  399. 'lib' => array('suffix' => '.php', 'extends' => null, 'core' => true),
  400. 'view' => array('suffix' => '.php', 'extends' => null, 'core' => true),
  401. 'helper' => array('suffix' => '.php', 'extends' => 'AppHelper', 'core' => true),
  402. 'vendor' => array('suffix' => '', 'extends' => null, 'core' => true),
  403. 'shell' => array('suffix' => '.php', 'extends' => 'Shell', 'core' => true),
  404. 'plugin' => array('suffix' => '', 'extends' => null, 'core' => true)
  405. );
  406. /**
  407. * List of additional path(s) where model files reside.
  408. *
  409. * @var array
  410. * @access public
  411. */
  412. private static $models = array();
  413. /**
  414. * List of additional path(s) where behavior files reside.
  415. *
  416. * @var array
  417. * @access public
  418. */
  419. private static $behaviors = array();
  420. /**
  421. * List of additional path(s) where controller files reside.
  422. *
  423. * @var array
  424. * @access public
  425. */
  426. private static $controllers = array();
  427. /**
  428. * List of additional path(s) where component files reside.
  429. *
  430. * @var array
  431. * @access public
  432. */
  433. private static $components = array();
  434. /**
  435. * List of additional path(s) where datasource files reside.
  436. *
  437. * @var array
  438. * @access private
  439. */
  440. private static $datasources = array();
  441. /**
  442. * List of additional path(s) where libs files reside.
  443. *
  444. * @var array
  445. * @access public
  446. */
  447. private static $libs = array();
  448. /**
  449. * List of additional path(s) where view files reside.
  450. *
  451. * @var array
  452. * @access public
  453. */
  454. private static $views = array();
  455. /**
  456. * List of additional path(s) where helper files reside.
  457. *
  458. * @var array
  459. * @access public
  460. */
  461. private static $helpers = array();
  462. /**
  463. * List of additional path(s) where plugins reside.
  464. *
  465. * @var array
  466. * @access public
  467. */
  468. private static $plugins = array();
  469. /**
  470. * List of additional path(s) where vendor packages reside.
  471. *
  472. * @var array
  473. * @access public
  474. */
  475. private static $vendors = array();
  476. /**
  477. * List of additional path(s) where locale files reside.
  478. *
  479. * @var array
  480. * @access public
  481. */
  482. private static $locales = array();
  483. /**
  484. * List of additional path(s) where console shell files reside.
  485. *
  486. * @var array
  487. * @access public
  488. */
  489. private static $shells = array();
  490. /**
  491. * Paths to search for files.
  492. *
  493. * @var array
  494. * @access public
  495. */
  496. private static $search = array();
  497. /**
  498. * Whether or not to return the file that is loaded.
  499. *
  500. * @var boolean
  501. * @access public
  502. */
  503. private static $return = false;
  504. /**
  505. * Determines if $__maps and $__paths cache should be written.
  506. *
  507. * @var boolean
  508. * @access private
  509. */
  510. private static $__cache = false;
  511. /**
  512. * Holds key/value pairs of $type => file path.
  513. *
  514. * @var array
  515. * @access private
  516. */
  517. private static $__map = array();
  518. /**
  519. * Holds paths for deep searching of files.
  520. *
  521. * @var array
  522. * @access private
  523. */
  524. private static $__paths = array();
  525. /**
  526. * Holds loaded files.
  527. *
  528. * @var array
  529. * @access private
  530. */
  531. private static $__loaded = array();
  532. /**
  533. * Holds and key => value array of object types.
  534. *
  535. * @var array
  536. * @access private
  537. */
  538. private static $__objects = array();
  539. /**
  540. * Used to read information stored path
  541. *
  542. * Usage
  543. * App::path('models'); will return all paths for models
  544. *
  545. * @param string $type type of path
  546. * @return string array
  547. * @access public
  548. */
  549. function path($type) {
  550. if (!isset(self::${$type})) {
  551. return array();
  552. }
  553. return self::${$type};
  554. }
  555. /**
  556. * Build path references. Merges the supplied $paths
  557. * with the base paths and the default core paths.
  558. *
  559. * @param array $paths paths defines in config/bootstrap.php
  560. * @param boolean $reset true will set paths, false merges paths [default] false
  561. * @return void
  562. * @access public
  563. */
  564. public function build($paths = array(), $reset = false) {
  565. $defaults = array(
  566. 'models' => array(MODELS),
  567. 'behaviors' => array(BEHAVIORS),
  568. 'datasources' => array(MODELS . 'datasources'),
  569. 'controllers' => array(CONTROLLERS),
  570. 'components' => array(COMPONENTS),
  571. 'libs' => array(APPLIBS),
  572. 'views' => array(VIEWS),
  573. 'helpers' => array(HELPERS),
  574. 'locales' => array(APP . 'locale' . DS),
  575. 'shells' => array(APP . 'vendors' . DS . 'shells' . DS, VENDORS . 'shells' . DS),
  576. 'vendors' => array(APP . 'vendors' . DS, VENDORS),
  577. 'plugins' => array(APP . 'plugins' . DS)
  578. );
  579. if ($reset == true) {
  580. foreach ($paths as $type => $new) {
  581. self::${$type} = (array)$new;
  582. }
  583. return $paths;
  584. }
  585. $core = self::core();
  586. $app = array('models' => true, 'controllers' => true, 'helpers' => true);
  587. foreach ($defaults as $type => $default) {
  588. $merge = array();
  589. if (isset($app[$type])) {
  590. $merge = array(APP);
  591. }
  592. if (isset($core[$type])) {
  593. $merge = array_merge($merge, (array)$core[$type]);
  594. }
  595. self::${$type} = $default;
  596. if (!empty($paths[$type])) {
  597. $path = array_flip(array_flip((array_merge(
  598. self::${$type}, (array)$paths[$type], $merge
  599. ))));
  600. self::${$type} = array_values($path);
  601. } else {
  602. $path = array_flip(array_flip((array_merge(self::${$type}, $merge))));
  603. self::${$type} = array_values($path);
  604. }
  605. }
  606. }
  607. /**
  608. * Get the path that a plugin is on. Searches through the defined plugin paths.
  609. *
  610. * @param string $plugin CamelCased plugin name to find the path of.
  611. * @return string full path to the plugin.
  612. */
  613. function pluginPath($plugin) {
  614. $pluginDir = Inflector::underscore($plugin);
  615. for ($i = 0, $length = count(self::$plugins); $i < $length; $i++) {
  616. if (is_dir(self::$plugins[$i] . $pluginDir)) {
  617. return self::$plugins[$i] . $pluginDir . DS ;
  618. }
  619. }
  620. return self::$plugins[0] . $pluginDir . DS;
  621. }
  622. /**
  623. * Returns a key/value list of all paths where core libs are found.
  624. * Passing $type only returns the values for a given value of $key.
  625. *
  626. * @param string $type valid values are: 'model', 'behavior', 'controller', 'component',
  627. * 'view', 'helper', 'datasource', 'libs', and 'cake'
  628. * @return array numeric keyed array of core lib paths
  629. * @access public
  630. */
  631. function core($type = null) {
  632. $paths = Cache::read('core_paths', '_cake_core_');
  633. if (!$paths) {
  634. $paths = array();
  635. $openBasedir = ini_get('open_basedir');
  636. if ($openBasedir) {
  637. $all = explode(PATH_SEPARATOR, $openBasedir);
  638. $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
  639. } else {
  640. $all = explode(PATH_SEPARATOR, ini_get('include_path'));
  641. $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
  642. }
  643. foreach ($all as $path) {
  644. if ($path !== DS) {
  645. $path = rtrim($path, DS);
  646. }
  647. if (empty($path) || $path === '.') {
  648. continue;
  649. }
  650. $cake = $path . DS . 'cake' . DS;
  651. $libs = $cake . 'libs' . DS;
  652. if (is_dir($libs)) {
  653. $paths['cake'][] = $cake;
  654. $paths['libs'][] = $libs;
  655. $paths['models'][] = $libs . 'model' . DS;
  656. $paths['datasources'][] = $libs . 'model' . DS . 'datasources' . DS;
  657. $paths['behaviors'][] = $libs . 'model' . DS . 'behaviors' . DS;
  658. $paths['controllers'][] = $libs . 'controller' . DS;
  659. $paths['components'][] = $libs . 'controller' . DS . 'components' . DS;
  660. $paths['views'][] = $libs . 'view' . DS;
  661. $paths['helpers'][] = $libs . 'view' . DS . 'helpers' . DS;
  662. $paths['plugins'][] = $path . DS . 'plugins' . DS;
  663. $paths['vendors'][] = $path . DS . 'vendors' . DS;
  664. $paths['shells'][] = $cake . 'console' . DS . 'libs' . DS;
  665. break;
  666. }
  667. }
  668. Cache::write('core_paths', array_filter($paths), '_cake_core_');
  669. }
  670. if ($type && isset($paths[$type])) {
  671. return $paths[$type];
  672. }
  673. return $paths;
  674. }
  675. /**
  676. * Returns an index of objects of the given type, with the physical path to each object.
  677. *
  678. * @param string $type Type of object, i.e. 'model', 'controller', 'helper', or 'plugin'
  679. * @param mixed $path Optional
  680. * @return Configure instance
  681. * @access public
  682. */
  683. function objects($type, $path = null, $cache = true) {
  684. $objects = array();
  685. $extension = false;
  686. $name = $type;
  687. if ($type === 'file' && !$path) {
  688. return false;
  689. } elseif ($type === 'file') {
  690. $extension = true;
  691. $name = $type . str_replace(DS, '', $path);
  692. }
  693. if (empty(self::$__objects) && $cache === true) {
  694. self::$__objects = Cache::read('object_map', '_cake_core_');
  695. }
  696. if (empty(self::$__objects) || !isset(self::$__objects[$type]) || $cache !== true) {
  697. $types = self::$types;
  698. if (!isset($types[$type])) {
  699. return false;
  700. }
  701. $objects = array();
  702. if (empty($path)) {
  703. $path = self::${"{$type}s"};
  704. if (isset($types[$type]['core']) && $types[$type]['core'] === false) {
  705. array_pop($path);
  706. }
  707. }
  708. $items = array();
  709. foreach ((array)$path as $dir) {
  710. if ($type === 'file' || $type === 'class' || strpos($dir, $type) !== false) {
  711. $items = self::__list($dir, $types[$type]['suffix'], $extension);
  712. $objects = array_merge($items, array_diff($objects, $items));
  713. }
  714. }
  715. if ($type !== 'file') {
  716. foreach ($objects as $key => $value) {
  717. $objects[$key] = Inflector::camelize($value);
  718. }
  719. }
  720. if ($cache === true) {
  721. self::$__cache = true;
  722. }
  723. self::$__objects[$name] = $objects;
  724. }
  725. return self::$__objects[$name];
  726. }
  727. /**
  728. * Finds classes based on $name or specific file(s) to search.
  729. *
  730. * @link http://book.cakephp.org/view/529/Using-App-import
  731. * @param mixed $type The type of Class if passed as a string, or all params can be passed as
  732. * an single array to $type,
  733. * @param string $name Name of the Class or a unique name for the file
  734. * @param mixed $parent boolean true if Class Parent should be searched, accepts key => value
  735. * array('parent' => $parent ,'file' => $file, 'search' => $search, 'ext' => '$ext');
  736. * $ext allows setting the extension of the file name
  737. * based on Inflector::underscore($name) . ".$ext";
  738. * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3');
  739. * @param string $file full name of the file to search for including extension
  740. * @param boolean $return, return the loaded file, the file must have a return
  741. * statement in it to work: return $variable;
  742. * @return boolean true if Class is already in memory or if file is found and loaded, false if not
  743. * @access public
  744. */
  745. public function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) {
  746. $plugin = $directory = null;
  747. if (is_array($type)) {
  748. extract($type, EXTR_OVERWRITE);
  749. }
  750. if (is_array($parent)) {
  751. extract($parent, EXTR_OVERWRITE);
  752. }
  753. if ($name === null && $file === null) {
  754. $name = $type;
  755. $type = 'Core';
  756. } elseif ($name === null) {
  757. $type = 'File';
  758. }
  759. if (is_array($name)) {
  760. foreach ($name as $class) {
  761. $tempType = $type;
  762. $plugin = null;
  763. if (strpos($class, '.') !== false) {
  764. $value = explode('.', $class);
  765. $count = count($value);
  766. if ($count > 2) {
  767. $tempType = $value[0];
  768. $plugin = $value[1] . '.';
  769. $class = $value[2];
  770. } elseif ($count === 2 && ($type === 'Core' || $type === 'File')) {
  771. $tempType = $value[0];
  772. $class = $value[1];
  773. } else {
  774. $plugin = $value[0] . '.';
  775. $class = $value[1];
  776. }
  777. }
  778. if (!self::import($tempType, $plugin . $class, $parent)) {
  779. return false;
  780. }
  781. }
  782. return true;
  783. }
  784. if ($name != null && strpos($name, '.') !== false) {
  785. list($plugin, $name) = explode('.', $name);
  786. $plugin = Inflector::camelize($plugin);
  787. }
  788. self::$return = $return;
  789. if (isset($ext)) {
  790. $file = Inflector::underscore($name) . ".{$ext}";
  791. }
  792. $ext = self::__settings($type, $plugin, $parent);
  793. if ($name != null && !class_exists($name . $ext['class'])) {
  794. if ($load = self::__mapped($name . $ext['class'], $type, $plugin)) {
  795. if (self::__load($load)) {
  796. if (self::$return) {
  797. $value = include $load;
  798. return $value;
  799. }
  800. return true;
  801. } else {
  802. self::__remove($name . $ext['class'], $type, $plugin);
  803. self::$__cache = true;
  804. }
  805. }
  806. if (!empty($search)) {
  807. self::$search = $search;
  808. } elseif ($plugin) {
  809. self::$search = self::__paths('plugin');
  810. } else {
  811. self::$search = self::__paths($type);
  812. }
  813. $find = $file;
  814. if ($find === null) {
  815. $find = Inflector::underscore($name . $ext['suffix']).'.php';
  816. if ($plugin) {
  817. $paths = self::$search;
  818. foreach ($paths as $key => $value) {
  819. self::$search[$key] = $value . $ext['path'];
  820. }
  821. }
  822. }
  823. if (strtolower($type) !== 'vendor' && empty($search) && self::__load($file)) {
  824. $directory = false;
  825. } else {
  826. $file = $find;
  827. $directory = self::__find($find, true);
  828. }
  829. if ($directory !== null) {
  830. self::$__cache = true;
  831. self::__map($directory . $file, $name . $ext['class'], $type, $plugin);
  832. if (self::$return) {
  833. $value = include $directory . $file;
  834. return $value;
  835. }
  836. return true;
  837. }
  838. return false;
  839. }
  840. return true;
  841. }
  842. /**
  843. * Locates the $file in $__paths, searches recursively.
  844. *
  845. * @param string $file full file name
  846. * @param boolean $recursive search $__paths recursively
  847. * @return mixed boolean on fail, $file directory path on success
  848. * @access private
  849. */
  850. private static function __find($file, $recursive = true) {
  851. if (empty(self::$search)) {
  852. return null;
  853. } elseif (is_string(self::$search)) {
  854. self::$search = array(self::$search);
  855. }
  856. if (empty(self::$__paths)) {
  857. self::$__paths = Cache::read('dir_map', '_cake_core_');
  858. }
  859. foreach (self::$search as $path) {
  860. $path = rtrim($path, DS);
  861. if ($path === rtrim(APP, DS)) {
  862. $recursive = false;
  863. }
  864. if ($recursive === false) {
  865. if (self::__load($path . DS . $file)) {
  866. return $path . DS;
  867. }
  868. continue;
  869. }
  870. if (!isset(self::$__paths[$path])) {
  871. if (!class_exists('Folder')) {
  872. require LIBS . 'folder.php';
  873. }
  874. $Folder = new Folder();
  875. $directories = $Folder->tree($path, array('.svn', 'tests', 'templates'), 'dir');
  876. sort($directories);
  877. self::$__paths[$path] = $directories;
  878. }
  879. foreach (self::$__paths[$path] as $directory) {
  880. if (self::__load($directory . DS . $file)) {
  881. return $directory . DS;
  882. }
  883. }
  884. }
  885. return null;
  886. }
  887. /**
  888. * Attempts to load $file.
  889. *
  890. * @param string $file full path to file including file name
  891. * @return boolean
  892. * @access private
  893. */
  894. private static function __load($file) {
  895. if (empty($file)) {
  896. return false;
  897. }
  898. if (!self::$return && isset(self::$__loaded[$file])) {
  899. return true;
  900. }
  901. if (file_exists($file)) {
  902. if (!self::$return) {
  903. require($file);
  904. self::$__loaded[$file] = true;
  905. }
  906. return true;
  907. }
  908. return false;
  909. }
  910. /**
  911. * Maps the $name to the $file.
  912. *
  913. * @param string $file full path to file
  914. * @param string $name unique name for this map
  915. * @param string $type type object being mapped
  916. * @param string $plugin camelized if object is from a plugin, the name of the plugin
  917. * @access private
  918. */
  919. private static function __map($file, $name, $type, $plugin) {
  920. if ($plugin) {
  921. self::$__map['Plugin'][$plugin][$type][$name] = $file;
  922. } else {
  923. self::$__map[$type][$name] = $file;
  924. }
  925. }
  926. /**
  927. * Returns a file's complete path.
  928. *
  929. * @param string $name unique name
  930. * @param string $type type object
  931. * @param string $plugin camelized if object is from a plugin, the name of the plugin
  932. * @return mixed, file path if found, false otherwise
  933. * @access private
  934. */
  935. private static function __mapped($name, $type, $plugin) {
  936. if ($plugin) {
  937. if (isset(self::$__map['Plugin'][$plugin][$type]) && isset(self::$__map['Plugin'][$plugin][$type][$name])) {
  938. return self::$__map['Plugin'][$plugin][$type][$name];
  939. }
  940. return false;
  941. }
  942. if (isset(self::$__map[$type]) && isset(self::$__map[$type][$name])) {
  943. return self::$__map[$type][$name];
  944. }
  945. return false;
  946. }
  947. /**
  948. * Used to overload objects as needed.
  949. *
  950. * @param string $type Model or Helper
  951. * @param string $name Class name to overload
  952. * @access private
  953. * @todo remove
  954. */
  955. private function __overload($type, $name, $parent) {
  956. if (($type === 'Model' || $type === 'Helper') && $parent !== false) {
  957. Overloadable::overload($name);
  958. }
  959. }
  960. /**
  961. * Loads parent classes based on $type.
  962. * Returns a prefix or suffix needed for loading files.
  963. *
  964. * @param string $type type of object
  965. * @param string $plugin camelized name of plugin
  966. * @param boolean $parent false will not attempt to load parent
  967. * @return array
  968. * @access private
  969. */
  970. private static function __settings($type, $plugin, $parent) {
  971. if (!$parent) {
  972. return null;
  973. }
  974. if ($plugin) {
  975. $pluginPath = Inflector::underscore($plugin);
  976. }
  977. $path = null;
  978. $load = strtolower($type);
  979. switch ($load) {
  980. case 'model':
  981. if (!class_exists('Model')) {
  982. require LIBS . 'model' . DS . 'model.php';
  983. }
  984. if (!class_exists('AppModel')) {
  985. self::import($type, 'AppModel', false);
  986. }
  987. if ($plugin) {
  988. if (!class_exists($plugin . 'AppModel')) {
  989. self::import($type, $plugin . '.' . $plugin . 'AppModel', false, array(), $pluginPath . DS . $pluginPath . '_app_model.php');
  990. }
  991. $path = $pluginPath . DS . 'models' . DS;
  992. }
  993. return array('class' => null, 'suffix' => null, 'path' => $path);
  994. break;
  995. case 'behavior':
  996. if ($plugin) {
  997. $path = $pluginPath . DS . 'models' . DS . 'behaviors' . DS;
  998. }
  999. return array('class' => $type, 'suffix' => null, 'path' => $path);
  1000. break;
  1001. case 'controller':
  1002. self::import($type, 'AppController', false);
  1003. if ($plugin) {
  1004. self::import($type, $plugin . '.' . $plugin . 'AppController', false, array(), $pluginPath . DS . $pluginPath . '_app_controller.php');
  1005. $path = $pluginPath . DS . 'controllers' . DS;
  1006. }
  1007. return array('class' => $type, 'suffix' => $type, 'path' => $path);
  1008. break;
  1009. case 'component':
  1010. if ($plugin) {
  1011. $path = $pluginPath . DS . 'controllers' . DS . 'components' . DS;
  1012. }
  1013. return array('class' => $type, 'suffix' => null, 'path' => $path);
  1014. break;
  1015. case 'lib':
  1016. if ($plugin) {
  1017. $path = $pluginPath . DS . 'libs' . DS;
  1018. }
  1019. return array('class' => null, 'suffix' => null, 'path' => $path);
  1020. break;
  1021. case 'view':
  1022. if ($plugin) {
  1023. $path = $pluginPath . DS . 'views' . DS;
  1024. }
  1025. return array('class' => $type, 'suffix' => null, 'path' => $path);
  1026. break;
  1027. case 'helper':
  1028. if (!class_exists('AppHelper')) {
  1029. self::import($type, 'AppHelper', false);
  1030. }
  1031. if ($plugin) {
  1032. $path = $pluginPath . DS . 'views' . DS . 'helpers' . DS;
  1033. }
  1034. return array('class' => $type, 'suffix' => null, 'path' => $path);
  1035. break;
  1036. case 'vendor':
  1037. if ($plugin) {
  1038. $path = $pluginPath . DS . 'vendors' . DS;
  1039. }
  1040. return array('class' => null, 'suffix' => null, 'path' => $path);
  1041. break;
  1042. default:
  1043. $type = $suffix = $path = null;
  1044. break;
  1045. }
  1046. return array('class' => null, 'suffix' => null, 'path' => null);
  1047. }
  1048. /**
  1049. * Returns default search paths.
  1050. *
  1051. * @param string $type type of object to be searched
  1052. * @return array list of paths
  1053. * @access private
  1054. */
  1055. private static function __paths($type) {
  1056. $type = strtolower($type);
  1057. $paths = array();
  1058. if ($type === 'core') {
  1059. return self::core('libs');
  1060. }
  1061. if ($paths = App::path($type .'s')) {
  1062. return $paths;
  1063. }
  1064. return $paths;
  1065. }
  1066. /**
  1067. * Removes file location from map if the file has been deleted.
  1068. *
  1069. * @param string $name name of object
  1070. * @param string $type type of object
  1071. * @param string $plugin camelized name of plugin
  1072. * @return void
  1073. * @access private
  1074. */
  1075. private static function __remove($name, $type, $plugin) {
  1076. if ($plugin) {
  1077. unset(self::$__map['Plugin'][$plugin][$type][$name]);
  1078. } else {
  1079. unset(self::$__map[$type][$name]);
  1080. }
  1081. }
  1082. /**
  1083. * Returns an array of filenames of PHP files in the given directory.
  1084. *
  1085. * @param string $path Path to scan for files
  1086. * @param string $suffix if false, return only directories. if string, match and return files
  1087. * @return array List of directories or files in directory
  1088. */
  1089. function __list($path, $suffix = false, $extension = false) {
  1090. if (!class_exists('Folder')) {
  1091. require LIBS . 'folder.php';
  1092. }
  1093. $items = array();
  1094. $Folder =& new Folder($path);
  1095. $contents = $Folder->read(false, true);
  1096. if (is_array($contents)) {
  1097. if (!$suffix) {
  1098. return $contents[0];
  1099. } else {
  1100. foreach ($contents[1] as $item) {
  1101. if (substr($item, - strlen($suffix)) === $suffix) {
  1102. if ($extension) {
  1103. $items[] = $item;
  1104. } else {
  1105. $items[] = substr($item, 0, strlen($item) - strlen($suffix));
  1106. }
  1107. }
  1108. }
  1109. }
  1110. }
  1111. return $items;
  1112. }
  1113. /**
  1114. * Object destructor.
  1115. *
  1116. * Writes cache file if changes have been made to the $__map or $__paths
  1117. *
  1118. * @return void
  1119. * @access public
  1120. */
  1121. public static function destruct__() {
  1122. if (self::$__cache) {
  1123. $core = self::core('cake');
  1124. unset(self::$__paths[rtrim($core[0], DS)]);
  1125. Cache::write('dir_map', array_filter(self::$__paths), '_cake_core_');
  1126. Cache::write('file_map', array_filter(self::$__map), '_cake_core_');
  1127. Cache::write('object_map', self::$__objects, '_cake_core_');
  1128. }
  1129. }
  1130. }
  1131. register_shutdown_function(array('App','destruct__'));
  1132. ?>