PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/cake/libs/configure.php

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