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