1: <?php
2: /**
3: * App class
4: *
5: * PHP 5
6: *
7: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8: * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
9: *
10: * Licensed under The MIT License
11: * Redistributions of files must retain the above copyright notice.
12: *
13: * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
14: * @link http://cakephp.org CakePHP(tm) Project
15: * @package Cake.Core
16: * @since CakePHP(tm) v 1.2.0.6001
17: * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
18: */
19:
20: /**
21: * App is responsible for path management, class location and class loading.
22: *
23: * ### Adding paths
24: *
25: * You can add paths to the search indexes App uses to find classes using `App::build()`. Adding
26: * additional controller paths for example would alter where CakePHP looks for controllers.
27: * This allows you to split your application up across the filesystem.
28: *
29: * ### Packages
30: *
31: * CakePHP is organized around the idea of packages, each class belongs to a package or folder where other
32: * classes reside. You can configure each package location in your application using `App::build('APackage/SubPackage', $paths)`
33: * to inform the framework where should each class be loaded. Almost every class in the CakePHP framework can be swapped
34: * by your own compatible implementation. If you wish to use you own class instead of the classes the framework provides,
35: * just add the class to your libs folder mocking the directory location of where CakePHP expects to find it.
36: *
37: * For instance if you'd like to use your own HttpSocket class, put it under
38: *
39: * app/Network/Http/HttpSocket.php
40: *
41: * ### Inspecting loaded paths
42: *
43: * You can inspect the currently loaded paths using `App::path('Controller')` for example to see loaded
44: * controller paths.
45: *
46: * It is also possible to inspect paths for plugin classes, for instance, to see a plugin's helpers you would call
47: * `App::path('View/Helper', 'MyPlugin')`
48: *
49: * ### Locating plugins and themes
50: *
51: * Plugins and Themes can be located with App as well. Using App::pluginPath('DebugKit') for example, will
52: * give you the full path to the DebugKit plugin. App::themePath('purple'), would give the full path to the
53: * `purple` theme.
54: *
55: * ### Inspecting known objects
56: *
57: * You can find out which objects App knows about using App::objects('Controller') for example to find
58: * which application controllers App knows about.
59: *
60: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html
61: * @package Cake.Core
62: */
63: class App {
64:
65: /**
66: * Append paths
67: *
68: * @constant APPEND
69: */
70: const APPEND = 'append';
71:
72: /**
73: * Prepend paths
74: *
75: * @constant PREPEND
76: */
77: const PREPEND = 'prepend';
78:
79: /**
80: * Reset paths instead of merging
81: *
82: * @constant RESET
83: */
84: const RESET = true;
85:
86: /**
87: * List of object types and their properties
88: *
89: * @var array
90: */
91: public static $types = array(
92: 'class' => array('extends' => null, 'core' => true),
93: 'file' => array('extends' => null, 'core' => true),
94: 'model' => array('extends' => 'AppModel', 'core' => false),
95: 'behavior' => array('suffix' => 'Behavior', 'extends' => 'Model/ModelBehavior', 'core' => true),
96: 'controller' => array('suffix' => 'Controller', 'extends' => 'AppController', 'core' => true),
97: 'component' => array('suffix' => 'Component', 'extends' => null, 'core' => true),
98: 'lib' => array('extends' => null, 'core' => true),
99: 'view' => array('suffix' => 'View', 'extends' => null, 'core' => true),
100: 'helper' => array('suffix' => 'Helper', 'extends' => 'AppHelper', 'core' => true),
101: 'vendor' => array('extends' => null, 'core' => true),
102: 'shell' => array('suffix' => 'Shell', 'extends' => 'AppShell', 'core' => true),
103: 'plugin' => array('extends' => null, 'core' => true)
104: );
105:
106: /**
107: * Paths to search for files.
108: *
109: * @var array
110: */
111: public static $search = array();
112:
113: /**
114: * Whether or not to return the file that is loaded.
115: *
116: * @var boolean
117: */
118: public static $return = false;
119:
120: /**
121: * Holds key/value pairs of $type => file path.
122: *
123: * @var array
124: */
125: protected static $_map = array();
126:
127: /**
128: * Holds and key => value array of object types.
129: *
130: * @var array
131: */
132: protected static $_objects = array();
133:
134: /**
135: * Holds the location of each class
136: *
137: * @var array
138: */
139: protected static $_classMap = array();
140:
141: /**
142: * Holds the possible paths for each package name
143: *
144: * @var array
145: */
146: protected static $_packages = array();
147:
148: /**
149: * Holds the templates for each customizable package path in the application
150: *
151: * @var array
152: */
153: protected static $_packageFormat = array();
154:
155: /**
156: * Maps an old style CakePHP class type to the corresponding package
157: *
158: * @var array
159: */
160: public static $legacy = array(
161: 'models' => 'Model',
162: 'behaviors' => 'Model/Behavior',
163: 'datasources' => 'Model/Datasource',
164: 'controllers' => 'Controller',
165: 'components' => 'Controller/Component',
166: 'views' => 'View',
167: 'helpers' => 'View/Helper',
168: 'shells' => 'Console/Command',
169: 'libs' => 'Lib',
170: 'vendors' => 'Vendor',
171: 'plugins' => 'Plugin',
172: );
173:
174: /**
175: * Indicates whether the class cache should be stored again because of an addition to it
176: *
177: * @var boolean
178: */
179: protected static $_cacheChange = false;
180:
181: /**
182: * Indicates whether the object cache should be stored again because of an addition to it
183: *
184: * @var boolean
185: */
186: protected static $_objectCacheChange = false;
187:
188: /**
189: * Indicates the the Application is in the bootstrapping process. Used to better cache
190: * loaded classes while the cache libraries have not been yet initialized
191: *
192: * @var boolean
193: */
194: public static $bootstrapping = false;
195:
196: /**
197: * Used to read information stored path
198: *
199: * Usage:
200: *
201: * `App::path('Model'); will return all paths for models`
202: *
203: * `App::path('Model/Datasource', 'MyPlugin'); will return the path for datasources under the 'MyPlugin' plugin`
204: *
205: * @param string $type type of path
206: * @param string $plugin name of plugin
207: * @return array
208: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::path
209: */
210: public static function path($type, $plugin = null) {
211: if (!empty(self::$legacy[$type])) {
212: $type = self::$legacy[$type];
213: }
214:
215: if (!empty($plugin)) {
216: $path = array();
217: $pluginPath = self::pluginPath($plugin);
218: $packageFormat= self::_packageFormat();
219: if (!empty($packageFormat[$type])) {
220: foreach ($packageFormat[$type] as $f) {
221: $path[] = sprintf($f, $pluginPath);
222: }
223: }
224: $path[] = $pluginPath . 'Lib' . DS . $type . DS;
225: return $path;
226: }
227:
228: if (!isset(self::$_packages[$type])) {
229: return array();
230: }
231: return self::$_packages[$type];
232: }
233:
234: /**
235: * Get all the currently loaded paths from App. Useful for inspecting
236: * or storing all paths App knows about. For a paths to a specific package
237: * use App::path()
238: *
239: * @return array An array of packages and their associated paths.
240: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::paths
241: */
242: public static function paths() {
243: return self::$_packages;
244: }
245:
246: /**
247: * Sets up each package location on the file system. You can configure multiple search paths
248: * for each package, those will be used to look for files one folder at a time in the specified order
249: * All paths should be terminated with a Directory separator
250: *
251: * Usage:
252: *
253: * `App::build(array(Model' => array('/a/full/path/to/models/'))); will setup a new search path for the Model package`
254: *
255: * `App::build(array('Model' => array('/path/to/models/')), App::RESET); will setup the path as the only valid path for searching models`
256: *
257: * `App::build(array('View/Helper' => array('/path/to/helpers/', '/another/path/'))); will setup multiple search paths for helpers`
258: *
259: * If reset is set to true, all loaded plugins will be forgotten and they will be needed to be loaded again.
260: *
261: * @param array $paths associative array with package names as keys and a list of directories for new search paths
262: * @param mixed $mode App::RESET will set paths, App::APPEND with append paths, App::PREPEND will prepend paths, [default] App::PREPEND
263: * @return void
264: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::build
265: */
266: public static function build($paths = array(), $mode = App::PREPEND) {
267: //Provides Backwards compatibility for old-style package names
268: $legacyPaths = array();
269: foreach ($paths as $type => $path) {
270: if (!empty(self::$legacy[$type])) {
271: $type = self::$legacy[$type];
272: }
273: $legacyPaths[$type] = $path;
274: }
275: $paths = $legacyPaths;
276:
277: if ($mode === App::RESET) {
278: foreach ($paths as $type => $new) {
279: self::$_packages[$type] = (array)$new;
280: self::objects($type, null, false);
281: }
282: return;
283: }
284:
285: $packageFormat = self::_packageFormat();
286:
287: $defaults = array();
288: foreach ($packageFormat as $package => $format) {
289: foreach ($format as $f) {
290: $defaults[$package][] = sprintf($f, APP);
291: }
292: }
293:
294: if (empty($paths)) {
295: self::$_packages = $defaults;
296: return;
297: }
298:
299: foreach ($defaults as $type => $default) {
300: if (!empty(self::$_packages[$type])) {
301: $path = self::$_packages[$type];
302: }
303:
304: if (!empty($paths[$type])) {
305: $newPath = (array)$paths[$type];
306:
307: if ($mode === App::PREPEND) {
308: $path = array_merge($newPath, $path);
309: } else {
310: $path = array_merge($path, $newPath);
311: }
312:
313: $path = array_values(array_unique($path));
314: }
315:
316: self::$_packages[$type] = $path;
317: }
318: }
319:
320: /**
321: * Gets the path that a plugin is on. Searches through the defined plugin paths.
322: *
323: * Usage:
324: *
325: * `App::pluginPath('MyPlugin'); will return the full path to 'MyPlugin' plugin'`
326: *
327: * @param string $plugin CamelCased/lower_cased plugin name to find the path of.
328: * @return string full path to the plugin.
329: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::pluginPath
330: */
331: public static function pluginPath($plugin) {
332: return CakePlugin::path($plugin);
333: }
334:
335: /**
336: * Finds the path that a theme is on. Searches through the defined theme paths.
337: *
338: * Usage:
339: *
340: * `App::themePath('MyTheme'); will return the full path to the 'MyTheme' theme`
341: *
342: * @param string $theme theme name to find the path of.
343: * @return string full path to the theme.
344: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::themePath
345: */
346: public static function themePath($theme) {
347: $themeDir = 'Themed' . DS . Inflector::camelize($theme);
348: foreach (self::$_packages['View'] as $path) {
349: if (is_dir($path . $themeDir)) {
350: return $path . $themeDir . DS ;
351: }
352: }
353: return self::$_packages['View'][0] . $themeDir . DS;
354: }
355:
356: /**
357: * Returns the full path to a package inside the CakePHP core
358: *
359: * Usage:
360: *
361: * `App::core('Cache/Engine'); will return the full path to the cache engines package`
362: *
363: * @param string $type
364: * @return array full path to package
365: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::core
366: */
367: public static function core($type) {
368: return array(CAKE . str_replace('/', DS, $type) . DS);
369: }
370:
371: /**
372: * Returns an array of objects of the given type.
373: *
374: * Example usage:
375: *
376: * `App::objects('plugin');` returns `array('DebugKit', 'Blog', 'User');`
377: *
378: * `App::objects('Controller');` returns `array('PagesController', 'BlogController');`
379: *
380: * You can also search only within a plugin's objects by using the plugin dot
381: * syntax.
382: *
383: * `App::objects('MyPlugin.Model');` returns `array('MyPluginPost', 'MyPluginComment');`
384: *
385: * When scanning directories, files and directories beginning with `.` will be excluded as these
386: * are commonly used by version control systems.
387: *
388: * @param string $type Type of object, i.e. 'Model', 'Controller', 'View/Helper', 'file', 'class' or 'plugin'
389: * @param mixed $path Optional Scan only the path given. If null, paths for the chosen type will be used.
390: * @param boolean $cache Set to false to rescan objects of the chosen type. Defaults to true.
391: * @return mixed Either false on incorrect / miss. Or an array of found objects.
392: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::objects
393: */
394: public static function objects($type, $path = null, $cache = true) {
395: $extension = '/\.php$/';
396: $includeDirectories = false;
397: $name = $type;
398:
399: if ($type === 'plugin') {
400: $type = 'plugins';
401: }
402:
403: if ($type == 'plugins') {
404: $extension = '/.*/';
405: $includeDirectories = true;
406: }
407:
408: list($plugin, $type) = pluginSplit($type);
409:
410: if (isset(self::$legacy[$type . 's'])) {
411: $type = self::$legacy[$type . 's'];
412: }
413:
414: if ($type === 'file' && !$path) {
415: return false;
416: } elseif ($type === 'file') {
417: $extension = '/\.php$/';
418: $name = $type . str_replace(DS, '', $path);
419: }
420:
421: if (empty(self::$_objects) && $cache === true) {
422: self::$_objects = Cache::read('object_map', '_cake_core_');
423: }
424:
425: $cacheLocation = empty($plugin) ? 'app' : $plugin;
426:
427: if ($cache !== true || !isset(self::$_objects[$cacheLocation][$name])) {
428: $objects = array();
429:
430: if (empty($path)) {
431: $path = self::path($type, $plugin);
432: }
433:
434: foreach ((array)$path as $dir) {
435: if ($dir != APP && is_dir($dir)) {
436: $files = new RegexIterator(new DirectoryIterator($dir), $extension);
437: foreach ($files as $file) {
438: $fileName = basename($file);
439: if (!$file->isDot() && $fileName[0] !== '.') {
440: $isDir = $file->isDir() ;
441: if ($isDir && $includeDirectories) {
442: $objects[] = $fileName;
443: } elseif (!$includeDirectories && !$isDir) {
444: $objects[] = substr($fileName, 0, -4);
445: }
446: }
447: }
448: }
449: }
450:
451: if ($type !== 'file') {
452: foreach ($objects as $key => $value) {
453: $objects[$key] = Inflector::camelize($value);
454: }
455: }
456:
457: sort($objects);
458: if ($plugin) {
459: return $objects;
460: }
461:
462: self::$_objects[$cacheLocation][$name] = $objects;
463: if ($cache) {
464: self::$_objectCacheChange = true;
465: }
466: }
467:
468: return self::$_objects[$cacheLocation][$name];
469: }
470:
471: /**
472: * Declares a package for a class. This package location will be used
473: * by the automatic class loader if the class is tried to be used
474: *
475: * Usage:
476: *
477: * `App::uses('MyCustomController', 'Controller');` will setup the class to be found under Controller package
478: *
479: * `App::uses('MyHelper', 'MyPlugin.View/Helper');` will setup the helper class to be found in plugin's helper package
480: *
481: * @param string $className the name of the class to configure package for
482: * @param string $location the package name
483: * @return void
484: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::uses
485: */
486: public static function uses($className, $location) {
487: self::$_classMap[$className] = $location;
488: }
489:
490: /**
491: * Method to handle the automatic class loading. It will look for each class' package
492: * defined using App::uses() and with this information it will resolve the package name to a full path
493: * to load the class from. File name for each class should follow the class name. For instance,
494: * if a class is name `MyCustomClass` the file name should be `MyCustomClass.php`
495: *
496: * @param string $className the name of the class to load
497: * @return boolean
498: */
499: public static function load($className) {
500: if (!isset(self::$_classMap[$className])) {
501: return false;
502: }
503:
504: if ($file = self::_mapped($className)) {
505: return include $file;
506: }
507:
508: $parts = explode('.', self::$_classMap[$className], 2);
509: list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts));
510: $paths = self::path($package, $plugin);
511:
512: if (empty($plugin)) {
513: $appLibs = empty(self::$_packages['Lib']) ? APPLIBS : current(self::$_packages['Lib']);
514: $paths[] = $appLibs . $package . DS;
515: $paths[] = CAKE . $package . DS;
516: }
517:
518: foreach ($paths as $path) {
519: $file = $path . $className . '.php';
520: if (file_exists($file)) {
521: self::_map($file, $className);
522: return include $file;
523: }
524: }
525:
526: // To help apps migrate to 2.0 old style file names are allowed
527: // if the trailing segment is one of the types that changed, alternates will be tried.
528: foreach ($paths as $path) {
529: $underscored = Inflector::underscore($className);
530: $tries = array($path . $underscored . '.php');
531: $parts = explode('_', $underscored);
532: $numParts = count($parts);
533: if ($numParts > 1 && in_array($parts[$numParts - 1], array('behavior', 'helper', 'component'))) {
534: array_pop($parts);
535: $tries[] = $path . implode('_', $parts) . '.php';
536: }
537: foreach ($tries as $file) {
538: if (file_exists($file)) {
539: self::_map($file, $className);
540: return include $file;
541: }
542: }
543: }
544:
545: return false;
546: }
547:
548: /**
549: * Returns the package name where a class was defined to be located at
550: *
551: * @param string $className name of the class to obtain the package name from
552: * @return string package name or null if not declared
553: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::location
554: */
555: public static function location($className) {
556: if (!empty(self::$_classMap[$className])) {
557: return self::$_classMap[$className];
558: }
559: return null;
560: }
561:
562: /**
563: * Finds classes based on $name or specific file(s) to search. Calling App::import() will
564: * not construct any classes contained in the files. It will only find and require() the file.
565: *
566: * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#including-files-with-app-import
567: * @param mixed $type The type of Class if passed as a string, or all params can be passed as
568: * an single array to $type,
569: * @param string $name Name of the Class or a unique name for the file
570: * @param mixed $parent boolean true if Class Parent should be searched, accepts key => value
571: * array('parent' => $parent ,'file' => $file, 'search' => $search, 'ext' => '$ext');
572: * $ext allows setting the extension of the file name
573: * based on Inflector::underscore($name) . ".$ext";
574: * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3');
575: * @param string $file full name of the file to search for including extension
576: * @param boolean $return Return the loaded file, the file must have a return
577: * statement in it to work: return $variable;
578: * @return boolean true if Class is already in memory or if file is found and loaded, false if not
579: */
580: public static function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) {
581: $ext = null;
582:
583: if (is_array($type)) {
584: extract($type, EXTR_OVERWRITE);
585: }
586:
587: if (is_array($parent)) {
588: extract($parent, EXTR_OVERWRITE);
589: }
590:
591: if ($name == null && $file == null) {
592: return false;
593: }
594:
595: if (is_array($name)) {
596: foreach ($name as $class) {
597: if (!App::import(compact('type', 'parent', 'search', 'file', 'return') + array('name' => $class))) {
598: return false;
599: }
600: }
601: return true;
602: }
603:
604: $originalType = strtolower($type);
605: $specialPackage = in_array($originalType, array('file', 'vendor'));
606: if (!$specialPackage && isset(self::$legacy[$originalType . 's'])) {
607: $type = self::$legacy[$originalType . 's'];
608: }
609: list($plugin, $name) = pluginSplit($name);
610: if (!empty($plugin)) {
611: if (!CakePlugin::loaded($plugin)) {
612: return false;
613: }
614: }
615:
616: if (!$specialPackage) {
617: return self::_loadClass($name, $plugin, $type, $originalType, $parent);
618: }
619:
620: if ($originalType == 'file' && !empty($file)) {
621: return self::_loadFile($name, $plugin, $search, $file, $return);
622: }
623:
624: if ($originalType == 'vendor') {
625: return self::_loadVendor($name, $plugin, $file, $ext);
626: }
627:
628: return false;
629: }
630:
631: /**
632: * Helper function to include classes
633: * This is a compatibility wrapper around using App::uses() and automatic class loading
634: *
635: * @param string $name unique name of the file for identifying it inside the application
636: * @param string $plugin camel cased plugin name if any
637: * @param string $type name of the packed where the class is located
638: * @param string $originalType type name as supplied initially by the user
639: * @param boolean $parent whether to load the class parent or not
640: * @return boolean true indicating the successful load and existence of the class
641: */
642: protected static function _loadClass($name, $plugin, $type, $originalType, $parent) {
643: if ($type == 'Console/Command' && $name == 'Shell') {
644: $type = 'Console';
645: } else if (isset(self::$types[$originalType]['suffix'])) {
646: $suffix = self::$types[$originalType]['suffix'];
647: $name .= ($suffix == $name) ? '' : $suffix;
648: }
649: if ($parent && isset(self::$types[$originalType]['extends'])) {
650: $extends = self::$types[$originalType]['extends'];
651: $extendType = $type;
652: if (strpos($extends, '/') !== false) {
653: $parts = explode('/', $extends);
654: $extends = array_pop($parts);
655: $extendType = implode('/', $parts);
656: }
657: App::uses($extends, $extendType);
658: if ($plugin && in_array($originalType, array('controller', 'model'))) {
659: App::uses($plugin . $extends, $plugin . '.' . $type);
660: }
661: }
662: if ($plugin) {
663: $plugin .= '.';
664: }
665: $name = Inflector::camelize($name);
666: App::uses($name, $plugin . $type);
667: return class_exists($name);
668: }
669:
670: /**
671: * Helper function to include single files
672: *
673: * @param string $name unique name of the file for identifying it inside the application
674: * @param string $plugin camel cased plugin name if any
675: * @param array $search list of paths to search the file into
676: * @param string $file filename if known, the $name param will be used otherwise
677: * @param boolean $return whether this function should return the contents of the file after being parsed by php or just a success notice
678: * @return mixed if $return contents of the file after php parses it, boolean indicating success otherwise
679: */
680: protected static function _loadFile($name, $plugin, $search, $file, $return) {
681: $mapped = self::_mapped($name, $plugin);
682: if ($mapped) {
683: $file = $mapped;
684: } else if (!empty($search)) {
685: foreach ($search as $path) {
686: $found = false;
687: if (file_exists($path . $file)) {
688: $file = $path . $file;
689: $found = true;
690: break;
691: }
692: if (empty($found)) {
693: $file = false;
694: }
695: }
696: }
697: if (!empty($file) && file_exists($file)) {
698: self::_map($file, $name, $plugin);
699: $returnValue = include $file;
700: if ($return) {
701: return $returnValue;
702: }
703: return (bool) $returnValue;
704: }
705: return false;
706: }
707:
708: /**
709: * Helper function to load files from vendors folders
710: *
711: * @param string $name unique name of the file for identifying it inside the application
712: * @param string $plugin camel cased plugin name if any
713: * @param string $file file name if known
714: * @param string $ext file extension if known
715: * @return boolean true if the file was loaded successfully, false otherwise
716: */
717: protected static function _loadVendor($name, $plugin, $file, $ext) {
718: if ($mapped = self::_mapped($name, $plugin)) {
719: return (bool) include_once($mapped);
720: }
721: $fileTries = array();
722: $paths = ($plugin) ? App::path('vendors', $plugin) : App::path('vendors');
723: if (empty($ext)) {
724: $ext = 'php';
725: }
726: if (empty($file)) {
727: $fileTries[] = $name . '.' . $ext;
728: $fileTries[] = Inflector::underscore($name) . '.' . $ext;
729: } else {
730: $fileTries[] = $file;
731: }
732:
733: foreach ($fileTries as $file) {
734: foreach ($paths as $path) {
735: if (file_exists($path . $file)) {
736: self::_map($path . $file, $name, $plugin);
737: return (bool) include($path . $file);
738: }
739: }
740: }
741: return false;
742: }
743:
744: /**
745: * Initializes the cache for App, registers a shutdown function.
746: *
747: * @return void
748: */
749: public static function init() {
750: self::$_map += (array)Cache::read('file_map', '_cake_core_');
751: self::$_objects += (array)Cache::read('object_map', '_cake_core_');
752: register_shutdown_function(array('App', 'shutdown'));
753: }
754:
755: /**
756: * Maps the $name to the $file.
757: *
758: * @param string $file full path to file
759: * @param string $name unique name for this map
760: * @param string $plugin camelized if object is from a plugin, the name of the plugin
761: * @return void
762: */
763: protected static function _map($file, $name, $plugin = null) {
764: if ($plugin) {
765: self::$_map['Plugin'][$plugin][$name] = $file;
766: } else {
767: self::$_map[$name] = $file;
768: }
769: if (!self::$bootstrapping) {
770: self::$_cacheChange = true;
771: }
772: }
773:
774: /**
775: * Returns a file's complete path.
776: *
777: * @param string $name unique name
778: * @param string $plugin camelized if object is from a plugin, the name of the plugin
779: * @return mixed file path if found, false otherwise
780: */
781: protected static function _mapped($name, $plugin = null) {
782: if ($plugin) {
783: if (isset(self::$_map['Plugin'][$plugin][$name])) {
784: return self::$_map['Plugin'][$plugin][$name];
785: }
786: return false;
787: }
788:
789: if (isset(self::$_map[$name])) {
790: return self::$_map[$name];
791: }
792: return false;
793: }
794:
795: /**
796: * Sets then returns the templates for each customizable package path
797: *
798: * @return array templates for each customizable package path
799: */
800: protected static function _packageFormat() {
801: if (empty(self::$_packageFormat)) {
802: self::$_packageFormat = array(
803: 'Model' => array(
804: '%s' . 'Model' . DS,
805: '%s' . 'models' . DS
806: ),
807: 'Model/Behavior' => array(
808: '%s' . 'Model' . DS . 'Behavior' . DS,
809: '%s' . 'models' . DS . 'behaviors' . DS
810: ),
811: 'Model/Datasource' => array(
812: '%s' . 'Model' . DS . 'Datasource' . DS,
813: '%s' . 'models' . DS . 'datasources' . DS
814: ),
815: 'Model/Datasource/Database' => array(
816: '%s' . 'Model' . DS . 'Datasource' . DS . 'Database' . DS,
817: '%s' . 'models' . DS . 'datasources' . DS . 'database' . DS
818: ),
819: 'Model/Datasource/Session' => array(
820: '%s' . 'Model' . DS . 'Datasource' . DS . 'Session' . DS,
821: '%s' . 'models' . DS . 'datasources' . DS . 'session' . DS
822: ),
823: 'Controller' => array(
824: '%s' . 'Controller' . DS,
825: '%s' . 'controllers' . DS
826: ),
827: 'Controller/Component' => array(
828: '%s' . 'Controller' . DS . 'Component' . DS,
829: '%s' . 'controllers' . DS . 'components' . DS
830: ),
831: 'Controller/Component/Auth' => array(
832: '%s' . 'Controller' . DS . 'Component' . DS . 'Auth' . DS,
833: '%s' . 'controllers' . DS . 'components' . DS . 'auth' . DS
834: ),
835: 'View' => array(
836: '%s' . 'View' . DS,
837: '%s' . 'views' . DS
838: ),
839: 'View/Helper' => array(
840: '%s' . 'View' . DS . 'Helper' . DS,
841: '%s' . 'views' . DS . 'helpers' . DS
842: ),
843: 'Console' => array(
844: '%s' . 'Console' . DS,
845: '%s' . 'console' . DS
846: ),
847: 'Console/Command' => array(
848: '%s' . 'Console' . DS . 'Command' . DS,
849: '%s' . 'console' . DS . 'shells' . DS,
850: ),
851: 'Console/Command/Task' => array(
852: '%s' . 'Console' . DS . 'Command' . DS . 'Task' . DS,
853: '%s' . 'console' . DS . 'shells' . DS . 'tasks' . DS
854: ),
855: 'Lib' => array(
856: '%s' . 'Lib' . DS,
857: '%s' . 'libs' . DS
858: ),
859: 'locales' => array(
860: '%s' . 'Locale' . DS,
861: '%s' . 'locale' . DS
862: ),
863: 'Vendor' => array(
864: '%s' . 'Vendor' . DS,
865: dirname(dirname(CAKE)) . DS . 'vendors' . DS,
866: VENDORS
867: ),
868: 'Plugin' => array(
869: APP . 'Plugin' . DS,
870: APP . 'plugins' . DS,
871: dirname(dirname(CAKE)) . DS . 'plugins' . DS
872: )
873: );
874: }
875:
876: return self::$_packageFormat;
877: }
878:
879: /**
880: * Object destructor.
881: *
882: * Writes cache file if changes have been made to the $_map
883: *
884: * @return void
885: */
886: public static function shutdown() {
887: if (self::$_cacheChange) {
888: Cache::write('file_map', array_filter(self::$_map), '_cake_core_');
889: }
890: if (self::$_objectCacheChange) {
891: Cache::write('object_map', self::$_objects, '_cake_core_');
892: }
893: }
894: }
895: