統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Core / App.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (27.506 KB)

1
<?php
2
/**
3
 * App class
4
 *
5
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @package       Cake.Core
15
 * @since         CakePHP(tm) v 1.2.0.6001
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18

    
19
App::uses('Inflector', 'Utility');
20
App::uses('CakePlugin', 'Core');
21

    
22
/**
23
 * App is responsible for path management, class location and class loading.
24
 *
25
 * ### Adding paths
26
 *
27
 * You can add paths to the search indexes App uses to find classes using `App::build()`. Adding
28
 * additional controller paths for example would alter where CakePHP looks for controllers.
29
 * This allows you to split your application up across the filesystem.
30
 *
31
 * ### Packages
32
 *
33
 * CakePHP is organized around the idea of packages, each class belongs to a package or folder where other
34
 * classes reside. You can configure each package location in your application using `App::build('APackage/SubPackage', $paths)`
35
 * to inform the framework where should each class be loaded. Almost every class in the CakePHP framework can be swapped
36
 * by your own compatible implementation. If you wish to use your own class instead of the classes the framework provides,
37
 * just add the class to your libs folder mocking the directory location of where CakePHP expects to find it.
38
 *
39
 * For instance if you'd like to use your own HttpSocket class, put it under
40
 *
41
 *                app/Network/Http/HttpSocket.php
42
 *
43
 * ### Inspecting loaded paths
44
 *
45
 * You can inspect the currently loaded paths using `App::path('Controller')` for example to see loaded
46
 * controller paths.
47
 *
48
 * It is also possible to inspect paths for plugin classes, for instance, to see a plugin's helpers you would call
49
 * `App::path('View/Helper', 'MyPlugin')`
50
 *
51
 * ### Locating plugins and themes
52
 *
53
 * Plugins and Themes can be located with App as well. Using App::pluginPath('DebugKit') for example, will
54
 * give you the full path to the DebugKit plugin. App::themePath('purple'), would give the full path to the
55
 * `purple` theme.
56
 *
57
 * ### Inspecting known objects
58
 *
59
 * You can find out which objects App knows about using App::objects('Controller') for example to find
60
 * which application controllers App knows about.
61
 *
62
 * @link          http://book.cakephp.org/2.0/en/core-utility-libraries/app.html
63
 * @package       Cake.Core
64
 */
65
class App {
66

    
67
/**
68
 * Append paths
69
 *
70
 * @var string
71
 */
72
        const APPEND = 'append';
73

    
74
/**
75
 * Prepend paths
76
 *
77
 * @var string
78
 */
79
        const PREPEND = 'prepend';
80

    
81
/**
82
 * Register package
83
 *
84
 * @var string
85
 */
86
        const REGISTER = 'register';
87

    
88
/**
89
 * Reset paths instead of merging
90
 *
91
 * @var bool
92
 */
93
        const RESET = true;
94

    
95
/**
96
 * List of object types and their properties
97
 *
98
 * @var array
99
 */
100
        public static $types = array(
101
                'class' => array('extends' => null, 'core' => true),
102
                'file' => array('extends' => null, 'core' => true),
103
                'model' => array('extends' => 'AppModel', 'core' => false),
104
                'behavior' => array('suffix' => 'Behavior', 'extends' => 'Model/ModelBehavior', 'core' => true),
105
                'controller' => array('suffix' => 'Controller', 'extends' => 'AppController', 'core' => true),
106
                'component' => array('suffix' => 'Component', 'extends' => null, 'core' => true),
107
                'lib' => array('extends' => null, 'core' => true),
108
                'view' => array('suffix' => 'View', 'extends' => null, 'core' => true),
109
                'helper' => array('suffix' => 'Helper', 'extends' => 'AppHelper', 'core' => true),
110
                'vendor' => array('extends' => null, 'core' => true),
111
                'shell' => array('suffix' => 'Shell', 'extends' => 'AppShell', 'core' => true),
112
                'plugin' => array('extends' => null, 'core' => true)
113
        );
114

    
115
/**
116
 * Paths to search for files.
117
 *
118
 * @var array
119
 */
120
        public static $search = array();
121

    
122
/**
123
 * Whether or not to return the file that is loaded.
124
 *
125
 * @var bool
126
 */
127
        public static $return = false;
128

    
129
/**
130
 * Holds key/value pairs of $type => file path.
131
 *
132
 * @var array
133
 */
134
        protected static $_map = array();
135

    
136
/**
137
 * Holds and key => value array of object types.
138
 *
139
 * @var array
140
 */
141
        protected static $_objects = array();
142

    
143
/**
144
 * Holds the location of each class
145
 *
146
 * @var array
147
 */
148
        protected static $_classMap = array();
149

    
150
/**
151
 * Holds the possible paths for each package name
152
 *
153
 * @var array
154
 */
155
        protected static $_packages = array();
156

    
157
/**
158
 * Holds the templates for each customizable package path in the application
159
 *
160
 * @var array
161
 */
162
        protected static $_packageFormat = array();
163

    
164
/**
165
 * Maps an old style CakePHP class type to the corresponding package
166
 *
167
 * @var array
168
 */
169
        public static $legacy = array(
170
                'models' => 'Model',
171
                'behaviors' => 'Model/Behavior',
172
                'datasources' => 'Model/Datasource',
173
                'controllers' => 'Controller',
174
                'components' => 'Controller/Component',
175
                'views' => 'View',
176
                'helpers' => 'View/Helper',
177
                'shells' => 'Console/Command',
178
                'libs' => 'Lib',
179
                'vendors' => 'Vendor',
180
                'plugins' => 'Plugin',
181
                'locales' => 'Locale'
182
        );
183

    
184
/**
185
 * Indicates whether the class cache should be stored again because of an addition to it
186
 *
187
 * @var bool
188
 */
189
        protected static $_cacheChange = false;
190

    
191
/**
192
 * Indicates whether the object cache should be stored again because of an addition to it
193
 *
194
 * @var bool
195
 */
196
        protected static $_objectCacheChange = false;
197

    
198
/**
199
 * Indicates the the Application is in the bootstrapping process. Used to better cache
200
 * loaded classes while the cache libraries have not been yet initialized
201
 *
202
 * @var bool
203
 */
204
        public static $bootstrapping = false;
205

    
206
/**
207
 * Used to read information stored path
208
 *
209
 * Usage:
210
 *
211
 * `App::path('Model'); will return all paths for models`
212
 *
213
 * `App::path('Model/Datasource', 'MyPlugin'); will return the path for datasources under the 'MyPlugin' plugin`
214
 *
215
 * @param string $type type of path
216
 * @param string $plugin name of plugin
217
 * @return array
218
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::path
219
 */
220
        public static function path($type, $plugin = null) {
221
                if (!empty(static::$legacy[$type])) {
222
                        $type = static::$legacy[$type];
223
                }
224

    
225
                if (!empty($plugin)) {
226
                        $path = array();
227
                        $pluginPath = CakePlugin::path($plugin);
228
                        $packageFormat = static::_packageFormat();
229
                        if (!empty($packageFormat[$type])) {
230
                                foreach ($packageFormat[$type] as $f) {
231
                                        $path[] = sprintf($f, $pluginPath);
232
                                }
233
                        }
234
                        return $path;
235
                }
236

    
237
                if (!isset(static::$_packages[$type])) {
238
                        return array();
239
                }
240
                return static::$_packages[$type];
241
        }
242

    
243
/**
244
 * Get all the currently loaded paths from App. Useful for inspecting
245
 * or storing all paths App knows about. For a paths to a specific package
246
 * use App::path()
247
 *
248
 * @return array An array of packages and their associated paths.
249
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::paths
250
 */
251
        public static function paths() {
252
                return static::$_packages;
253
        }
254

    
255
/**
256
 * Sets up each package location on the file system. You can configure multiple search paths
257
 * for each package, those will be used to look for files one folder at a time in the specified order
258
 * All paths should be terminated with a Directory separator
259
 *
260
 * Usage:
261
 *
262
 * `App::build(array('Model' => array('/a/full/path/to/models/'))); will setup a new search path for the Model package`
263
 *
264
 * `App::build(array('Model' => array('/path/to/models/')), App::RESET); will setup the path as the only valid path for searching models`
265
 *
266
 * `App::build(array('View/Helper' => array('/path/to/helpers/', '/another/path/'))); will setup multiple search paths for helpers`
267
 *
268
 * `App::build(array('Service' => array('%s' . 'Service' . DS)), App::REGISTER); will register new package 'Service'`
269
 *
270
 * If reset is set to true, all loaded plugins will be forgotten and they will be needed to be loaded again.
271
 *
272
 * @param array $paths associative array with package names as keys and a list of directories for new search paths
273
 * @param bool|string $mode App::RESET will set paths, App::APPEND with append paths, App::PREPEND will prepend paths (default)
274
 *         App::REGISTER will register new packages and their paths, %s in path will be replaced by APP path
275
 * @return void
276
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::build
277
 */
278
        public static function build($paths = array(), $mode = App::PREPEND) {
279
                //Provides Backwards compatibility for old-style package names
280
                $legacyPaths = array();
281
                foreach ($paths as $type => $path) {
282
                        if (!empty(static::$legacy[$type])) {
283
                                $type = static::$legacy[$type];
284
                        }
285
                        $legacyPaths[$type] = $path;
286
                }
287
                $paths = $legacyPaths;
288

    
289
                if ($mode === App::RESET) {
290
                        foreach ($paths as $type => $new) {
291
                                static::$_packages[$type] = (array)$new;
292
                                static::objects($type, null, false);
293
                        }
294
                        return;
295
                }
296

    
297
                if (empty($paths)) {
298
                        static::$_packageFormat = null;
299
                }
300

    
301
                $packageFormat = static::_packageFormat();
302

    
303
                if ($mode === App::REGISTER) {
304
                        foreach ($paths as $package => $formats) {
305
                                if (empty($packageFormat[$package])) {
306
                                        $packageFormat[$package] = $formats;
307
                                } else {
308
                                        $formats = array_merge($packageFormat[$package], $formats);
309
                                        $packageFormat[$package] = array_values(array_unique($formats));
310
                                }
311
                        }
312
                        static::$_packageFormat = $packageFormat;
313
                }
314

    
315
                $defaults = array();
316
                foreach ($packageFormat as $package => $format) {
317
                        foreach ($format as $f) {
318
                                $defaults[$package][] = sprintf($f, APP);
319
                        }
320
                }
321

    
322
                if (empty($paths)) {
323
                        static::$_packages = $defaults;
324
                        return;
325
                }
326

    
327
                if ($mode === App::REGISTER) {
328
                        $paths = array();
329
                }
330

    
331
                foreach ($defaults as $type => $default) {
332
                        if (!empty(static::$_packages[$type])) {
333
                                $path = static::$_packages[$type];
334
                        } else {
335
                                $path = $default;
336
                        }
337

    
338
                        if (!empty($paths[$type])) {
339
                                $newPath = (array)$paths[$type];
340

    
341
                                if ($mode === App::PREPEND) {
342
                                        $path = array_merge($newPath, $path);
343
                                } else {
344
                                        $path = array_merge($path, $newPath);
345
                                }
346

    
347
                                $path = array_values(array_unique($path));
348
                        }
349

    
350
                        static::$_packages[$type] = $path;
351
                }
352
        }
353

    
354
/**
355
 * Gets the path that a plugin is on. Searches through the defined plugin paths.
356
 *
357
 * Usage:
358
 *
359
 * `App::pluginPath('MyPlugin'); will return the full path to 'MyPlugin' plugin'`
360
 *
361
 * @param string $plugin CamelCased/lower_cased plugin name to find the path of.
362
 * @return string full path to the plugin.
363
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::pluginPath
364
 * @deprecated 3.0.0 Use `CakePlugin::path()` instead.
365
 */
366
        public static function pluginPath($plugin) {
367
                return CakePlugin::path($plugin);
368
        }
369

    
370
/**
371
 * Finds the path that a theme is on. Searches through the defined theme paths.
372
 *
373
 * Usage:
374
 *
375
 * `App::themePath('MyTheme'); will return the full path to the 'MyTheme' theme`
376
 *
377
 * @param string $theme theme name to find the path of.
378
 * @return string full path to the theme.
379
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::themePath
380
 */
381
        public static function themePath($theme) {
382
                $themeDir = 'Themed' . DS . Inflector::camelize($theme);
383
                foreach (static::$_packages['View'] as $path) {
384
                        if (is_dir($path . $themeDir)) {
385
                                return $path . $themeDir . DS;
386
                        }
387
                }
388
                return static::$_packages['View'][0] . $themeDir . DS;
389
        }
390

    
391
/**
392
 * Returns the full path to a package inside the CakePHP core
393
 *
394
 * Usage:
395
 *
396
 * `App::core('Cache/Engine'); will return the full path to the cache engines package`
397
 *
398
 * @param string $type Package type.
399
 * @return array full path to package
400
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::core
401
 */
402
        public static function core($type) {
403
                return array(CAKE . str_replace('/', DS, $type) . DS);
404
        }
405

    
406
/**
407
 * Returns an array of objects of the given type.
408
 *
409
 * Example usage:
410
 *
411
 * `App::objects('plugin');` returns `array('DebugKit', 'Blog', 'User');`
412
 *
413
 * `App::objects('Controller');` returns `array('PagesController', 'BlogController');`
414
 *
415
 * You can also search only within a plugin's objects by using the plugin dot
416
 * syntax.
417
 *
418
 * `App::objects('MyPlugin.Model');` returns `array('MyPluginPost', 'MyPluginComment');`
419
 *
420
 * When scanning directories, files and directories beginning with `.` will be excluded as these
421
 * are commonly used by version control systems.
422
 *
423
 * @param string $type Type of object, i.e. 'Model', 'Controller', 'View/Helper', 'file', 'class' or 'plugin'
424
 * @param string|array $path Optional Scan only the path given. If null, paths for the chosen type will be used.
425
 * @param bool $cache Set to false to rescan objects of the chosen type. Defaults to true.
426
 * @return mixed Either false on incorrect / miss. Or an array of found objects.
427
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::objects
428
 */
429
        public static function objects($type, $path = null, $cache = true) {
430
                if (empty(static::$_objects) && $cache === true) {
431
                        static::$_objects = (array)Cache::read('object_map', '_cake_core_');
432
                }
433

    
434
                $extension = '/\.php$/';
435
                $includeDirectories = false;
436
                $name = $type;
437

    
438
                if ($type === 'plugin') {
439
                        $type = 'plugins';
440
                }
441

    
442
                if ($type === 'plugins') {
443
                        $extension = '/.*/';
444
                        $includeDirectories = true;
445
                }
446

    
447
                list($plugin, $type) = pluginSplit($type);
448

    
449
                if (isset(static::$legacy[$type . 's'])) {
450
                        $type = static::$legacy[$type . 's'];
451
                }
452

    
453
                if ($type === 'file' && !$path) {
454
                        return false;
455
                } elseif ($type === 'file') {
456
                        $extension = '/\.php$/';
457
                        $name = $type . str_replace(DS, '', $path);
458
                }
459

    
460
                $cacheLocation = empty($plugin) ? 'app' : $plugin;
461

    
462
                if ($cache !== true || !isset(static::$_objects[$cacheLocation][$name])) {
463
                        $objects = array();
464

    
465
                        if (empty($path)) {
466
                                $path = static::path($type, $plugin);
467
                        }
468

    
469
                        foreach ((array)$path as $dir) {
470
                                if ($dir != APP && is_dir($dir)) {
471
                                        $files = new RegexIterator(new DirectoryIterator($dir), $extension);
472
                                        foreach ($files as $file) {
473
                                                $fileName = basename($file);
474
                                                if (!$file->isDot() && $fileName[0] !== '.') {
475
                                                        $isDir = $file->isDir();
476
                                                        if ($isDir && $includeDirectories) {
477
                                                                $objects[] = $fileName;
478
                                                        } elseif (!$includeDirectories && !$isDir) {
479
                                                                $objects[] = substr($fileName, 0, -4);
480
                                                        }
481
                                                }
482
                                        }
483
                                }
484
                        }
485

    
486
                        if ($type !== 'file') {
487
                                foreach ($objects as $key => $value) {
488
                                        $objects[$key] = Inflector::camelize($value);
489
                                }
490
                        }
491

    
492
                        sort($objects);
493
                        if ($plugin) {
494
                                return $objects;
495
                        }
496

    
497
                        static::$_objects[$cacheLocation][$name] = $objects;
498
                        if ($cache) {
499
                                static::$_objectCacheChange = true;
500
                        }
501
                }
502

    
503
                return static::$_objects[$cacheLocation][$name];
504
        }
505

    
506
/**
507
 * Declares a package for a class. This package location will be used
508
 * by the automatic class loader if the class is tried to be used
509
 *
510
 * Usage:
511
 *
512
 * `App::uses('MyCustomController', 'Controller');` will setup the class to be found under Controller package
513
 *
514
 * `App::uses('MyHelper', 'MyPlugin.View/Helper');` will setup the helper class to be found in plugin's helper package
515
 *
516
 * @param string $className the name of the class to configure package for
517
 * @param string $location the package name
518
 * @return void
519
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::uses
520
 */
521
        public static function uses($className, $location) {
522
                static::$_classMap[$className] = $location;
523
        }
524

    
525
/**
526
 * Method to handle the automatic class loading. It will look for each class' package
527
 * defined using App::uses() and with this information it will resolve the package name to a full path
528
 * to load the class from. File name for each class should follow the class name. For instance,
529
 * if a class is name `MyCustomClass` the file name should be `MyCustomClass.php`
530
 *
531
 * @param string $className the name of the class to load
532
 * @return bool
533
 */
534
        public static function load($className) {
535
                if (!isset(static::$_classMap[$className])) {
536
                        return false;
537
                }
538
                if (strpos($className, '..') !== false) {
539
                        return false;
540
                }
541

    
542
                $parts = explode('.', static::$_classMap[$className], 2);
543
                list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts));
544

    
545
                $file = static::_mapped($className, $plugin);
546
                if ($file) {
547
                        return include $file;
548
                }
549
                $paths = static::path($package, $plugin);
550

    
551
                if (empty($plugin)) {
552
                        $appLibs = empty(static::$_packages['Lib']) ? APPLIBS : current(static::$_packages['Lib']);
553
                        $paths[] = $appLibs . $package . DS;
554
                        $paths[] = APP . $package . DS;
555
                        $paths[] = CAKE . $package . DS;
556
                } else {
557
                        $pluginPath = CakePlugin::path($plugin);
558
                        $paths[] = $pluginPath . 'Lib' . DS . $package . DS;
559
                        $paths[] = $pluginPath . $package . DS;
560
                }
561

    
562
                $normalizedClassName = str_replace('\\', DS, $className);
563
                foreach ($paths as $path) {
564
                        $file = $path . $normalizedClassName . '.php';
565
                        if (file_exists($file)) {
566
                                static::_map($file, $className, $plugin);
567
                                return include $file;
568
                        }
569
                }
570

    
571
                return false;
572
        }
573

    
574
/**
575
 * Returns the package name where a class was defined to be located at
576
 *
577
 * @param string $className name of the class to obtain the package name from
578
 * @return string|null Package name, or null if not declared
579
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::location
580
 */
581
        public static function location($className) {
582
                if (!empty(static::$_classMap[$className])) {
583
                        return static::$_classMap[$className];
584
                }
585
                return null;
586
        }
587

    
588
/**
589
 * Finds classes based on $name or specific file(s) to search. Calling App::import() will
590
 * not construct any classes contained in the files. It will only find and require() the file.
591
 *
592
 * @param string|array $type The type of Class if passed as a string, or all params can be passed as
593
 *   a single array to $type.
594
 * @param string $name Name of the Class or a unique name for the file
595
 * @param bool|array $parent boolean true if Class Parent should be searched, accepts key => value
596
 *   array('parent' => $parent, 'file' => $file, 'search' => $search, 'ext' => '$ext');
597
 *   $ext allows setting the extension of the file name
598
 *   based on Inflector::underscore($name) . ".$ext";
599
 * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3');
600
 * @param string $file full name of the file to search for including extension
601
 * @param bool $return Return the loaded file, the file must have a return
602
 *   statement in it to work: return $variable;
603
 * @return bool true if Class is already in memory or if file is found and loaded, false if not
604
 * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#including-files-with-app-import
605
 */
606
        public static function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) {
607
                $ext = null;
608

    
609
                if (is_array($type)) {
610
                        extract($type, EXTR_OVERWRITE);
611
                }
612

    
613
                if (is_array($parent)) {
614
                        extract($parent, EXTR_OVERWRITE);
615
                }
616

    
617
                if (!$name && !$file) {
618
                        return false;
619
                }
620

    
621
                if (is_array($name)) {
622
                        foreach ($name as $class) {
623
                                if (!App::import(compact('type', 'parent', 'search', 'file', 'return') + array('name' => $class))) {
624
                                        return false;
625
                                }
626
                        }
627
                        return true;
628
                }
629

    
630
                $originalType = strtolower($type);
631
                $specialPackage = in_array($originalType, array('file', 'vendor'));
632
                if (!$specialPackage && isset(static::$legacy[$originalType . 's'])) {
633
                        $type = static::$legacy[$originalType . 's'];
634
                }
635
                list($plugin, $name) = pluginSplit($name);
636
                if (!empty($plugin)) {
637
                        if (!CakePlugin::loaded($plugin)) {
638
                                return false;
639
                        }
640
                }
641

    
642
                if (!$specialPackage) {
643
                        return static::_loadClass($name, $plugin, $type, $originalType, $parent);
644
                }
645

    
646
                if ($originalType === 'file' && !empty($file)) {
647
                        return static::_loadFile($name, $plugin, $search, $file, $return);
648
                }
649

    
650
                if ($originalType === 'vendor') {
651
                        return static::_loadVendor($name, $plugin, $file, $ext);
652
                }
653

    
654
                return false;
655
        }
656

    
657
/**
658
 * Helper function to include classes
659
 * This is a compatibility wrapper around using App::uses() and automatic class loading
660
 *
661
 * @param string $name unique name of the file for identifying it inside the application
662
 * @param string $plugin camel cased plugin name if any
663
 * @param string $type name of the packed where the class is located
664
 * @param string $originalType type name as supplied initially by the user
665
 * @param bool $parent whether to load the class parent or not
666
 * @return bool true indicating the successful load and existence of the class
667
 */
668
        protected static function _loadClass($name, $plugin, $type, $originalType, $parent) {
669
                if ($type === 'Console/Command' && $name === 'Shell') {
670
                        $type = 'Console';
671
                } elseif (isset(static::$types[$originalType]['suffix'])) {
672
                        $suffix = static::$types[$originalType]['suffix'];
673
                        $name .= ($suffix === $name) ? '' : $suffix;
674
                }
675
                if ($parent && isset(static::$types[$originalType]['extends'])) {
676
                        $extends = static::$types[$originalType]['extends'];
677
                        $extendType = $type;
678
                        if (strpos($extends, '/') !== false) {
679
                                $parts = explode('/', $extends);
680
                                $extends = array_pop($parts);
681
                                $extendType = implode('/', $parts);
682
                        }
683
                        App::uses($extends, $extendType);
684
                        if ($plugin && in_array($originalType, array('controller', 'model'))) {
685
                                App::uses($plugin . $extends, $plugin . '.' . $type);
686
                        }
687
                }
688
                if ($plugin) {
689
                        $plugin .= '.';
690
                }
691
                $name = Inflector::camelize($name);
692
                App::uses($name, $plugin . $type);
693
                return class_exists($name);
694
        }
695

    
696
/**
697
 * Helper function to include single files
698
 *
699
 * @param string $name unique name of the file for identifying it inside the application
700
 * @param string $plugin camel cased plugin name if any
701
 * @param array $search list of paths to search the file into
702
 * @param string $file filename if known, the $name param will be used otherwise
703
 * @param bool $return whether this function should return the contents of the file after being parsed by php or just a success notice
704
 * @return mixed if $return contents of the file after php parses it, boolean indicating success otherwise
705
 */
706
        protected static function _loadFile($name, $plugin, $search, $file, $return) {
707
                $mapped = static::_mapped($name, $plugin);
708
                if ($mapped) {
709
                        $file = $mapped;
710
                } elseif (!empty($search)) {
711
                        foreach ($search as $path) {
712
                                $found = false;
713
                                if (file_exists($path . $file)) {
714
                                        $file = $path . $file;
715
                                        $found = true;
716
                                        break;
717
                                }
718
                                if (empty($found)) {
719
                                        $file = false;
720
                                }
721
                        }
722
                }
723
                if (!empty($file) && file_exists($file)) {
724
                        static::_map($file, $name, $plugin);
725
                        $returnValue = include $file;
726
                        if ($return) {
727
                                return $returnValue;
728
                        }
729
                        return (bool)$returnValue;
730
                }
731
                return false;
732
        }
733

    
734
/**
735
 * Helper function to load files from vendors folders
736
 *
737
 * @param string $name unique name of the file for identifying it inside the application
738
 * @param string $plugin camel cased plugin name if any
739
 * @param string $file file name if known
740
 * @param string $ext file extension if known
741
 * @return bool true if the file was loaded successfully, false otherwise
742
 */
743
        protected static function _loadVendor($name, $plugin, $file, $ext) {
744
                if ($mapped = static::_mapped($name, $plugin)) {
745
                        return (bool)include_once $mapped;
746
                }
747
                $fileTries = array();
748
                $paths = ($plugin) ? App::path('vendors', $plugin) : App::path('vendors');
749
                if (empty($ext)) {
750
                        $ext = 'php';
751
                }
752
                if (empty($file)) {
753
                        $fileTries[] = $name . '.' . $ext;
754
                        $fileTries[] = Inflector::underscore($name) . '.' . $ext;
755
                } else {
756
                        $fileTries[] = $file;
757
                }
758

    
759
                foreach ($fileTries as $file) {
760
                        foreach ($paths as $path) {
761
                                if (file_exists($path . $file)) {
762
                                        static::_map($path . $file, $name, $plugin);
763
                                        return (bool)include $path . $file;
764
                                }
765
                        }
766
                }
767
                return false;
768
        }
769

    
770
/**
771
 * Initializes the cache for App, registers a shutdown function.
772
 *
773
 * @return void
774
 */
775
        public static function init() {
776
                static::$_map += (array)Cache::read('file_map', '_cake_core_');
777
                register_shutdown_function(array('App', 'shutdown'));
778
        }
779

    
780
/**
781
 * Maps the $name to the $file.
782
 *
783
 * @param string $file full path to file
784
 * @param string $name unique name for this map
785
 * @param string $plugin camelized if object is from a plugin, the name of the plugin
786
 * @return void
787
 */
788
        protected static function _map($file, $name, $plugin = null) {
789
                $key = $name;
790
                if ($plugin) {
791
                        $key = 'plugin.' . $name;
792
                }
793
                if ($plugin && empty(static::$_map[$name])) {
794
                        static::$_map[$key] = $file;
795
                }
796
                if (!$plugin && empty(static::$_map['plugin.' . $name])) {
797
                        static::$_map[$key] = $file;
798
                }
799
                if (!static::$bootstrapping) {
800
                        static::$_cacheChange = true;
801
                }
802
        }
803

    
804
/**
805
 * Returns a file's complete path.
806
 *
807
 * @param string $name unique name
808
 * @param string $plugin camelized if object is from a plugin, the name of the plugin
809
 * @return mixed file path if found, false otherwise
810
 */
811
        protected static function _mapped($name, $plugin = null) {
812
                $key = $name;
813
                if ($plugin) {
814
                        $key = 'plugin.' . $name;
815
                }
816
                return isset(static::$_map[$key]) ? static::$_map[$key] : false;
817
        }
818

    
819
/**
820
 * Sets then returns the templates for each customizable package path
821
 *
822
 * @return array templates for each customizable package path
823
 */
824
        protected static function _packageFormat() {
825
                if (empty(static::$_packageFormat)) {
826
                        static::$_packageFormat = array(
827
                                'Model' => array(
828
                                        '%s' . 'Model' . DS
829
                                ),
830
                                'Model/Behavior' => array(
831
                                        '%s' . 'Model' . DS . 'Behavior' . DS
832
                                ),
833
                                'Model/Datasource' => array(
834
                                        '%s' . 'Model' . DS . 'Datasource' . DS
835
                                ),
836
                                'Model/Datasource/Database' => array(
837
                                        '%s' . 'Model' . DS . 'Datasource' . DS . 'Database' . DS
838
                                ),
839
                                'Model/Datasource/Session' => array(
840
                                        '%s' . 'Model' . DS . 'Datasource' . DS . 'Session' . DS
841
                                ),
842
                                'Controller' => array(
843
                                        '%s' . 'Controller' . DS
844
                                ),
845
                                'Controller/Component' => array(
846
                                        '%s' . 'Controller' . DS . 'Component' . DS
847
                                ),
848
                                'Controller/Component/Auth' => array(
849
                                        '%s' . 'Controller' . DS . 'Component' . DS . 'Auth' . DS
850
                                ),
851
                                'Controller/Component/Acl' => array(
852
                                        '%s' . 'Controller' . DS . 'Component' . DS . 'Acl' . DS
853
                                ),
854
                                'View' => array(
855
                                        '%s' . 'View' . DS
856
                                ),
857
                                'View/Helper' => array(
858
                                        '%s' . 'View' . DS . 'Helper' . DS
859
                                ),
860
                                'Console' => array(
861
                                        '%s' . 'Console' . DS
862
                                ),
863
                                'Console/Command' => array(
864
                                        '%s' . 'Console' . DS . 'Command' . DS
865
                                ),
866
                                'Console/Command/Task' => array(
867
                                        '%s' . 'Console' . DS . 'Command' . DS . 'Task' . DS
868
                                ),
869
                                'Lib' => array(
870
                                        '%s' . 'Lib' . DS
871
                                ),
872
                                'Locale' => array(
873
                                        '%s' . 'Locale' . DS
874
                                ),
875
                                'Vendor' => array(
876
                                        '%s' . 'Vendor' . DS,
877
                                        ROOT . DS . 'vendors' . DS,
878
                                        dirname(dirname(CAKE)) . DS . 'vendors' . DS
879
                                ),
880
                                'Plugin' => array(
881
                                        APP . 'Plugin' . DS,
882
                                        ROOT . DS . 'plugins' . DS,
883
                                        dirname(dirname(CAKE)) . DS . 'plugins' . DS
884
                                )
885
                        );
886
                }
887

    
888
                return static::$_packageFormat;
889
        }
890

    
891
/**
892
 * Object destructor.
893
 *
894
 * Writes cache file if changes have been made to the $_map. Also, check if a fatal
895
 * error happened and call the handler.
896
 *
897
 * @return void
898
 */
899
        public static function shutdown() {
900
                if (static::$_cacheChange) {
901
                        Cache::write('file_map', array_filter(static::$_map), '_cake_core_');
902
                }
903
                if (static::$_objectCacheChange) {
904
                        Cache::write('object_map', static::$_objects, '_cake_core_');
905
                }
906
                static::_checkFatalError();
907
        }
908

    
909
/**
910
 * Check if a fatal error happened and trigger the configured handler if configured
911
 *
912
 * @return void
913
 */
914
        protected static function _checkFatalError() {
915
                $lastError = error_get_last();
916
                if (!is_array($lastError)) {
917
                        return;
918
                }
919

    
920
                list(, $log) = ErrorHandler::mapErrorCode($lastError['type']);
921
                if ($log !== LOG_ERR) {
922
                        return;
923
                }
924

    
925
                if (PHP_SAPI === 'cli') {
926
                        $errorHandler = Configure::read('Error.consoleHandler');
927
                } else {
928
                        $errorHandler = Configure::read('Error.handler');
929
                }
930
                if (!is_callable($errorHandler)) {
931
                        return;
932
                }
933
                call_user_func($errorHandler, $lastError['type'], $lastError['message'], $lastError['file'], $lastError['line'], array());
934
        }
935

    
936
}