PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/configure.php

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