- Patch #532512 by Gábor Hojtsy, andypost, no_commit_credit: fixed Plural string...
[project/drupal.git] / core / vendor / Symfony / Component / ClassLoader / UniversalClassLoader.php
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
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 (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
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(
34 * 'Symfony\Component' => __DIR__.'/component',
35 * 'Symfony' => __DIR__.'/framework',
36 * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'),
37 * ));
38 *
39 * // register a library using the PEAR naming convention
40 * $loader->registerPrefixes(array(
41 * 'Swift_' => __DIR__.'/Swift',
42 * ));
43 *
44 * // activate the autoloader
45 * $loader->register();
46 *
47 * In this example, if you try to use a class in the Symfony\Component
48 * namespace or one of its children (Symfony\Component\Console for instance),
49 * the autoloader will first look for the class under the component/
50 * directory, and it will then fallback to the framework/ directory if not
51 * found before giving up.
52 *
53 * @author Fabien Potencier <fabien@symfony.com>
54 *
55 * @api
56 */
57 class UniversalClassLoader
58 {
59 private $namespaces = array();
60 private $prefixes = array();
61 private $namespaceFallbacks = array();
62 private $prefixFallbacks = array();
63
64 /**
65 * Gets the configured namespaces.
66 *
67 * @return array A hash with namespaces as keys and directories as values
68 */
69 public function getNamespaces()
70 {
71 return $this->namespaces;
72 }
73
74 /**
75 * Gets the configured class prefixes.
76 *
77 * @return array A hash with class prefixes as keys and directories as values
78 */
79 public function getPrefixes()
80 {
81 return $this->prefixes;
82 }
83
84 /**
85 * Gets the directory(ies) to use as a fallback for namespaces.
86 *
87 * @return array An array of directories
88 */
89 public function getNamespaceFallbacks()
90 {
91 return $this->namespaceFallbacks;
92 }
93
94 /**
95 * Gets the directory(ies) to use as a fallback for class prefixes.
96 *
97 * @return array An array of directories
98 */
99 public function getPrefixFallbacks()
100 {
101 return $this->prefixFallbacks;
102 }
103
104 /**
105 * Registers the directory to use as a fallback for namespaces.
106 *
107 * @param array $dirs An array of directories
108 *
109 * @api
110 */
111 public function registerNamespaceFallbacks(array $dirs)
112 {
113 $this->namespaceFallbacks = $dirs;
114 }
115
116 /**
117 * Registers the directory to use as a fallback for class prefixes.
118 *
119 * @param array $dirs An array of directories
120 *
121 * @api
122 */
123 public function registerPrefixFallbacks(array $dirs)
124 {
125 $this->prefixFallbacks = $dirs;
126 }
127
128 /**
129 * Registers an array of namespaces
130 *
131 * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
132 *
133 * @api
134 */
135 public function registerNamespaces(array $namespaces)
136 {
137 foreach ($namespaces as $namespace => $locations) {
138 $this->namespaces[$namespace] = (array) $locations;
139 }
140 }
141
142 /**
143 * Registers a namespace.
144 *
145 * @param string $namespace The namespace
146 * @param array|string $paths The location(s) of the namespace
147 *
148 * @api
149 */
150 public function registerNamespace($namespace, $paths)
151 {
152 $this->namespaces[$namespace] = (array) $paths;
153 }
154
155 /**
156 * Registers an array of classes using the PEAR naming convention.
157 *
158 * @param array $classes An array of classes (prefixes as keys and locations as values)
159 *
160 * @api
161 */
162 public function registerPrefixes(array $classes)
163 {
164 foreach ($classes as $prefix => $locations) {
165 $this->prefixes[$prefix] = (array) $locations;
166 }
167 }
168
169 /**
170 * Registers a set of classes using the PEAR naming convention.
171 *
172 * @param string $prefix The classes prefix
173 * @param array|string $paths The location(s) of the classes
174 *
175 * @api
176 */
177 public function registerPrefix($prefix, $paths)
178 {
179 $this->prefixes[$prefix] = (array) $paths;
180 }
181
182 /**
183 * Registers this instance as an autoloader.
184 *
185 * @param Boolean $prepend Whether to prepend the autoloader or not
186 *
187 * @api
188 */
189 public function register($prepend = false)
190 {
191 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
192 }
193
194 /**
195 * Loads the given class or interface.
196 *
197 * @param string $class The name of the class
198 */
199 public function loadClass($class)
200 {
201 if ($file = $this->findFile($class)) {
202 require $file;
203 }
204 }
205
206 /**
207 * Finds the path to the file where the class is defined.
208 *
209 * @param string $class The name of the class
210 *
211 * @return string|null The path, if found
212 */
213 public function findFile($class)
214 {
215 if ('\\' == $class[0]) {
216 $class = substr($class, 1);
217 }
218
219 if (false !== $pos = strrpos($class, '\\')) {
220 // namespaced class name
221 $namespace = substr($class, 0, $pos);
222 foreach ($this->namespaces as $ns => $dirs) {
223 if (0 !== strpos($namespace, $ns)) {
224 continue;
225 }
226
227 foreach ($dirs as $dir) {
228 $className = substr($class, $pos + 1);
229 $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
230 if (file_exists($file)) {
231 return $file;
232 }
233 }
234 }
235
236 foreach ($this->namespaceFallbacks as $dir) {
237 $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
238 if (file_exists($file)) {
239 return $file;
240 }
241 }
242 } else {
243 // PEAR-like class name
244 foreach ($this->prefixes as $prefix => $dirs) {
245 if (0 !== strpos($class, $prefix)) {
246 continue;
247 }
248
249 foreach ($dirs as $dir) {
250 $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
251 if (file_exists($file)) {
252 return $file;
253 }
254 }
255 }
256
257 foreach ($this->prefixFallbacks as $dir) {
258 $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
259 if (file_exists($file)) {
260 return $file;
261 }
262 }
263 }
264 }
265 }