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

/cake/libs/configure.php

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