PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.9.5
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.9.5
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
← All changes | vendor/composer/ClassLoader.php +206 -38 3.0.93.9.5 View file →
@@ -36,51 +36,126 @@
36 36 * This class is loosely based on the Symfony UniversalClassLoader.
37 37 *
38 38 * @author Fabien Potencier <fabien@symfony.com>
39 39 * @author Jordi Boggiano <j.boggiano@seld.be>
40 - * @see http://www.php-fig.org/psr/psr-0/
41 - * @see http://www.php-fig.org/psr/psr-4/
40 + * @see https://www.php-fig.org/psr/psr-0/
41 + * @see https://www.php-fig.org/psr/psr-4/
42 42 */
43 43 class ClassLoader
44 44 {
45 + /** @var \Closure(string):void */
46 + private static $includeFile;
47 +
48 + /** @var ?string */
49 + private $vendorDir;
50 +
45 51 // PSR-4
52 + /**
53 + * @var array[]
54 + * @psalm-var array<string, array<string, int>>
55 + */
46 56 private $prefixLengthsPsr4 = array();
57 + /**
58 + * @var array[]
59 + * @psalm-var array<string, array<int, string>>
60 + */
47 61 private $prefixDirsPsr4 = array();
62 + /**
63 + * @var array[]
64 + * @psalm-var array<string, string>
65 + */
48 66 private $fallbackDirsPsr4 = array();
49 67
50 68 // PSR-0
69 + /**
70 + * @var array[]
71 + * @psalm-var array<string, array<string, string[]>>
72 + */
51 73 private $prefixesPsr0 = array();
74 + /**
75 + * @var array[]
76 + * @psalm-var array<string, string>
77 + */
52 78 private $fallbackDirsPsr0 = array();
53 79
80 + /** @var bool */
54 81 private $useIncludePath = false;
82 +
83 + /**
84 + * @var string[]
85 + * @psalm-var array<string, string>
86 + */
55 87 private $classMap = array();
56 88
89 + /** @var bool */
57 90 private $classMapAuthoritative = false;
58 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 + */
59 118 public function getPrefixes()
60 119 {
61 120 if (!empty($this->prefixesPsr0)) {
62 - return call_user_func_array('array_merge', $this->prefixesPsr0);
121 + return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
63 122 }
64 123
65 124 return array();
66 125 }
67 126
127 + /**
128 + * @return array[]
129 + * @psalm-return array<string, array<int, string>>
130 + */
68 131 public function getPrefixesPsr4()
69 132 {
70 133 return $this->prefixDirsPsr4;
71 134 }
72 135
136 + /**
137 + * @return array[]
138 + * @psalm-return array<string, string>
139 + */
73 140 public function getFallbackDirs()
74 141 {
75 142 return $this->fallbackDirsPsr0;
76 143 }
77 144
145 + /**
146 + * @return array[]
147 + * @psalm-return array<string, string>
148 + */
78 149 public function getFallbackDirsPsr4()
79 150 {
80 151 return $this->fallbackDirsPsr4;
81 152 }
82 153
154 + /**
155 + * @return string[] Array of classname => path
156 + * @psalm-return array<string, string>
157 + */
83 158 public function getClassMap()
84 159 {
85 160 return $this->classMap;
86 161 }
@@ -85,9 +160,12 @@
85 160 return $this->classMap;
86 161 }
87 162
88 163 /**
89 - * @param array $classMap Class to filename map
164 + * @param string[] $classMap Class to filename map
165 + * @psalm-param array<string, string> $classMap
166 + *
167 + * @return void
90 168 */
91 169 public function addClassMap(array $classMap)
92 170 {
93 171 if ($this->classMap) {
@@ -100,11 +178,13 @@
100 178 /**
101 179 * Registers a set of PSR-0 directories for a given prefix, either
102 180 * appending or prepending to the ones previously set for this prefix.
103 181 *
104 - * @param string $prefix The prefix
105 - * @param array|string $paths The PSR-0 root directories
106 - * @param bool $prepend Whether to prepend the directories
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
107 187 */
108 188 public function add($prefix, $paths, $prepend = false)
109 189 {
110 190 if (!$prefix) {
@@ -145,13 +225,15 @@
145 225 /**
146 226 * Registers a set of PSR-4 directories for a given namespace, either
147 227 * appending or prepending to the ones previously set for this namespace.
148 228 *
149 - * @param string $prefix The prefix/namespace, with trailing '\\'
150 - * @param array|string $paths The PSR-4 base directories
151 - * @param bool $prepend Whether to prepend the directories
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
152 232 *
153 233 * @throws \InvalidArgumentException
234 + *
235 + * @return void
154 236 */
155 237 public function addPsr4($prefix, $paths, $prepend = false)
156 238 {
157 239 if (!$prefix) {
@@ -193,10 +275,12 @@
193 275 /**
194 276 * Registers a set of PSR-0 directories for a given prefix,
195 277 * replacing any others previously set for this prefix.
196 278 *
197 - * @param string $prefix The prefix
198 - * @param array|string $paths The PSR-0 base directories
279 + * @param string $prefix The prefix
280 + * @param string[]|string $paths The PSR-0 base directories
281 + *
282 + * @return void
199 283 */
200 284 public function set($prefix, $paths)
201 285 {
202 286 if (!$prefix) {
@@ -209,12 +293,14 @@
209 293 /**
210 294 * Registers a set of PSR-4 directories for a given namespace,
211 295 * replacing any others previously set for this namespace.
212 296 *
213 - * @param string $prefix The prefix/namespace, with trailing '\\'
214 - * @param array|string $paths The PSR-4 base directories
297 + * @param string $prefix The prefix/namespace, with trailing '\\'
298 + * @param string[]|string $paths The PSR-4 base directories
215 299 *
216 300 * @throws \InvalidArgumentException
301 + *
302 + * @return void
217 303 */
218 304 public function setPsr4($prefix, $paths)
219 305 {
220 306 if (!$prefix) {
@@ -232,8 +318,10 @@
232 318 /**
233 319 * Turns on searching the include path for class files.
234 320 *
235 321 * @param bool $useIncludePath
322 + *
323 + * @return void
236 324 */
237 325 public function setUseIncludePath($useIncludePath)
238 326 {
239 327 $this->useIncludePath = $useIncludePath;
@@ -254,8 +342,10 @@
254 342 * Turns off searching the prefix and fallback directories for classes
255 343 * that have not been registered with the class map.
256 344 *
257 345 * @param bool $classMapAuthoritative
346 + *
347 + * @return void
258 348 */
259 349 public function setClassMapAuthoritative($classMapAuthoritative)
260 350 {
261 351 $this->classMapAuthoritative = $classMapAuthoritative;
@@ -271,23 +361,64 @@
271 361 return $this->classMapAuthoritative;
272 362 }
273 363
274 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 + /**
275 387 * Registers this instance as an autoloader.
276 388 *
277 389 * @param bool $prepend Whether to prepend the autoloader or not
390 + *
391 + * @return void
278 392 */
279 393 public function register($prepend = false)
280 394 {
281 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 + }
282 407 }
283 408
284 409 /**
285 410 * Unregisters this instance as an autoloader.
411 + *
412 + * @return void
286 413 */
287 414 public function unregister()
288 415 {
289 416 spl_autoload_unregister(array($this, 'loadClass'));
417 +
418 + if (null !== $this->vendorDir) {
419 + unset(self::$registeredLoaders[$this->vendorDir]);
420 + }
290 421 }
291 422
292 423 /**
293 424 * Loads the given class or interface.
@@ -292,17 +423,19 @@
292 423 /**
293 424 * Loads the given class or interface.
294 425 *
295 426 * @param string $class The name of the class
296 - * @return bool|null True if loaded, null otherwise
427 + * @return true|null True if loaded, null otherwise
297 428 */
298 429 public function loadClass($class)
299 430 {
300 431 if ($file = $this->findFile($class)) {
301 - includeFile($file);
432 + (self::$includeFile)($file);
302 433
303 434 return true;
304 435 }
436 +
437 + return null;
305 438 }
306 439
307 440 /**
308 441 * Finds the path to the file where the class is defined.
@@ -312,36 +445,56 @@
312 445 * @return string|false The path if found, false otherwise
313 446 */
314 447 public function findFile($class)
315 448 {
316 - // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317 - if ('\\' == $class[0]) {
318 - $class = substr($class, 1);
319 - }
320 -
321 449 // class map lookup
322 450 if (isset($this->classMap[$class])) {
323 451 return $this->classMap[$class];
324 452 }
325 - if ($this->classMapAuthoritative) {
453 + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
326 454 return false;
327 455 }
456 + if (null !== $this->apcuPrefix) {
457 + $file = apcu_fetch($this->apcuPrefix.$class, $hit);
458 + if ($hit) {
459 + return $file;
460 + }
461 + }
328 462
329 463 $file = $this->findFileWithExtension($class, '.php');
330 464
331 465 // Search for Hack files if we are running on HHVM
332 - if ($file === null && defined('HHVM_VERSION')) {
466 + if (false === $file && defined('HHVM_VERSION')) {
333 467 $file = $this->findFileWithExtension($class, '.hh');
334 468 }
335 469
336 - if ($file === null) {
470 + if (null !== $this->apcuPrefix) {
471 + apcu_add($this->apcuPrefix.$class, $file);
472 + }
473 +
474 + if (false === $file) {
337 475 // Remember that this class does not exist.
338 - return $this->classMap[$class] = false;
476 + $this->missingClasses[$class] = true;
339 477 }
340 478
341 479 return $file;
342 480 }
343 481
482 + /**
483 + * Returns the currently registered loaders indexed by their corresponding vendor directories.
484 + *
485 + * @return self[]
486 + */
487 + public static function getRegisteredLoaders()
488 + {
489 + return self::$registeredLoaders;
490 + }
491 +
492 + /**
493 + * @param string $class
494 + * @param string $ext
495 + * @return string|false
496 + */
344 497 private function findFileWithExtension($class, $ext)
345 498 {
346 499 // PSR-4 lookup
347 500 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
@@ -347,12 +500,16 @@
347 500 $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
348 501
349 502 $first = $class[0];
350 503 if (isset($this->prefixLengthsPsr4[$first])) {
351 - foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
352 - if (0 === strpos($class, $prefix)) {
353 - foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
354 - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
504 + $subPath = $class;
505 + while (false !== $lastPos = strrpos($subPath, '\\')) {
506 + $subPath = substr($subPath, 0, $lastPos);
507 + $search = $subPath . '\\';
508 + if (isset($this->prefixDirsPsr4[$search])) {
509 + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
510 + foreach ($this->prefixDirsPsr4[$search] as $dir) {
511 + if (file_exists($file = $dir . $pathEnd)) {
355 512 return $file;
356 513 }
357 514 }
358 515 }
@@ -398,16 +555,27 @@
398 555 // PSR-0 include paths.
399 556 if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
400 557 return $file;
401 558 }
559 +
560 + return false;
402 561 }
403 -}
404 562
405 -/**
406 - * Scope isolated include.
407 - *
408 - * Prevents access to $this/self from included files.
409 - */
410 -function includeFile($file)
411 -{
412 - include $file;
563 + private static function initializeIncludeClosure(): void
564 + {
565 + if (self::$includeFile !== null) {
566 + return;
567 + }
568 +
569 + /**
570 + * Scope isolated include.
571 + *
572 + * Prevents access to $this/self from included files.
573 + *
574 + * @param string $file
575 + * @return void
576 + */
577 + self::$includeFile = static function($file) {
578 + include $file;
579 + };
580 + }
413 581 }