Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\ClassLoader;
|
Chris@0
|
13
|
Chris@0
|
14 /**
|
Chris@0
|
15 * ClassLoader implements an PSR-0 class loader.
|
Chris@0
|
16 *
|
Chris@0
|
17 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
Chris@0
|
18 *
|
Chris@0
|
19 * $loader = new ClassLoader();
|
Chris@0
|
20 *
|
Chris@0
|
21 * // register classes with namespaces
|
Chris@0
|
22 * $loader->addPrefix('Symfony\Component', __DIR__.'/component');
|
Chris@0
|
23 * $loader->addPrefix('Symfony', __DIR__.'/framework');
|
Chris@0
|
24 *
|
Chris@0
|
25 * // activate the autoloader
|
Chris@0
|
26 * $loader->register();
|
Chris@0
|
27 *
|
Chris@0
|
28 * // to enable searching the include path (e.g. for PEAR packages)
|
Chris@0
|
29 * $loader->setUseIncludePath(true);
|
Chris@0
|
30 *
|
Chris@0
|
31 * In this example, if you try to use a class in the Symfony\Component
|
Chris@0
|
32 * namespace or one of its children (Symfony\Component\Console for instance),
|
Chris@0
|
33 * the autoloader will first look for the class under the component/
|
Chris@0
|
34 * directory, and it will then fallback to the framework/ directory if not
|
Chris@0
|
35 * found before giving up.
|
Chris@0
|
36 *
|
Chris@0
|
37 * @author Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
38 * @author Jordi Boggiano <j.boggiano@seld.be>
|
Chris@0
|
39 */
|
Chris@0
|
40 class ClassLoader
|
Chris@0
|
41 {
|
Chris@0
|
42 private $prefixes = array();
|
Chris@0
|
43 private $fallbackDirs = array();
|
Chris@0
|
44 private $useIncludePath = false;
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * Returns prefixes.
|
Chris@0
|
48 *
|
Chris@0
|
49 * @return array
|
Chris@0
|
50 */
|
Chris@0
|
51 public function getPrefixes()
|
Chris@0
|
52 {
|
Chris@0
|
53 return $this->prefixes;
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * Returns fallback directories.
|
Chris@0
|
58 *
|
Chris@0
|
59 * @return array
|
Chris@0
|
60 */
|
Chris@0
|
61 public function getFallbackDirs()
|
Chris@0
|
62 {
|
Chris@0
|
63 return $this->fallbackDirs;
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Adds prefixes.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param array $prefixes Prefixes to add
|
Chris@0
|
70 */
|
Chris@0
|
71 public function addPrefixes(array $prefixes)
|
Chris@0
|
72 {
|
Chris@0
|
73 foreach ($prefixes as $prefix => $path) {
|
Chris@0
|
74 $this->addPrefix($prefix, $path);
|
Chris@0
|
75 }
|
Chris@0
|
76 }
|
Chris@0
|
77
|
Chris@0
|
78 /**
|
Chris@0
|
79 * Registers a set of classes.
|
Chris@0
|
80 *
|
Chris@0
|
81 * @param string $prefix The classes prefix
|
Chris@0
|
82 * @param array|string $paths The location(s) of the classes
|
Chris@0
|
83 */
|
Chris@0
|
84 public function addPrefix($prefix, $paths)
|
Chris@0
|
85 {
|
Chris@0
|
86 if (!$prefix) {
|
Chris@0
|
87 foreach ((array) $paths as $path) {
|
Chris@0
|
88 $this->fallbackDirs[] = $path;
|
Chris@0
|
89 }
|
Chris@0
|
90
|
Chris@0
|
91 return;
|
Chris@0
|
92 }
|
Chris@0
|
93 if (isset($this->prefixes[$prefix])) {
|
Chris@0
|
94 if (is_array($paths)) {
|
Chris@0
|
95 $this->prefixes[$prefix] = array_unique(array_merge(
|
Chris@0
|
96 $this->prefixes[$prefix],
|
Chris@0
|
97 $paths
|
Chris@0
|
98 ));
|
Chris@0
|
99 } elseif (!in_array($paths, $this->prefixes[$prefix])) {
|
Chris@0
|
100 $this->prefixes[$prefix][] = $paths;
|
Chris@0
|
101 }
|
Chris@0
|
102 } else {
|
Chris@0
|
103 $this->prefixes[$prefix] = array_unique((array) $paths);
|
Chris@0
|
104 }
|
Chris@0
|
105 }
|
Chris@0
|
106
|
Chris@0
|
107 /**
|
Chris@0
|
108 * Turns on searching the include for class files.
|
Chris@0
|
109 *
|
Chris@0
|
110 * @param bool $useIncludePath
|
Chris@0
|
111 */
|
Chris@0
|
112 public function setUseIncludePath($useIncludePath)
|
Chris@0
|
113 {
|
Chris@0
|
114 $this->useIncludePath = (bool) $useIncludePath;
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 /**
|
Chris@0
|
118 * Can be used to check if the autoloader uses the include path to check
|
Chris@0
|
119 * for classes.
|
Chris@0
|
120 *
|
Chris@0
|
121 * @return bool
|
Chris@0
|
122 */
|
Chris@0
|
123 public function getUseIncludePath()
|
Chris@0
|
124 {
|
Chris@0
|
125 return $this->useIncludePath;
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 /**
|
Chris@0
|
129 * Registers this instance as an autoloader.
|
Chris@0
|
130 *
|
Chris@0
|
131 * @param bool $prepend Whether to prepend the autoloader or not
|
Chris@0
|
132 */
|
Chris@0
|
133 public function register($prepend = false)
|
Chris@0
|
134 {
|
Chris@0
|
135 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 /**
|
Chris@0
|
139 * Unregisters this instance as an autoloader.
|
Chris@0
|
140 */
|
Chris@0
|
141 public function unregister()
|
Chris@0
|
142 {
|
Chris@0
|
143 spl_autoload_unregister(array($this, 'loadClass'));
|
Chris@0
|
144 }
|
Chris@0
|
145
|
Chris@0
|
146 /**
|
Chris@0
|
147 * Loads the given class or interface.
|
Chris@0
|
148 *
|
Chris@0
|
149 * @param string $class The name of the class
|
Chris@0
|
150 *
|
Chris@0
|
151 * @return bool|null True, if loaded
|
Chris@0
|
152 */
|
Chris@0
|
153 public function loadClass($class)
|
Chris@0
|
154 {
|
Chris@0
|
155 if ($file = $this->findFile($class)) {
|
Chris@0
|
156 require $file;
|
Chris@0
|
157
|
Chris@0
|
158 return true;
|
Chris@0
|
159 }
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 /**
|
Chris@0
|
163 * Finds the path to the file where the class is defined.
|
Chris@0
|
164 *
|
Chris@0
|
165 * @param string $class The name of the class
|
Chris@0
|
166 *
|
Chris@0
|
167 * @return string|null The path, if found
|
Chris@0
|
168 */
|
Chris@0
|
169 public function findFile($class)
|
Chris@0
|
170 {
|
Chris@0
|
171 if (false !== $pos = strrpos($class, '\\')) {
|
Chris@0
|
172 // namespaced class name
|
Chris@0
|
173 $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
|
Chris@0
|
174 $className = substr($class, $pos + 1);
|
Chris@0
|
175 } else {
|
Chris@0
|
176 // PEAR-like class name
|
Chris@0
|
177 $classPath = null;
|
Chris@0
|
178 $className = $class;
|
Chris@0
|
179 }
|
Chris@0
|
180
|
Chris@0
|
181 $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php';
|
Chris@0
|
182
|
Chris@0
|
183 foreach ($this->prefixes as $prefix => $dirs) {
|
Chris@0
|
184 if ($class === strstr($class, $prefix)) {
|
Chris@0
|
185 foreach ($dirs as $dir) {
|
Chris@0
|
186 if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
|
Chris@0
|
187 return $dir.DIRECTORY_SEPARATOR.$classPath;
|
Chris@0
|
188 }
|
Chris@0
|
189 }
|
Chris@0
|
190 }
|
Chris@0
|
191 }
|
Chris@0
|
192
|
Chris@0
|
193 foreach ($this->fallbackDirs as $dir) {
|
Chris@0
|
194 if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
|
Chris@0
|
195 return $dir.DIRECTORY_SEPARATOR.$classPath;
|
Chris@0
|
196 }
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
|
Chris@0
|
200 return $file;
|
Chris@0
|
201 }
|
Chris@0
|
202 }
|
Chris@0
|
203 }
|