[BUGFIX] Caching framework: Reduce code duplication in db backend
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_autoloader.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2008-2011 Dmitry Dulepov <dmitry@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Contains TYPO3 autoloader
29 *
30 * @author Dmitry Dulepov <dmitry@typo3.org>
31 * @author Martin Kutschker <masi@typo3.org>
32 * @author Oliver Hader <oliver@typo3.org>
33 * @author Sebastian Kurf├╝rst <sebastian@typo3.org>
34 */
35
36 /**
37 * This class contains TYPO3 autoloader for classes.
38 * It handles:
39 * - the core of TYPO3
40 * - all extensions with an ext_autoload.php file
41 */
42 class t3lib_autoloader {
43
44 /**
45 * Class name to file mapping. Key: class name. Value: fully qualified file name.
46 *
47 * @var array
48 */
49 protected static $classNameToFileMapping = array();
50
51 /**
52 * Associative array which sets for each extension which was attempted to load if it has an autoload configuration
53 *
54 * Key: extension key
55 * Value: TRUE, if extension has an ext_autoload.php and this is already part of $classNameToFileMapping
56 * FALSE, if extension has no ext_autoload.php
57 *
58 * @var array
59 */
60 protected static $extensionHasAutoloadConfiguration = array();
61
62 /**
63 * The autoloader is static, thus we do not allow instances of this class.
64 */
65 private function __construct() {
66 }
67
68 /**
69 * Installs TYPO3 autoloader, and loads the autoload registry for the core.
70 *
71 * @return boolean TRUE in case of success
72 */
73 static public function registerAutoloader() {
74 self::loadCoreRegistry();
75 self::$extensionHasAutoloadConfiguration = array();
76 return spl_autoload_register('t3lib_autoloader::autoload');
77 }
78
79 /**
80 * Uninstalls TYPO3 autoloader. This function is for the sake of completeness.
81 * It is never called by the TYPO3 core.
82 *
83 * @return boolean TRUE in case of success
84 */
85 static public function unregisterAutoloader() {
86 return spl_autoload_unregister('t3lib_autoloader::autoload');
87 }
88
89 /**
90 * Autoload function for TYPO3.
91 *
92 * This method looks up class names in the registry
93 * (which contains extensions and core files)
94 *
95 * @param string $className Class name
96 * @return void
97 */
98 static public function autoload($className) {
99 $classPath = FALSE;
100
101 // use core and extension registry
102 $classPath = self::getClassPathByRegistryLookup($className);
103
104 if ($classPath && file_exists($classPath)) {
105 t3lib_div::requireFile($classPath);
106 } else {
107 try {
108 // Regular expression for a valid classname taken from
109 // http://www.php.net/manual/en/language.oop5.basic.php
110 if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $className)) {
111 spl_autoload($className);
112 }
113 } catch (LogicException $exception) {
114 }
115 }
116 }
117
118 /**
119 * Load the core registry into $classNameToFileMapping, effectively overriding
120 * the whole contents of $classNameToFileMapping.
121 *
122 * @return void
123 */
124 static protected function loadCoreRegistry() {
125 self::$classNameToFileMapping = require(PATH_t3lib . 'core_autoload.php');
126 }
127
128 /**
129 * Get the full path to a class by looking it up in the registry. If not found, returns NULL.
130 *
131 * @param string $className Class name
132 * @return string full name of the file where $className is declared, or NULL if no entry found in registry.
133 */
134 static protected function getClassPathByRegistryLookup($className) {
135 $className = strtolower($className);
136 if (!array_key_exists($className, self::$classNameToFileMapping)) {
137 self::attemptToLoadRegistryForGivenClassName($className);
138 }
139 if (array_key_exists($className, self::$classNameToFileMapping)) {
140 return self::$classNameToFileMapping[$className];
141 } else {
142 return NULL;
143 }
144 }
145
146 /**
147 * Try to load the entries for a given class name into the registry.
148 *
149 * First, figures out the extension the class belongs to.
150 * Then, tries to load the ext_autoload.php file inside the extension directory, and adds its contents to the $classNameToFileMapping.
151 *
152 * @param string $className Class Name
153 */
154 static protected function attemptToLoadRegistryForGivenClassName($className) {
155 $classNameParts = explode('_', $className);
156 $extensionPrefix = array_shift($classNameParts) . '_' . array_shift($classNameParts);
157 $extensionKey = t3lib_extMgm::getExtensionKeyByPrefix($extensionPrefix);
158
159 if (!$extensionKey || array_key_exists($extensionKey, self::$extensionHasAutoloadConfiguration)) {
160 // extension key could not be determined or we already tried to load the extension's autoload configuration
161 return;
162 }
163 $possibleAutoloadConfigurationFileName = t3lib_extMgm::extPath($extensionKey) . 'ext_autoload.php';
164 if (file_exists($possibleAutoloadConfigurationFileName)) {
165 self::$extensionHasAutoloadConfiguration[$extensionKey] = TRUE;
166 $extensionClassNameToFileMapping = require($possibleAutoloadConfigurationFileName);
167 self::$classNameToFileMapping = array_merge($extensionClassNameToFileMapping, self::$classNameToFileMapping);
168 } else {
169 self::$extensionHasAutoloadConfiguration[$extensionKey] = FALSE;
170 }
171 }
172 }
173 ?>