configure.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: configure_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Short description for file.
00005  *
00006  * Long description for filec
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs
00023  * @since           CakePHP(tm) v 1.0.0.2363
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * Short description for file.
00031  *
00032  * Long description for file
00033  *
00034  * @package     cake
00035  * @subpackage  cake.cake.libs
00036  */
00037 class Configure extends Object {
00038 /**
00039  * Hold array with paths to model files
00040  *
00041  * @var array
00042  * @access public
00043  */
00044     var $modelPaths = array();
00045 /**
00046  * Hold array with paths to behavior files
00047  *
00048  * @var array
00049  * @access public
00050  */
00051     var $behaviorPaths = array();
00052 /**
00053  * Hold array with paths to controller files
00054  *
00055  * @var array
00056  * @access public
00057  */
00058     var $controllerPaths = array();
00059 /**
00060  * Hold array with paths to component files
00061  *
00062  * @var array
00063  * @access public
00064  */
00065     var $componentPaths = array();
00066 /**
00067  * Hold array with paths to view files
00068  *
00069  * @var array
00070  * @access public
00071  */
00072     var $viewPaths = array();
00073 /**
00074  * Hold array with paths to helper files
00075  *
00076  * @var array
00077  * @access public
00078  */
00079     var $helperPaths = array();
00080 /**
00081  * Hold array with paths to plugins
00082  *
00083  * @var array
00084  * @access public
00085  */
00086     var $pluginPaths = array();
00087 /**
00088  * Hold array with paths to vendor files
00089  *
00090  * @var array
00091  * @access public
00092  */
00093     var $vendorPaths = array();
00094 /**
00095  * Current debug level
00096  *
00097  * @var integer
00098  * @access public
00099  */
00100     var $debug = null;
00101 /**
00102  * Determine if $__objects cache should be wrote
00103  *
00104  * @var boolean
00105  * @access private
00106  */
00107     var $__cache = false;
00108 /**
00109  * Holds and key => value array of objects type
00110  *
00111  * @var array
00112  * @access private
00113  */
00114     var $__objects = array();
00115 /**
00116  * Return a singleton instance of Configure.
00117  *
00118  * @return Configure instance
00119  * @access public
00120  */
00121     function &getInstance($boot = true) {
00122         static $instance = array();
00123         if (!$instance) {
00124             $instance[0] =& new Configure();
00125             $instance[0]->__loadBootstrap($boot);
00126         }
00127         return $instance[0];
00128     }
00129 /**
00130  * Returns an index of objects of the given type, with the physical path to each object
00131  *
00132  * @param string    $type Type of object, i.e. 'model', 'controller', 'helper', or 'plugin'
00133  * @param mixed     $path Optional
00134  * @return Configure instance
00135  * @access public
00136  */
00137     function listObjects($type, $path = null, $cache = true) {
00138         $_this =& Configure::getInstance();
00139         $objects = array();
00140         $extension = false;
00141         $name = $type;
00142 
00143         if ($type === 'file' && !$path) {
00144             return false;
00145         } elseif ($type === 'file') {
00146             $extension = true;
00147             $name = $type . str_replace(DS, '', $path);
00148         }
00149 
00150         if (empty($_this->__objects) && $cache === true) {
00151             $_this->__objects = Cache::read('object_map', '_cake_core_');
00152         }
00153 
00154         if (empty($_this->__objects) || !isset($_this->__objects[$type]) || $cache !== true) {
00155             $Inflector =& Inflector::getInstance();
00156             $types = array(
00157                 'model' => array('suffix' => '.php', 'base' => 'AppModel', 'core' => false),
00158                 'behavior' => array('suffix' => '.php', 'base' => 'ModelBehavior'),
00159                 'controller' => array('suffix' => '_controller.php', 'base' => 'AppController'),
00160                 'component' => array('suffix' => '.php', 'base' => null),
00161                 'view' => array('suffix' => '.php', 'base' => null),
00162                 'helper' => array('suffix' => '.php', 'base' => 'AppHelper'),
00163                 'plugin' => array('suffix' => '', 'base' => null),
00164                 'vendor' => array('suffix' => '', 'base' => null),
00165                 'class' => array('suffix' => '.php', 'base' => null),
00166                 'file' => array('suffix' => '.php', 'base' => null)
00167             );
00168 
00169             if (!isset($types[$type])) {
00170                 return false;
00171             }
00172             $objects = array();
00173 
00174             if (empty($path)) {
00175                 $path = $_this->{$type . 'Paths'};
00176                 if (isset($types[$type]['core']) && $types[$type]['core'] === false) {
00177                     array_pop($path);
00178                 }
00179             }
00180             $items = array();
00181 
00182             foreach ((array)$path as $dir) {
00183                 if ($type === 'file' || $type === 'class' || strpos($dir, $type) !== false) {
00184                     $items = $_this->__list($dir, $types[$type]['suffix'], $extension);
00185                     $objects = array_merge($items, array_diff($objects, $items));
00186                 }
00187             }
00188 
00189             if ($type !== 'file') {
00190                 $objects = array_map(array(&$Inflector, 'camelize'), $objects);
00191             }
00192             if ($cache === true) {
00193                 $_this->__objects[$name] = $objects;
00194                 $_this->__cache = true;
00195             } else {
00196                 return $objects;
00197             }
00198         }
00199 
00200         return $_this->__objects[$name];
00201     }
00202 /**
00203  * Returns an array of filenames of PHP files in given directory.
00204  *
00205  * @param  string $path Path to scan for files
00206  * @param  string $suffix if false, return only directories. if string, match and return files
00207  * @return array  List of directories or files in directory
00208  */
00209     function __list($path, $suffix = false, $extension = false) {
00210         if (!class_exists('Folder')) {
00211             uses('folder');
00212         }
00213         $items = array();
00214         $Folder =& new Folder($path);
00215         $contents = $Folder->read(false, true);
00216 
00217         if (is_array($contents)) {
00218             if (!$suffix) {
00219                 return $contents[0];
00220             } else {
00221                 foreach($contents[1] as $item) {
00222                     if (substr($item, - strlen($suffix)) == $suffix) {
00223                         if ($extension) {
00224                             $items[] = $item;
00225                         } else {
00226                             $items[] = substr($item, 0, strlen($item) - strlen($suffix));
00227                         }
00228                     }
00229                 }
00230             }
00231         }
00232         return $items;
00233     }
00234 /**
00235  * Used to write a dynamic var in the Configure instance.
00236  *
00237  * Usage
00238  * Configure::write('One.key1', 'value of the Configure::One[key1]');
00239  * Configure::write(array('One.key1' => 'value of the Configure::One[key1]'));
00240  * Configure::write('One', array('key1'=>'value of the Configure::One[key1]', 'key2'=>'value of the Configure::One[key2]');
00241  * Configure::write(array('One.key1' => 'value of the Configure::One[key1]', 'One.key2' => 'value of the Configure::One[key2]'));
00242  *
00243  * @param array $config Name of var to write
00244  * @param mixed $value Value to set for var
00245  * @access public
00246  */
00247     function write($config, $value = null) {
00248         $_this =& Configure::getInstance();
00249 
00250         if (!is_array($config)) {
00251             $config = array($config => $value);
00252         }
00253 
00254         foreach ($config as $names => $value) {
00255             $name = $_this->__configVarNames($names);
00256 
00257             switch (count($name)) {
00258                 case 3:
00259                     $_this->{$name[0]}[$name[1]][$name[2]] = $value;
00260                 break;
00261                 case 2:
00262                     $_this->{$name[0]}[$name[1]] = $value;
00263                 break;
00264                 default:
00265                     $_this->{$name[0]} = $value;
00266                 break;
00267             }
00268         }
00269 
00270         if (array_key_exists('debug', $config)) {
00271             if ($_this->debug) {
00272                 error_reporting(E_ALL);
00273 
00274                 if (function_exists('ini_set')) {
00275                     ini_set('display_errors', 1);
00276                 }
00277 
00278                 if (!class_exists('Debugger')) {
00279                     uses('debugger');
00280                 }
00281                 if (!class_exists('CakeLog')) {
00282                     uses('cake_log');
00283                 }
00284                 Configure::write('log', LOG_NOTICE);
00285             } else {
00286                 error_reporting(0);
00287                 Configure::write('log', LOG_NOTICE);
00288             }
00289         }
00290     }
00291 /**
00292  * Used to read Configure::$var
00293  *
00294  * Usage
00295  * Configure::read('Name'); will return all values for Name
00296  * Configure::read('Name.key'); will return only the value of Configure::Name[key]
00297  *
00298  * @param string $var Variable to obtain
00299  * @return string value of Configure::$var
00300  * @access public
00301  */
00302     function read($var = 'debug') {
00303         $_this =& Configure::getInstance();
00304 
00305         if ($var === 'debug') {
00306             if (!isset($_this->debug)) {
00307                 if (defined('DEBUG')) {
00308                     $_this->debug = DEBUG;
00309                 } else {
00310                     $_this->debug = 0;
00311                 }
00312             }
00313             return $_this->debug;
00314         }
00315         $name = $_this->__configVarNames($var);
00316 
00317         switch (count($name)) {
00318             case 3:
00319                 if (isset($_this->{$name[0]}[$name[1]][$name[2]])) {
00320                     return $_this->{$name[0]}[$name[1]][$name[2]];
00321                 }
00322             break;
00323             case 2:
00324                 if (isset($_this->{$name[0]}[$name[1]])) {
00325                     return $_this->{$name[0]}[$name[1]];
00326                 }
00327             break;
00328             case 1:
00329                 if (isset($_this->{$name[0]})) {
00330                     return $_this->{$name[0]};
00331                 }
00332             break;
00333         }
00334         return null;
00335     }
00336 /**
00337  * Used to delete a var from the Configure instance.
00338  *
00339  * Usage:
00340  * Configure::delete('Name'); will delete the entire Configure::Name
00341  * Configure::delete('Name.key'); will delete only the Configure::Name[key]
00342  *
00343  * @param string $var the var to be deleted
00344  * @access public
00345  */
00346     function delete($var = null) {
00347         $_this =& Configure::getInstance();
00348         $name = $_this->__configVarNames($var);
00349 
00350         if (count($name) > 1) {
00351             unset($_this->{$name[0]}[$name[1]]);
00352         } else {
00353             unset($_this->{$name[0]});
00354         }
00355     }
00356 /**
00357  * Will load a file from app/config/configure_file.php
00358  * variables in the files should be formated like:
00359  *  $config['name'] = 'value';
00360  * These will be used to create dynamic Configure vars.
00361  *
00362  * Usage Configure::load('configure_file');
00363  *
00364  * @param string $fileName name of file to load, extension must be .php and only the name should be used, not the extenstion
00365  * @access public
00366  */
00367     function load($fileName) {
00368         $found = false;
00369         $_this =& Configure::getInstance();
00370 
00371         if (file_exists(CONFIGS . $fileName . '.php')) {
00372             include(CONFIGS . $fileName . '.php');
00373             $found = true;
00374         } elseif (file_exists(CACHE . 'persistent' . DS . $fileName . '.php')) {
00375             include(CACHE . 'persistent' . DS . $fileName . '.php');
00376             $found = true;
00377         } else {
00378             foreach ($_this->corePaths('cake') as $key => $path) {
00379                 if (file_exists($path . DS . 'config' . DS . $fileName . '.php')) {
00380                     include($path . DS . 'config' . DS . $fileName . '.php');
00381                     $found = true;
00382                     break;
00383                 }
00384             }
00385         }
00386 
00387         if (!$found) {
00388             return false;
00389         }
00390 
00391         if (!isset($config)) {
00392             trigger_error(sprintf(__("Configure::load() - no variable \$config found in %s.php", true), $fileName), E_USER_WARNING);
00393             return false;
00394         }
00395         return $_this->write($config);
00396     }
00397 /**
00398  * Used to determine the current version of CakePHP
00399  *
00400  * Usage Configure::version();
00401  *
00402  * @return string Current version of CakePHP
00403  * @access public
00404  */
00405     function version() {
00406         $_this =& Configure::getInstance();
00407 
00408         if (!isset($_this->Cake['version'])) {
00409             require(CORE_PATH . 'cake' . DS . 'config' . DS . 'config.php');
00410             $_this->write($config);
00411         }
00412         return $_this->Cake['version'];
00413     }
00414 /**
00415  * Used to write a config file to the server.
00416  *
00417  * Configure::store('Model', 'class.paths', array('Users' => array('path' => 'users', 'plugin' => true)));
00418  *
00419  * @param string $type Type of config file to write, ex: Models, Controllers, Helpers, Components
00420  * @param string $name file name.
00421  * @param array $data array of values to store.
00422  * @access public
00423  */
00424     function store($type, $name, $data = array()) {
00425         $_this =& Configure::getInstance();
00426         $write = true;
00427         $content = '';
00428 
00429         foreach ($data as $key => $value) {
00430             $content .= "\$config['$type']['$key']";
00431 
00432             if (is_array($value)) {
00433                 $content .= " = array(";
00434 
00435                 foreach ($value as $key1 => $value2) {
00436                     $value2 = addslashes($value2);
00437                     $content .= "'$key1' => '$value2', ";
00438                 }
00439                 $content .= ");\n";
00440             } else {
00441                 $value = addslashes($value);
00442                 $content .= " = '$value';\n";
00443             }
00444         }
00445         if (is_null($type)) {
00446             $write = false;
00447         }
00448         $_this->__writeConfig($content, $name, $write);
00449     }
00450 /**
00451  * Returns key => value list of all paths where core libs are found
00452  * passing $type will only return the values for $key.
00453  *
00454  * @param string $type valid values are: 'model', 'behavior', 'controller', 'component', 'view', 'helper', 'libs', and 'cake'
00455  * @return array numeric keyed array of core lib paths
00456  * @access public
00457  */
00458     function corePaths($type = null) {
00459         $paths = Cache::read('core_paths', '_cake_core_');
00460         if (!$paths) {
00461             $used = array();
00462             $vendor = false;
00463             $openBasedir = ini_get('open_basedir');
00464 
00465             if ($openBasedir) {
00466                 $all = explode(PATH_SEPARATOR, $openBasedir);
00467                 $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
00468             } else {
00469                 $all = explode(PATH_SEPARATOR, ini_get('include_path'));
00470                 $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all))));
00471             }
00472             $all = array_values($all);
00473 
00474             foreach ($all as $path) {
00475                 $path = rtrim($path, DS);
00476                 if (empty($path) || $path == '.' || in_array(realpath($path), $used)) {
00477                     continue;
00478                 }
00479                 if (is_dir($path .  DS . 'cake' . DS . 'libs')) {
00480                     $paths['libs'][] = $path .  DS . 'cake' . DS . 'libs' . DS;
00481                 }
00482                 if (is_dir($path .  DS . 'cake' . DS . 'libs' . DS . 'model')) {
00483                     $paths['model'][] = $path .  DS . 'cake' . DS . 'libs' . DS . 'model' . DS;
00484                 }
00485                 if (is_dir($path . DS . 'cake' . DS . 'libs' . DS . 'model' . DS . 'behaviors')) {
00486                     $paths['behavior'][] = $path . DS . 'cake' . DS . 'libs' . DS . 'model' . DS . 'behaviors' . DS;
00487                 }
00488                 if (is_dir($path . DS . 'cake' . DS . 'libs' . DS . 'controller')) {
00489                     $paths['controller'][] = $path . DS . 'cake' . DS . 'libs' . DS . 'controller' . DS;
00490                 }
00491                 if (is_dir($path . DS . 'cake' . DS . 'libs' . DS . 'controller' . DS . 'components')) {
00492                     $paths['component'][] = $path . DS . 'cake' . DS . 'libs' . DS . 'controller' . DS . 'components' . DS;
00493                 }
00494                 if (is_dir($path . DS . 'cake' . DS . 'libs' . DS . 'view')) {
00495                     $paths['view'][] = $path . DS . 'cake' . DS . 'libs' . DS . 'view' . DS;
00496                 }
00497                 if (is_dir($path . DS . 'cake' . DS . 'libs' . DS . 'view' . DS . 'helpers')) {
00498                     $paths['helper'][] = $path . DS . 'cake' . DS . 'libs' . DS . 'view' . DS . 'helpers' . DS;
00499                 }
00500                 if (is_dir($path .  DS . 'cake')) {
00501                     $paths['cake'][] = $path .  DS . 'cake' . DS;
00502                     $paths['class'][] = $path .  DS . 'cake' . DS;
00503                 }
00504                 if (is_dir($path .  DS . 'vendors')) {
00505                     $vendor['vendor'][] = $path .  DS . 'vendors' . DS;
00506                 }
00507                 $used[] = $path;
00508             }
00509 
00510             if ($vendor) {
00511                 $paths = array_merge($paths, $vendor);
00512             }
00513             Cache::write('core_paths', array_filter($paths), '_cake_core_');
00514         }
00515         if ($type && isset($paths[$type])) {
00516             return $paths[$type];
00517         }
00518         return $paths;
00519     }
00520 /**
00521  * Creates a cached version of a configuration file.
00522  * Appends values passed from Configure::store() to the cached file
00523  *
00524  * @param string $content Content to write on file
00525  * @param string $name Name to use for cache file
00526  * @param boolean $write true if content should be written, false otherwise
00527  * @access private
00528  */
00529     function __writeConfig($content, $name, $write = true) {
00530         $file = CACHE . 'persistent' . DS . $name . '.php';
00531         $_this =& Configure::getInstance();
00532 
00533         if ($_this->read() > 0) {
00534             $expires = "+10 seconds";
00535         } else {
00536             $expires = "+999 days";
00537         }
00538         $cache = cache('persistent' . DS . $name . '.php', null, $expires);
00539 
00540         if ($cache === null) {
00541             cache('persistent' . DS . $name . '.php', "<?php\n\$config = array();\n", $expires);
00542         }
00543 
00544         if ($write === true) {
00545             if (!class_exists('File')) {
00546                 uses('file');
00547             }
00548             $fileClass = new File($file);
00549 
00550             if ($fileClass->writable()) {
00551                 $fileClass->append($content);
00552             }
00553         }
00554     }
00555 /**
00556  * Checks $name for dot notation to create dynamic Configure::$var as an array when needed.
00557  *
00558  * @param mixed $name Name to split
00559  * @return array Name separated in items through dot notation
00560  * @access private
00561  */
00562     function __configVarNames($name) {
00563         if (is_string($name)) {
00564             if (strpos($name, ".")) {
00565                 return explode(".", $name);
00566             }
00567             return array($name);
00568         }
00569         return $name;
00570     }
00571 /**
00572  * Sets the paths for the given object type
00573  *
00574  * @param array $paths paths defines in config/bootstrap.php
00575  * @access private
00576  */
00577     function buildPaths($paths) {
00578         $_this =& Configure::getInstance();
00579         $core = $_this->corePaths();
00580         $basePaths = array(
00581             'model' => array(MODELS),
00582             'behavior' => array(BEHAVIORS),
00583             'controller' => array(CONTROLLERS),
00584             'component' => array(COMPONENTS),
00585             'view' => array(VIEWS),
00586             'helper' => array(HELPERS),
00587             'plugin' => array(APP . 'plugins' . DS),
00588             'vendor' => array(APP . 'vendors' . DS, VENDORS),
00589         );
00590 
00591         foreach ($basePaths as $type => $default) {
00592             $pathsVar = $type . 'Paths';
00593             $merge = array();
00594 
00595             if (isset($core[$type])) {
00596                 $merge = $core[$type];
00597             }
00598             if ($type === 'model' || $type === 'controller' || $type === 'helper') {
00599                 $merge = array_merge(array(APP), $merge);
00600             }
00601 
00602             if (!is_array($default)) {
00603                 $default = array($default);
00604             }
00605             $_this->{$pathsVar} = $default;
00606 
00607             if (isset($paths[$pathsVar]) && !empty($paths[$pathsVar])) {
00608                 $path = array_flip(array_flip((array_merge($_this->{$pathsVar}, (array)$paths[$pathsVar], $merge))));
00609                 $_this->{$pathsVar} = array_values($path);
00610             } else {
00611                 $path = array_flip(array_flip((array_merge($_this->{$pathsVar}, $merge))));
00612                 $_this->{$pathsVar} = array_values($path);
00613             }
00614         }
00615     }
00616 /**
00617  * Loads the app/config/bootstrap.php
00618  * If the alternative paths are set in this file
00619  * they will be added to the paths vars
00620  *
00621  * @param boolean $boot Load application bootstrap (if true)
00622  * @access private
00623  */
00624     function __loadBootstrap($boot) {
00625         $_this =& Configure::getInstance(false);
00626         $modelPaths = $behaviorPaths = $controllerPaths = $componentPaths = $viewPaths = $helperPaths = $pluginPaths = $vendorPaths = null;
00627 
00628         if ($boot) {
00629             $_this->write('App', array('base' => false, 'baseUrl' => false, 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR));
00630 
00631             if (php_sapi_name() == 'isapi') {
00632                 $_this->write('App.server', 'IIS');
00633             }
00634 
00635             if (!include(CONFIGS . 'core.php')) {
00636                 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);
00637             }
00638 
00639             if (!include(CONFIGS . 'bootstrap.php')) {
00640                 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);
00641             }
00642 
00643             if ($_this->read('Cache.disable') !== true) {
00644                 $cache = Cache::config('default');
00645 
00646                 if (empty($cache['settings'])) {
00647                     trigger_error('Cache not configured properly. Please check Cache::config(); in APP/config/core.php', E_USER_WARNING);
00648                     $cache = Cache::config('default', array('engine' => 'File'));
00649                 }
00650 
00651                 $path = $prefix = null;
00652                 if (!empty($cache['settings']['path'])) {
00653                     $path = realpath($cache['settings']['path']);
00654                 } else {
00655                     $prefix = $cache['settings']['prefix'];
00656                 }
00657 
00658                 $duration = $cache['settings']['duration'];
00659                 if (Configure::read() > 1) {
00660                     $duration = 10;
00661                 }
00662 
00663                 if (Cache::config('_cake_core_') === false) {
00664                     Cache::config('_cake_core_', array_merge($cache['settings'], array(
00665                         'prefix' => $prefix . 'cake_core_', 'path' => $path . DS . 'persistent' . DS,
00666                         'serialize' => true, 'duration' => $duration
00667                         )
00668                     ));
00669                 }
00670 
00671                 if (Cache::config('_cake_model_') === false) {
00672                     Cache::config('_cake_model_', array_merge($cache['settings'], array(
00673                         'prefix' => $prefix . 'cake_model_', 'path' => $path . DS . 'models' . DS,
00674                         'serialize' => true, 'duration' => $duration
00675                         )
00676                     ));
00677                 }
00678 
00679                 Cache::config('default');
00680             }
00681 
00682             $_this->buildPaths(compact('modelPaths', 'viewPaths', 'controllerPaths', 'helperPaths', 'componentPaths', 'behaviorPaths', 'pluginPaths', 'vendorPaths'));
00683         }
00684     }
00685 /**
00686  * Caches the object map when the instance of the Configure class is destroyed
00687  *
00688  * @access public
00689  */
00690     function __destruct() {
00691         $_this = & Configure::getInstance();
00692 
00693         if ($_this->__cache) {
00694             Cache::write('object_map', array_filter($_this->__objects), '_cake_core_');
00695         }
00696     }
00697 }
00698 /**
00699  * Class and file loader.
00700  *
00701  * @since       CakePHP(tm) v 1.2.0.6001
00702  * @package     cake
00703  * @subpackage  cake.cake.libs
00704  */
00705 class App extends Object {
00706 /**
00707  * Paths to search for files
00708  *
00709  * @var array
00710  * @access public
00711  */
00712     var $search = array();
00713 /**
00714  * Return the file that is loaded
00715  *
00716  * @var array
00717  * @access public
00718  */
00719     var $return = false;
00720 /**
00721  * Determine if $__maps and $__paths cache should be wrote
00722  *
00723  * @var boolean
00724  * @access private
00725  */
00726     var $__cache = false;
00727 /**
00728  * Holds key => values  pairs of $type => file path
00729  *
00730  * @var array
00731  * @access private
00732  */
00733     var $__map = array();
00734 /**
00735  * Holds paths for deep searching of files
00736  *
00737  * @var array
00738  * @access private
00739  */
00740     var $__paths = array();
00741 /**
00742  * Holds loaded files
00743  *
00744  * @var array
00745  * @access private
00746  */
00747     var $__loaded = array();
00748 /**
00749  * Will find Classes based on the $name, or can accept specific file to search for
00750  *
00751  * @param mixed $type The type of Class if passed as a string, or all params can be passed as an single array to $type,
00752  * @param string $name Name of the Class or a unique name for the file
00753  * @param mixed $parent boolean true if Class Parent should be searched, accepts key => value array('parent' => $parent ,'file' => $file, 'search' => $search, 'ext' => '$ext');
00754  *  $ext allows setting the extension of the file name based on Inflector::underscore($name) . ".$ext";
00755  * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3');
00756  * @param string $file full name of the file to search for including extension
00757  * @param boolean $return, return the loaded file, the file must have a return statement in it to work: return $variable;
00758  * @return boolean true if Class is already in memory or if file is found and loaded, false if not
00759  * @access public
00760  */
00761     function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) {
00762         $plugin = null;
00763         $directory = null;
00764 
00765         if (is_array($type)) {
00766             extract($type, EXTR_OVERWRITE);
00767         }
00768 
00769         if (is_array($parent)) {
00770             extract($parent, EXTR_OVERWRITE);
00771         }
00772 
00773         if ($name === null && $file === null) {
00774             $name = $type;
00775             $type = 'Core';
00776         } elseif ($name === null) {
00777             $type = 'File';
00778         }
00779         $_this =& App::getInstance();
00780 
00781         if (is_array($name)) {
00782             foreach ($name as $class) {
00783                 $tempType = $type;
00784                 $plugin = null;
00785 
00786                 if (strpos($class, '.') !== false) {
00787                     $value = explode('.', $class);
00788                     $count = count($value);
00789 
00790                     if ($count > 2) {
00791                         $tempType = $value[0];
00792                         $plugin = $value[1] . '.';
00793                         $class = $value[2];
00794                     } elseif ($count === 2 && ($type === 'Core' || $type === 'File')) {
00795                         $tempType = $value[0];
00796                         $class = $value[1];
00797                     } else {
00798                         $plugin = $value[0] . '.';
00799                         $class = $value[1];
00800                     }
00801                 }
00802                 if (!$_this->import($tempType, $plugin . $class)) {
00803                     //trigger_error(sprintf(__('%1$s type with name %2$s was not found', true), $tempType, $class, E_USER_WARNING));
00804                     return false;
00805                 }
00806             }
00807             return true;
00808         }
00809 
00810         if ($name != null && strpos($name, '.') !== false) {
00811             list($plugin, $name) = explode('.', $name);
00812         }
00813         $_this =& App::getInstance();
00814         $_this->return = $return;
00815 
00816         if (isset($ext)) {
00817             $file = Inflector::underscore($name) . ".$ext";
00818         }
00819         $ext = $_this->__settings($type, $plugin, $parent);
00820 
00821         if ($name != null && !class_exists($name . $ext['class'])) {
00822             if ($load = $_this->__mapped($name . $ext['class'], $type, $plugin)) {
00823                 if ($_this->__load($load)) {
00824                     $_this->__overload($type, $name . $ext['class']);
00825 
00826                     if ($_this->return) {
00827                         $value = include $load;
00828                         return $value;
00829                     }
00830                     return true;
00831                 } else {
00832                     $_this->__remove($name . $ext['class'], $type, $plugin);
00833                     $_this->__cache = true;
00834                 }
00835             }
00836             if (!empty($search)) {
00837                 $_this->search = $search;
00838             } elseif ($plugin) {
00839                 $_this->search = $_this->__paths('plugin');
00840             } else {
00841                 $_this->search = $_this->__paths($type);
00842             }
00843             $find = $file;
00844 
00845             if ($find === null) {
00846                 $find = Inflector::underscore($name . $ext['suffix']).'.php';
00847 
00848                 if ($plugin) {
00849                     $paths = $_this->search;
00850                     foreach ($paths as $key => $value) {
00851                         $_this->search[$key] = $value . $ext['path'];
00852                     }
00853                     $plugin = Inflector::camelize($plugin);
00854                 }
00855             }
00856 
00857             if (strtolower($type) !== 'vendor' && empty($search) && $_this->__load($file)) {
00858                 $directory = false;
00859             } else {
00860                 $file = $find;
00861                 $directory = $_this->__find($find, true);
00862             }
00863 
00864             if ($directory !== null) {
00865                 $_this->__cache = true;
00866                 $_this->__map($directory . $file, $name . $ext['class'], $type, $plugin);
00867                 $_this->__overload($type, $name . $ext['class']);
00868 
00869                 if ( $_this->return) {
00870                     $value = include $directory . $file;
00871                     return $value;
00872                 }
00873                 return true;
00874             }
00875             return false;
00876         }
00877         return true;
00878     }
00879 /**
00880  * Returns a single instance of App
00881  *
00882  * @return object
00883  * @access public
00884  */
00885     function &getInstance() {
00886         static $instance = array();
00887         if (!$instance) {
00888             $instance[0] =& new App();
00889             $instance[0]->__map = Cache::read('file_map', '_cake_core_');
00890         }
00891         return $instance[0];
00892     }
00893 /**
00894  * Locates the $file in $__paths, searches recursively
00895  *
00896  * @param string $file full file name
00897  * @param boolean $recursive search $__paths recursively
00898  * @return mixed boolean on fail, $file directory path on success
00899  * @access private
00900  */
00901     function __find($file, $recursive = true) {
00902         $_this =& App::getInstance();
00903 
00904         if (empty($_this->search)) {
00905             return null;
00906         } elseif (is_string($_this->search)) {
00907             $_this->search = array($_this->search);
00908         }
00909 
00910         if (empty($_this->__paths)) {
00911             $_this->__paths = Cache::read('dir_map', '_cake_core_');
00912         }
00913 
00914         foreach ($_this->search as $path) {
00915             $path = rtrim($path, DS);
00916 
00917             if ($path === rtrim(APP, DS)) {
00918                 $recursive = false;
00919             }
00920             if ($recursive === false) {
00921                 if ($_this->__load($path . DS . $file)) {
00922                     return $path . DS;
00923                 }
00924                 continue;
00925             }
00926             if (!isset($_this->__paths[$path])) {
00927                 $_this->import('Folder');
00928                 $Folder =& new Folder();
00929                 $directories = $Folder->tree($path, false, 'dir');
00930                 $_this->__paths[$path] = $directories;
00931             }
00932 
00933             foreach ($_this->__paths[$path] as $directory) {
00934                 if ($_this->__load($directory . DS . $file)) {
00935                     return $directory . DS;
00936                 }
00937             }
00938         }
00939         return null;
00940     }
00941 /**
00942  * Attempts to load $file
00943  *
00944  * @param string $file full path to file including file name
00945  * @return boolean
00946  */
00947     function __load($file) {
00948         $_this =& App::getInstance();
00949 
00950         if (!$_this->return && in_array($file, $_this->__loaded)) {
00951             return true;
00952         }
00953 
00954         if (file_exists($file)) {
00955             if (!$_this->return) {
00956                 require($file);
00957             }
00958             $_this->__loaded[] = $file;
00959             return true;
00960         }
00961         return false;
00962     }
00963 /**
00964  * Maps the $name to the $file
00965  *
00966  * @param string $file full path to file
00967  * @param string $name unique name for this map
00968  * @param string $type type object being mapped
00969  * @param string $plugin if object is from a plugin, the name of the plugin
00970  * @access private
00971  */
00972     function __map($file, $name, $type, $plugin) {
00973         $_this =& App::getInstance();
00974 
00975         if ($plugin) {
00976             $plugin = Inflector::camelize($plugin);
00977             $_this->__map['Plugin'][$plugin][$type][$name] = $file;
00978         } else {
00979             $_this->__map[$type][$name] = $file;
00980         }
00981     }
00982 /**
00983  * Return files complete path
00984  *
00985  * @param string $name unique name
00986  * @param string $type type object
00987  * @param string $plugin if object is from a plugin, the name of the plugin
00988  * @return mixed, file path if found, false otherwise
00989  * @access private
00990  */
00991     function __mapped($name, $type, $plugin) {
00992         $_this =& App::getInstance();
00993 
00994         if ($plugin) {
00995             $plugin = Inflector::camelize($plugin);
00996 
00997             if (isset($_this->__map['Plugin'][$plugin][$type])) {
00998                 if (array_key_exists($name, $_this->__map['Plugin'][$plugin][$type])) {
00999                     return $_this->__map['Plugin'][$plugin][$type][$name];
01000                 }
01001                 return false;
01002             }
01003         }
01004 
01005         if (isset($_this->__map[$type])) {
01006             if (array_key_exists($name, $_this->__map[$type])) {
01007                 return $_this->__map[$type][$name];
01008 
01009             }
01010             return false;
01011         }
01012     }
01013 /**
01014  * Used to overload Objects as needed
01015  *
01016  * @param string $type Model or Helper
01017  * @param string $name Class name to overload
01018  * @access private
01019  */
01020     function __overload($type, $name) {
01021         if (($type ==='Model' || $type === 'Helper') && strtolower($name) != 'schema') {
01022             Overloadable::overload($name);
01023         }
01024     }
01025 /**
01026  * Loads parent classes based on the $type
01027  * Returns and prefix or suffix needed for load files
01028  *
01029  * @param string $type type of object
01030  * @param string $plugin name of plugin
01031  * @param boolean $parent false will not attempt to load parent
01032  * @return array
01033  * @access private
01034  */
01035     function __settings($type, $plugin, $parent) {
01036         $_this = & App::getInstance();
01037 
01038         if (!$parent) {
01039             return null;
01040         }
01041 
01042         if ($plugin) {
01043             $plugin = Inflector::underscore($plugin);
01044             $name = Inflector::camelize($plugin);
01045         }
01046         $path = null;
01047         $load = strtolower($type);
01048 
01049         switch ($load) {
01050             case 'model':
01051                 if (!class_exists('Model')) {
01052                     $_this->import('Core', 'Model', false, Configure::corePaths('model'));
01053                 }
01054                 $_this->import($type, 'AppModel', false, Configure::read('modelPaths'));
01055                 if ($plugin) {
01056                     $_this->import($type, $plugin . '.' . $name . 'AppModel', false, array(), $plugin . DS . $plugin . '_app_model.php');
01057                     $path = $plugin . DS . 'models' . DS;
01058                 }
01059                 return array('class' => null, 'suffix' => null, 'path' => $path);
01060             break;
01061             case 'behavior':
01062                 $_this->import($type, 'Behavior', false);
01063                 if ($plugin) {
01064                     $path = $plugin . DS . 'models' . DS . 'behaviors' . DS;
01065                 }
01066                 return array('class' => $type, 'suffix' => null, 'path' => $path);
01067             break;
01068             case 'controller':
01069                 $_this->import($type, 'AppController', false);
01070                 if ($plugin) {
01071                     $_this->import($type, $plugin . '.' . $name . 'AppController', false, array(), $plugin . DS . $plugin . '_app_controller.php');
01072                     $path = $plugin . DS . 'controllers' . DS;
01073                 }
01074                 return array('class' => $type, 'suffix' => $type, 'path' => $path);
01075             break;
01076             case 'component':
01077                 if ($plugin) {
01078                     $path = $plugin . DS . 'controllers' . DS . 'components' . DS;
01079                 }
01080                 return array('class' => $type, 'suffix' => null, 'path' => $path);
01081             break;
01082             case 'view':
01083                 if ($plugin) {
01084                     $path = $plugin . DS . 'views' . DS;
01085                 }
01086                 return array('class' => $type, 'suffix' => null, 'path' => $path);
01087             break;
01088             case 'helper':
01089                 $_this->import($type, 'AppHelper', false);
01090                 if ($plugin) {
01091                     $path = $plugin . DS . 'views' . DS . 'helpers' . DS;
01092                 }
01093                 return array('class' => $type, 'suffix' => null, 'path' => $path);
01094             break;
01095             case 'vendor':
01096                 if ($plugin) {
01097                     $path = $plugin . DS . 'vendors' . DS;
01098                 }
01099                 return array('class' => null, 'suffix' => null, 'path' => $path);
01100             break;
01101             default:
01102                 $type = $suffix = $path = null;
01103             break;
01104         }
01105         return array('class' => null, 'suffix' => null, 'path' => null);
01106     }
01107 /**
01108  * Returns default paths to search
01109  *
01110  * @param string $type type of object to be searched
01111  * @return array list of paths
01112  * @access private
01113  */
01114     function __paths($type) {
01115         if (strtolower($type) === 'core') {
01116             $path = Configure::corePaths();
01117 
01118             foreach ($path as $key => $value) {
01119                 $count = count($key);
01120 
01121                 for ($i = 0; $i < $count; $i++) {
01122                     $paths[] = $path[$key][$i];
01123                 }
01124             }
01125             return $paths;
01126         }
01127         $paths = Configure::read(strtolower($type) . 'Paths');
01128 
01129         if (empty($paths)) {
01130             if (strtolower($type) === 'plugin') {
01131                 $paths = array(APP . 'plugins' . DS);
01132             } elseif (strtolower($type) === 'vendor') {
01133                 $paths = array(APP . 'vendors' . DS, VENDORS, APP . 'plugins' . DS);
01134             } elseif (strtolower($type) === 'controller') {
01135                 $paths = array(APP . 'controllers' . DS, APP);
01136             } elseif (strtolower($type) === 'model') {
01137                 $paths = array(APP . 'models' . DS, APP);
01138             } elseif (strtolower($type) === 'view') {
01139                 $paths = array(APP . 'views' . DS);
01140             }
01141         }
01142         return $paths;
01143     }
01144 /**
01145  * Removes file location from map if file has been deleted
01146  *
01147  * @param string $name name of object
01148  * @param string $type type of object
01149  * @param string $plugin name of plugin
01150  */
01151     function __remove($name, $type, $plugin) {
01152         $_this =& App::getInstance();
01153 
01154         if ($plugin) {
01155             $plugin = Inflector::camelize($plugin);
01156             unset($_this->__map['Plugin'][$plugin][$type][$name]);
01157         } else {
01158             unset($_this->__map[$type][$name]);
01159         }
01160     }
01161 /**
01162  * Object destructor
01163  *
01164  * Write cache file if changes have been made to the $__map or $__paths
01165  * @access private
01166  */
01167     function __destruct() {
01168         $_this = & App::getInstance();
01169 
01170         if ($_this->__cache) {
01171             Cache::write('dir_map', array_filter($_this->__paths), '_cake_core_');
01172             Cache::write('file_map', array_filter($_this->__map), '_cake_core_');
01173         }
01174     }
01175 }
01176 ?>