PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 7.4.0-rc.2
WooCommerce v7.4.0-rc.2
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / vendor / composer / ClassLoader.php
woocommerce / vendor / composer Last commit date
installers 4 years ago ClassLoader.php 3 years ago InstalledVersions.php 4 years ago LICENSE 5 years ago autoload_classmap.php 3 years ago autoload_files.php 4 years ago autoload_namespaces.php 4 years ago autoload_psr4.php 3 years ago autoload_real.php 3 years ago autoload_static.php 3 years ago installed.json 3 years ago installed.php 3 years ago jetpack_autoload_classmap.php 3 years ago jetpack_autoload_filemap.php 3 years ago platform_check.php 4 years ago
ClassLoader.php
586 lines
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, PSR-4 and classmap class loader.
17 *
18 * $loader = new \Composer\Autoload\ClassLoader();
19 *
20 * // register classes with namespaces
21 * $loader->add('Symfony\Component', __DIR__.'/component');
22 * $loader->add('Symfony', __DIR__.'/framework');
23 *
24 * // activate the autoloader
25 * $loader->register();
26 *
27 * // to enable searching the include path (eg. for PEAR packages)
28 * $loader->setUseIncludePath(true);
29 *
30 * In this example, if you try to use a class in the Symfony\Component
31 * namespace or one of its children (Symfony\Component\Console for instance),
32 * the autoloader will first look for the class under the component/
33 * directory, and it will then fallback to the framework/ directory if not
34 * found before giving up.
35 *
36 * This class is loosely based on the Symfony UniversalClassLoader.
37 *
38 * @author Fabien Potencier <fabien@symfony.com>
39 * @author Jordi Boggiano <j.boggiano@seld.be>
40 * @see https://www.php-fig.org/psr/psr-0/
41 * @see https://www.php-fig.org/psr/psr-4/
42 */
43 class ClassLoader
44 {
45 /** @var \Closure(string):void */
46 private static $includeFile;
47
48 /** @var ?string */
49 private $vendorDir;
50
51 // PSR-4
52 /**
53 * @var array[]
54 * @psalm-var array<string, array<string, int>>
55 */
56 private $prefixLengthsPsr4 = array();
57 /**
58 * @var array[]
59 * @psalm-var array<string, array<int, string>>
60 */
61 private $prefixDirsPsr4 = array();
62 /**
63 * @var array[]
64 * @psalm-var array<string, string>
65 */
66 private $fallbackDirsPsr4 = array();
67
68 // PSR-0
69 /**
70 * @var array[]
71 * @psalm-var array<string, array<string, string[]>>
72 */
73 private $prefixesPsr0 = array();
74 /**
75 * @var array[]
76 * @psalm-var array<string, string>
77 */
78 private $fallbackDirsPsr0 = array();
79
80 /** @var bool */
81 private $useIncludePath = false;
82
83 /**
84 * @var string[]
85 * @psalm-var array<string, string>
86 */
87 private $classMap = array();
88
89 /** @var bool */
90 private $classMapAuthoritative = false;
91
92 /**
93 * @var bool[]
94 * @psalm-var array<string, bool>
95 */
96 private $missingClasses = array();
97
98 /** @var ?string */
99 private $apcuPrefix;
100
101 /**
102 * @var self[]
103 */
104 private static $registeredLoaders = array();
105
106 /**
107 * @param ?string $vendorDir
108 */
109 public function __construct($vendorDir = null)
110 {
111 $this->vendorDir = $vendorDir;
112 self::initializeIncludeClosure();
113 }
114
115 /**
116 * @return string[]
117 */
118 public function getPrefixes()
119 {
120 if (!empty($this->prefixesPsr0)) {
121 return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
122 }
123
124 return array();
125 }
126
127 /**
128 * @return array[]
129 * @psalm-return array<string, array<int, string>>
130 */
131 public function getPrefixesPsr4()
132 {
133 return $this->prefixDirsPsr4;
134 }
135
136 /**
137 * @return array[]
138 * @psalm-return array<string, string>
139 */
140 public function getFallbackDirs()
141 {
142 return $this->fallbackDirsPsr0;
143 }
144
145 /**
146 * @return array[]
147 * @psalm-return array<string, string>
148 */
149 public function getFallbackDirsPsr4()
150 {
151 return $this->fallbackDirsPsr4;
152 }
153
154 /**
155 * @return string[] Array of classname => path
156 * @psalm-return array<string, string>
157 */
158 public function getClassMap()
159 {
160 return $this->classMap;
161 }
162
163 /**
164 * @param string[] $classMap Class to filename map
165 * @psalm-param array<string, string> $classMap
166 *
167 * @return void
168 */
169 public function addClassMap(array $classMap)
170 {
171 if ($this->classMap) {
172 $this->classMap = array_merge($this->classMap, $classMap);
173 } else {
174 $this->classMap = $classMap;
175 }
176 }
177
178 /**
179 * Registers a set of PSR-0 directories for a given prefix, either
180 * appending or prepending to the ones previously set for this prefix.
181 *
182 * @param string $prefix The prefix
183 * @param string[]|string $paths The PSR-0 root directories
184 * @param bool $prepend Whether to prepend the directories
185 *
186 * @return void
187 */
188 public function add($prefix, $paths, $prepend = false)
189 {
190 if (!$prefix) {
191 if ($prepend) {
192 $this->fallbackDirsPsr0 = array_merge(
193 (array) $paths,
194 $this->fallbackDirsPsr0
195 );
196 } else {
197 $this->fallbackDirsPsr0 = array_merge(
198 $this->fallbackDirsPsr0,
199 (array) $paths
200 );
201 }
202
203 return;
204 }
205
206 $first = $prefix[0];
207 if (!isset($this->prefixesPsr0[$first][$prefix])) {
208 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
209
210 return;
211 }
212 if ($prepend) {
213 $this->prefixesPsr0[$first][$prefix] = array_merge(
214 (array) $paths,
215 $this->prefixesPsr0[$first][$prefix]
216 );
217 } else {
218 $this->prefixesPsr0[$first][$prefix] = array_merge(
219 $this->prefixesPsr0[$first][$prefix],
220 (array) $paths
221 );
222 }
223 }
224
225 /**
226 * Registers a set of PSR-4 directories for a given namespace, either
227 * appending or prepending to the ones previously set for this namespace.
228 *
229 * @param string $prefix The prefix/namespace, with trailing '\\'
230 * @param string[]|string $paths The PSR-4 base directories
231 * @param bool $prepend Whether to prepend the directories
232 *
233 * @throws \InvalidArgumentException
234 *
235 * @return void
236 */
237 public function addPsr4($prefix, $paths, $prepend = false)
238 {
239 if (!$prefix) {
240 // Register directories for the root namespace.
241 if ($prepend) {
242 $this->fallbackDirsPsr4 = array_merge(
243 (array) $paths,
244 $this->fallbackDirsPsr4
245 );
246 } else {
247 $this->fallbackDirsPsr4 = array_merge(
248 $this->fallbackDirsPsr4,
249 (array) $paths
250 );
251 }
252 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
253 // Register directories for a new namespace.
254 $length = strlen($prefix);
255 if ('\\' !== $prefix[$length - 1]) {
256 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
257 }
258 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
259 $this->prefixDirsPsr4[$prefix] = (array) $paths;
260 } elseif ($prepend) {
261 // Prepend directories for an already registered namespace.
262 $this->prefixDirsPsr4[$prefix] = array_merge(
263 (array) $paths,
264 $this->prefixDirsPsr4[$prefix]
265 );
266 } else {
267 // Append directories for an already registered namespace.
268 $this->prefixDirsPsr4[$prefix] = array_merge(
269 $this->prefixDirsPsr4[$prefix],
270 (array) $paths
271 );
272 }
273 }
274
275 /**
276 * Registers a set of PSR-0 directories for a given prefix,
277 * replacing any others previously set for this prefix.
278 *
279 * @param string $prefix The prefix
280 * @param string[]|string $paths The PSR-0 base directories
281 *
282 * @return void
283 */
284 public function set($prefix, $paths)
285 {
286 if (!$prefix) {
287 $this->fallbackDirsPsr0 = (array) $paths;
288 } else {
289 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
290 }
291 }
292
293 /**
294 * Registers a set of PSR-4 directories for a given namespace,
295 * replacing any others previously set for this namespace.
296 *
297 * @param string $prefix The prefix/namespace, with trailing '\\'
298 * @param string[]|string $paths The PSR-4 base directories
299 *
300 * @throws \InvalidArgumentException
301 *
302 * @return void
303 */
304 public function setPsr4($prefix, $paths)
305 {
306 if (!$prefix) {
307 $this->fallbackDirsPsr4 = (array) $paths;
308 } else {
309 $length = strlen($prefix);
310 if ('\\' !== $prefix[$length - 1]) {
311 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
312 }
313 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
314 $this->prefixDirsPsr4[$prefix] = (array) $paths;
315 }
316 }
317
318 /**
319 * Turns on searching the include path for class files.
320 *
321 * @param bool $useIncludePath
322 *
323 * @return void
324 */
325 public function setUseIncludePath($useIncludePath)
326 {
327 $this->useIncludePath = $useIncludePath;
328 }
329
330 /**
331 * Can be used to check if the autoloader uses the include path to check
332 * for classes.
333 *
334 * @return bool
335 */
336 public function getUseIncludePath()
337 {
338 return $this->useIncludePath;
339 }
340
341 /**
342 * Turns off searching the prefix and fallback directories for classes
343 * that have not been registered with the class map.
344 *
345 * @param bool $classMapAuthoritative
346 *
347 * @return void
348 */
349 public function setClassMapAuthoritative($classMapAuthoritative)
350 {
351 $this->classMapAuthoritative = $classMapAuthoritative;
352 }
353
354 /**
355 * Should class lookup fail if not found in the current class map?
356 *
357 * @return bool
358 */
359 public function isClassMapAuthoritative()
360 {
361 return $this->classMapAuthoritative;
362 }
363
364 /**
365 * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
366 *
367 * @param string|null $apcuPrefix
368 *
369 * @return void
370 */
371 public function setApcuPrefix($apcuPrefix)
372 {
373 $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
374 }
375
376 /**
377 * The APCu prefix in use, or null if APCu caching is not enabled.
378 *
379 * @return string|null
380 */
381 public function getApcuPrefix()
382 {
383 return $this->apcuPrefix;
384 }
385
386 /**
387 * Registers this instance as an autoloader.
388 *
389 * @param bool $prepend Whether to prepend the autoloader or not
390 *
391 * @return void
392 */
393 public function register($prepend = false)
394 {
395 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
396
397 if (null === $this->vendorDir) {
398 return;
399 }
400
401 if ($prepend) {
402 self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
403 } else {
404 unset(self::$registeredLoaders[$this->vendorDir]);
405 self::$registeredLoaders[$this->vendorDir] = $this;
406 }
407 }
408
409 /**
410 * Unregisters this instance as an autoloader.
411 *
412 * @return void
413 */
414 public function unregister()
415 {
416 spl_autoload_unregister(array($this, 'loadClass'));
417
418 if (null !== $this->vendorDir) {
419 unset(self::$registeredLoaders[$this->vendorDir]);
420 }
421 }
422
423 /**
424 * Loads the given class or interface.
425 *
426 * @param string $class The name of the class
427 * @return true|null True if loaded, null otherwise
428 */
429 public function loadClass($class)
430 {
431 if ($file = $this->findFile($class)) {
432 $includeFile = self::$includeFile;
433 $includeFile($file);
434
435 return true;
436 }
437
438 return null;
439 }
440
441 /**
442 * Finds the path to the file where the class is defined.
443 *
444 * @param string $class The name of the class
445 *
446 * @return string|false The path if found, false otherwise
447 */
448 public function findFile($class)
449 {
450 // class map lookup
451 if (isset($this->classMap[$class])) {
452 return $this->classMap[$class];
453 }
454 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
455 return false;
456 }
457 if (null !== $this->apcuPrefix) {
458 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
459 if ($hit) {
460 return $file;
461 }
462 }
463
464 $file = $this->findFileWithExtension($class, '.php');
465
466 // Search for Hack files if we are running on HHVM
467 if (false === $file && defined('HHVM_VERSION')) {
468 $file = $this->findFileWithExtension($class, '.hh');
469 }
470
471 if (null !== $this->apcuPrefix) {
472 apcu_add($this->apcuPrefix.$class, $file);
473 }
474
475 if (false === $file) {
476 // Remember that this class does not exist.
477 $this->missingClasses[$class] = true;
478 }
479
480 return $file;
481 }
482
483 /**
484 * Returns the currently registered loaders indexed by their corresponding vendor directories.
485 *
486 * @return self[]
487 */
488 public static function getRegisteredLoaders()
489 {
490 return self::$registeredLoaders;
491 }
492
493 /**
494 * @param string $class
495 * @param string $ext
496 * @return string|false
497 */
498 private function findFileWithExtension($class, $ext)
499 {
500 // PSR-4 lookup
501 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
502
503 $first = $class[0];
504 if (isset($this->prefixLengthsPsr4[$first])) {
505 $subPath = $class;
506 while (false !== $lastPos = strrpos($subPath, '\\')) {
507 $subPath = substr($subPath, 0, $lastPos);
508 $search = $subPath . '\\';
509 if (isset($this->prefixDirsPsr4[$search])) {
510 $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
511 foreach ($this->prefixDirsPsr4[$search] as $dir) {
512 if (file_exists($file = $dir . $pathEnd)) {
513 return $file;
514 }
515 }
516 }
517 }
518 }
519
520 // PSR-4 fallback dirs
521 foreach ($this->fallbackDirsPsr4 as $dir) {
522 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
523 return $file;
524 }
525 }
526
527 // PSR-0 lookup
528 if (false !== $pos = strrpos($class, '\\')) {
529 // namespaced class name
530 $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
531 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
532 } else {
533 // PEAR-like class name
534 $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
535 }
536
537 if (isset($this->prefixesPsr0[$first])) {
538 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
539 if (0 === strpos($class, $prefix)) {
540 foreach ($dirs as $dir) {
541 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
542 return $file;
543 }
544 }
545 }
546 }
547 }
548
549 // PSR-0 fallback dirs
550 foreach ($this->fallbackDirsPsr0 as $dir) {
551 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
552 return $file;
553 }
554 }
555
556 // PSR-0 include paths.
557 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
558 return $file;
559 }
560
561 return false;
562 }
563
564 /**
565 * @return void
566 */
567 private static function initializeIncludeClosure()
568 {
569 if (self::$includeFile !== null) {
570 return;
571 }
572
573 /**
574 * Scope isolated include.
575 *
576 * Prevents access to $this/self from included files.
577 *
578 * @param string $file
579 * @return void
580 */
581 self::$includeFile = \Closure::bind(static function($file) {
582 include $file;
583 }, null, null);
584 }
585 }
586