PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/configure.php

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