Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 324 lines (295 sloc) 8.89 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
1c05511 [ClassLoader] Update PSR-0 reference.
Drak authored
20 * class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
b895171 @fabpot moved the class loader to its own component
fabpot authored
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 *
4e509e3 @gajdaw [2.1][Component][ClassLoader] cs
gajdaw authored
45 * // to enable searching the include path (e.g. for PEAR packages)
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
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 /**
3200473 [ClassLoader] Add ability to incrementally register fallbacks.
Drak authored
144 * Registers a directory to use as a fallback for namespaces.
145 *
146 * @param string $dir A directory
147 */
148 public function registerNamespaceFallback($dir)
149 {
150 $this->namespaceFallbacks[] = $dir;
151 }
152
153 /**
154 * Registers directories to use as a fallback for class prefixes.
b895171 @fabpot moved the class loader to its own component
fabpot authored
155 *
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
156 * @param array $dirs An array of directories
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
157 *
158 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
159 */
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
160 public function registerPrefixFallbacks(array $dirs)
b895171 @fabpot moved the class loader to its own component
fabpot authored
161 {
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
162 $this->prefixFallbacks = $dirs;
b895171 @fabpot moved the class loader to its own component
fabpot authored
163 }
164
165 /**
3200473 [ClassLoader] Add ability to incrementally register fallbacks.
Drak authored
166 * Registers a directory to use as a fallback for class prefixes.
167 *
168 * @param string $dir A directory
169 */
170 public function registerPrefixFallback($dir)
171 {
172 $this->prefixFallbacks[] = $dir;
173 }
174
175 /**
b895171 @fabpot moved the class loader to its own component
fabpot authored
176 * Registers an array of namespaces
177 *
178 * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
179 *
180 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
181 */
182 public function registerNamespaces(array $namespaces)
183 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
184 foreach ($namespaces as $namespace => $locations) {
185 $this->namespaces[$namespace] = (array) $locations;
186 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
187 }
188
189 /**
190 * Registers a namespace.
191 *
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
192 * @param string $namespace The namespace
193 * @param array|string $paths The location(s) of the namespace
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
194 *
195 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
196 */
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
197 public function registerNamespace($namespace, $paths)
b895171 @fabpot moved the class loader to its own component
fabpot authored
198 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
199 $this->namespaces[$namespace] = (array) $paths;
b895171 @fabpot moved the class loader to its own component
fabpot authored
200 }
201
202 /**
203 * Registers an array of classes using the PEAR naming convention.
204 *
205 * @param array $classes An array of classes (prefixes as keys and locations as values)
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
206 *
207 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
208 */
209 public function registerPrefixes(array $classes)
210 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
211 foreach ($classes as $prefix => $locations) {
212 $this->prefixes[$prefix] = (array) $locations;
213 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
214 }
215
216 /**
217 * Registers a set of classes using the PEAR naming convention.
218 *
6329e84 @gajdaw [2.0][Component][ClassLoader] cs
gajdaw authored
219 * @param string $prefix The classes prefix
220 * @param array|string $paths The location(s) of the classes
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
221 *
222 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
223 */
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
224 public function registerPrefix($prefix, $paths)
b895171 @fabpot moved the class loader to its own component
fabpot authored
225 {
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
226 $this->prefixes[$prefix] = (array) $paths;
b895171 @fabpot moved the class loader to its own component
fabpot authored
227 }
228
229 /**
230 * Registers this instance as an autoloader.
231 *
232 * @param Boolean $prepend Whether to prepend the autoloader or not
250f88a @fabpot [CssSelector] tagged thlassLoader]d BC API
fabpot authored
233 *
234 * @api
b895171 @fabpot moved the class loader to its own component
fabpot authored
235 */
236 public function register($prepend = false)
237 {
238 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
239 }
240
241 /**
242 * Loads the given class or interface.
243 *
244 * @param string $class The name of the class
f291c7b @szicsu FIX [2.1][ClassLoader]UniversalClassLoader not working with Annotatio…
szicsu authored
245 *
246 * @return Boolean|null True, if loaded
b895171 @fabpot moved the class loader to its own component
fabpot authored
247 */
248 public function loadClass($class)
249 {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
250 if ($file = $this->findFile($class)) {
251 require $file;
f291c7b @szicsu FIX [2.1][ClassLoader]UniversalClassLoader not working with Annotatio…
szicsu authored
252
253 return true;
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
254 }
255 }
256
257 /**
258 * Finds the path to the file where the class is defined.
259 *
260 * @param string $class The name of the class
261 *
262 * @return string|null The path, if found
263 */
0091d0e @fabpot [ClassLoader] added ClassLoaderInterface
fabpot authored
264 public function findFile($class)
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
265 {
7567a77 @kriswallsmith [ClassLoader] added a check before trimming the leading \
kriswallsmith authored
266 if ('\\' == $class[0]) {
267 $class = substr($class, 1);
268 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
269
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
270 if (false !== $pos = strrpos($class, '\\')) {
b895171 @fabpot moved the class loader to its own component
fabpot authored
271 // namespaced class name
272 $namespace = substr($class, 0, $pos);
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
273 $className = substr($class, $pos + 1);
274 $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
275 foreach ($this->namespaces as $ns => $dirs) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
276 if (0 !== strpos($namespace, $ns)) {
277 continue;
278 }
279
280 foreach ($dirs as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
281 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
c6336b8 @fabpot converted file_exists calls to either is_file or is_dir where it make…
fabpot authored
282 if (is_file($file)) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
283 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
284 }
285 }
286 }
287
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
288 foreach ($this->namespaceFallbacks as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
289 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
c6336b8 @fabpot converted file_exists calls to either is_file or is_dir where it make…
fabpot authored
290 if (is_file($file)) {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
291 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
292 }
293 }
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
294
b895171 @fabpot moved the class loader to its own component
fabpot authored
295 } else {
296 // PEAR-like class name
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
297 $normalizedClass = str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
6a144c7 @fabpot [ClassLoader] added the possibility to define more than one directory…
fabpot authored
298 foreach ($this->prefixes as $prefix => $dirs) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
299 if (0 !== strpos($class, $prefix)) {
300 continue;
301 }
302
303 foreach ($dirs as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
304 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
c6336b8 @fabpot converted file_exists calls to either is_file or is_dir where it make…
fabpot authored
305 if (is_file($file)) {
33066c1 @fabpot [ClassLoader] fixed CS
fabpot authored
306 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
307 }
308 }
309 }
310
fc449bc @fabpot renamed some UniversalClassLoader for better consistency
fabpot authored
311 foreach ($this->prefixFallbacks as $dir) {
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
312 $file = $dir.DIRECTORY_SEPARATOR.$normalizedClass;
c6336b8 @fabpot converted file_exists calls to either is_file or is_dir where it make…
fabpot authored
313 if (is_file($file)) {
608bce3 @kriswallsmith [ClassLoader] created protected findFile() method to allow creating a…
kriswallsmith authored
314 return $file;
b895171 @fabpot moved the class loader to its own component
fabpot authored
315 }
316 }
317 }
d7b4565 @henrikbjorn [ClassLoader] Support for autoloading include_path incl. tests.
henrikbjorn authored
318
319 if ($this->useIncludePath && $file = stream_resolve_include_path($normalizedClass)) {
320 return $file;
321 }
b895171 @fabpot moved the class loader to its own component
fabpot authored
322 }
323 }
Something went wrong with that request. Please try again.