Skip to content
Newer
Older
100644 300 lines (274 sloc) 8.16 KB
b895171 @fabpot moved the class loader to its own component
fabpot authored
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
0364560 @fabpot replaced symfony-project.org by symfony.com
fabpot authored
6 * (c) Fabien Potencier <fabien@symfony.com>
b895171 @fabpot moved the class loader to its own component
fabpot authored
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\ClassLoader;
13
14 /**
15 * UniversalClassLoader implements a "universal" autoloader for PHP 5.3.
16 *
17 * It is able to load classes that use either:
18 *
19 * * The technical interoperability standards for PHP 5.3 namespaces and
20 * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal);
21 *
22 * * The PEAR naming convention for classes (http://pear.php.net/).
23 *
24 * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
25 * looked for in a list of locations to ease the vendoring of a sub-set of
26 * classes for large projects.
27 *
28 * Example usage:
29 *
30 * $loader = new UniversalClassLoader();
31 *
32 * // register classes with namespaces
33 * $loader->registerNamespaces(array(
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
34 * 'Symfony\Component' => __DIR__.'/component',
35 * 'Symfony' => __DIR__.'/framework',
36 * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
b895171 @fabpot moved the class loader to its own component
fabpot authored
37 * ));
38 *
39 * // register a library using the PEAR naming convention
40 * $loader->registerPrefixes(array(
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
41 * 'Swift_' => __DIR__.'/Swift',
b895171 @fabpot moved the class loader to its own component
fabpot authored
42 * ));
43 *
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
44 *
45 * // to enable searching the include path (eg. for PEAR packages)
46 * $loader->useIncludePath(true);
47 *
b895171 @fabpot moved the class loader to its own component
fabpot authored
48 * // activate the autoloader
49 * $loader->register();
50 *
51 * In this example, if you try to use a class in the Symfony\Component
52 * namespace or one of its children (Symfony\Component\Console for instance),
53 * the autoloader will first look for the class under the component/
54 * directory, and it will then fallback to the framework/ directory if not
55 * found before giving up.
56 *
0364560 @fabpot replaced symfony-project.org by symfony.com
fabpot authored
57 * @author Fabien Potencier <fabien@symfony.com>
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
58 *
59 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
60 */
80862ea @fabpot [ClassLoader] removed ClassLoaderInterface
fabpot authored
61 class UniversalClassLoader
b895171 @fabpot moved the class loader to its own component
fabpot authored
62 {
a1dbe36 @fabpot [ClassLoader] moved most protected methods and properties to private
fabpot authored
63 private $namespaces = array();
64 private $prefixes = array();
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
65 private $namespaceFallbacks = array();
66 private $prefixFallbacks = array();
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
67 private $useIncludePath = false;
68
69 /**
70 * Turns on searching the include for class files. Allows easy loading
71 * of installed PEAR packages
72 *
73 * @param Boolean $useIncludePath
74 */
75 public function useIncludePath($useIncludePath)
76 {
77 $this->useIncludePath = $useIncludePath;
78 }
79
80 /**
81 * Can be used to check if the autoloader uses the include path to check
82 * for classes.
83 *
84 * @return Boolean
85 */
86 public function getUseIncludePath()
87 {
88 return $this->useIncludePath;
89 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
90
91 /**
92 * Gets the configured namespaces.
93 *
94 * @return array A hash with namespaces as keys and directories as values
95 */
96 public function getNamespaces()
97 {
98 return $this->namespaces;
99 }
100
101 /**
102 * Gets the configured class prefixes.
103 *
104 * @return array A hash with class prefixes as keys and directories as values
105 */
106 public function getPrefixes()
107 {
108 return $this->prefixes;
109 }
110
111 /**
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
112 * Gets the directory(ies) to use as a fallback for namespaces.
b895171 @fabpot moved the class loader to its own component
fabpot authored
113 *
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
114 * @return array An array of directories
b895171 @fabpot moved the class loader to its own component
fabpot authored
115 */
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
116 public function getNamespaceFallbacks()
b895171 @fabpot moved the class loader to its own component
fabpot authored
117 {
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
118 return $this->namespaceFallbacks;
b895171 @fabpot moved the class loader to its own component
fabpot authored
119 }
120
121 /**
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
122 * Gets the directory(ies) to use as a fallback for class prefixes.
b895171 @fabpot moved the class loader to its own component
fabpot authored
123 *
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
124 * @return array An array of directories
b895171 @fabpot moved the class loader to its own component
fabpot authored
125 */
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
126 public function getPrefixFallbacks()
b895171 @fabpot moved the class loader to its own component
fabpot authored
127 {
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
128 return $this->prefixFallbacks;
b895171 @fabpot moved the class loader to its own component
fabpot authored
129 }
130
131 /**
132 * Registers the directory to use as a fallback for namespaces.
133 *
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
134 * @param array $dirs An array of directories
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
135 *
136 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
137 */
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
138 public function registerNamespaceFallbacks(array $dirs)
b895171 @fabpot moved the class loader to its own component
fabpot authored
139 {
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
140 $this->namespaceFallbacks = $dirs;
b895171 @fabpot moved the class loader to its own component
fabpot authored
141 }
142
143 /**
144 * Registers the directory to use as a fallback for class prefixes.
145 *
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
146 * @param array $dirs An array of directories
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
147 *
148 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
149 */
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
150 public function registerPrefixFallbacks(array $dirs)
b895171 @fabpot moved the class loader to its own component
fabpot authored
151 {
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
152 $this->prefixFallbacks = $dirs;
b895171 @fabpot moved the class loader to its own component
fabpot authored
153 }
154
155 /**
156 * Registers an array of namespaces
157 *
158 * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
159 *
160 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
161 */
162 public function registerNamespaces(array $namespaces)
163 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
164 foreach ($namespaces as $namespace => $locations) {
165 $this->namespaces[$namespace] = (array) $locations;
166 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
167 }
168
169 /**
170 * Registers a namespace.
171 *
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
172 * @param string $namespace The namespace
173 * @param array|string $paths The location(s) of the namespace
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
174 *
175 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
176 */
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
177 public function registerNamespace($namespace, $paths)
b895171 @fabpot moved the class loader to its own component
fabpot authored
178 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
179 $this->namespaces[$namespace] = (array) $paths;
b895171 @fabpot moved the class loader to its own component
fabpot authored
180 }
181
182 /**
183 * Registers an array of classes using the PEAR naming convention.
184 *
185 * @param array $classes An array of classes (prefixes as keys and locations as values)
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
186 *
187 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
188 */
189 public function registerPrefixes(array $classes)
190 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
191 foreach ($classes as $prefix => $locations) {
192 $this->prefixes[$prefix] = (array) $locations;
193 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
194 }
195
196 /**
197 * Registers a set of classes using the PEAR naming convention.
198 *
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
199 * @param string $prefix The classes prefix
200 * @param array|string $paths The location(s) of the classes
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
201 *
202 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
203 */
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
204 public function registerPrefix($prefix, $paths)
b895171 @fabpot moved the class loader to its own component
fabpot authored
205 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
206 $this->prefixes[$prefix] = (array) $paths;
b895171 @fabpot moved the class loader to its own component
fabpot authored
207 }
208
209 /**
210 * Registers this instance as an autoloader.
211 *
212 * @param Boolean $prepend Whether to prepend the autoloader or not
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
213 *
214 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
215 */
216 public function register($prepend = false)
217 {
218 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
219 }
220
221 /**
222 * Loads the given class or interface.
223 *
224 * @param string $class The name of the class
225 */
226 public function loadClass($class)
227 {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
228 if ($file = $this->findFile($class)) {
229 require $file;
230 }
231 }
232
233 /**
234 * Finds the path to the file where the class is defined.
235 *
236 * @param string $class The name of the class
237 *
238 * @return string|null The path, if found
239 */
0091d0e @fabpot [ClassLoader] added ClassLoaderInterface
fabpot authored
240 public function findFile($class)
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
241 {
7567a77 @kriswallsmith [ClassLoader] added a check before trimming the leading \
kriswallsmith authored
242 if ('\\' == $class[0]) {
243 $class = substr($class, 1);
244 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
245
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
246 if (false !== $pos = strrpos($class, '\\')) {
b895171 @fabpot moved the class loader to its own component
fabpot authored
247 // namespaced class name
248 $namespace = substr($class, 0, $pos);
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
249 $className = substr($class, $pos + 1);
250 $normalizedClass = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
251 foreach ($this->namespaces as $ns => $dirs) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
252 if (0 !== strpos($namespace, $ns)) {
253 continue;
254 }
255
256 foreach ($dirs as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
257 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
258 if (file_exists($file)) {
259 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
260 }
261 }
262 }
263
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
264 foreach ($this->namespaceFallbacks as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
265 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
b895171 @fabpot moved the class loader to its own component
fabpot authored
266 if (file_exists($file)) {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
267 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
268 }
269 }
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
270
b895171 @fabpot moved the class loader to its own component
fabpot authored
271 } else {
272 // PEAR-like class name
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
273 $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
274 foreach ($this->prefixes as $prefix => $dirs) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
275 if (0 !== strpos($class, $prefix)) {
276 continue;
277 }
278
279 foreach ($dirs as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
280 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
281 if (file_exists($file)) {
282 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
283 }
284 }
285 }
286
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
287 foreach ($this->prefixFallbacks as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
288 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
b895171 @fabpot moved the class loader to its own component
fabpot authored
289 if (file_exists($file)) {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
290 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
291 }
292 }
293 }
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
294
295 if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) {
296 return $file;
297 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
298 }
299 }
Something went wrong with that request. Please try again.