Vous êtes connecté en tant que anonymous Se Deconnecter
Browse code

Application modulaire fonctionnelle !

Emmanuel ROY authored on 12/08/2019 15:10:25
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,525 +0,0 @@
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\Debug;
13
-
14
-use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
15
-
16
-/**
17
- * Autoloader checking if the class is really defined in the file found.
18
- *
19
- * The ClassLoader will wrap all registered autoloaders
20
- * and will throw an exception if a file is found but does
21
- * not declare the class.
22
- *
23
- * @author Fabien Potencier <fabien@symfony.com>
24
- * @author Christophe Coevoet <stof@notk.org>
25
- * @author Nicolas Grekas <p@tchwork.com>
26
- * @author Guilhem Niot <guilhem.niot@gmail.com>
27
- */
28
-class DebugClassLoader
29
-{
30
-    private $classLoader;
31
-    private $isFinder;
32
-    private $loaded = [];
33
-    private static $caseCheck;
34
-    private static $checkedClasses = [];
35
-    private static $final = [];
36
-    private static $finalMethods = [];
37
-    private static $deprecated = [];
38
-    private static $internal = [];
39
-    private static $internalMethods = [];
40
-    private static $annotatedParameters = [];
41
-    private static $darwinCache = ['/' => ['/', []]];
42
-    private static $method = [];
43
-
44
-    public function __construct(callable $classLoader)
45
-    {
46
-        $this->classLoader = $classLoader;
47
-        $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
48
-
49
-        if (!isset(self::$caseCheck)) {
50
-            $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
51
-            $i = strrpos($file, \DIRECTORY_SEPARATOR);
52
-            $dir = substr($file, 0, 1 + $i);
53
-            $file = substr($file, 1 + $i);
54
-            $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
55
-            $test = realpath($dir.$test);
56
-
57
-            if (false === $test || false === $i) {
58
-                // filesystem is case sensitive
59
-                self::$caseCheck = 0;
60
-            } elseif (substr($test, -\strlen($file)) === $file) {
61
-                // filesystem is case insensitive and realpath() normalizes the case of characters
62
-                self::$caseCheck = 1;
63
-            } elseif (false !== stripos(PHP_OS, 'darwin')) {
64
-                // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
65
-                self::$caseCheck = 2;
66
-            } else {
67
-                // filesystem case checks failed, fallback to disabling them
68
-                self::$caseCheck = 0;
69
-            }
70
-        }
71
-    }
72
-
73
-    /**
74
-     * Gets the wrapped class loader.
75
-     *
76
-     * @return callable The wrapped class loader
77
-     */
78
-    public function getClassLoader()
79
-    {
80
-        return $this->classLoader;
81
-    }
82
-
83
-    /**
84
-     * Wraps all autoloaders.
85
-     */
86
-    public static function enable()
87
-    {
88
-        // Ensures we don't hit https://bugs.php.net/42098
89
-        class_exists('Symfony\Component\Debug\ErrorHandler');
90
-        class_exists('Psr\Log\LogLevel');
91
-
92
-        if (!\is_array($functions = spl_autoload_functions())) {
93
-            return;
94
-        }
95
-
96
-        foreach ($functions as $function) {
97
-            spl_autoload_unregister($function);
98
-        }
99
-
100
-        foreach ($functions as $function) {
101
-            if (!\is_array($function) || !$function[0] instanceof self) {
102
-                $function = [new static($function), 'loadClass'];
103
-            }
104
-
105
-            spl_autoload_register($function);
106
-        }
107
-    }
108
-
109
-    /**
110
-     * Disables the wrapping.
111
-     */
112
-    public static function disable()
113
-    {
114
-        if (!\is_array($functions = spl_autoload_functions())) {
115
-            return;
116
-        }
117
-
118
-        foreach ($functions as $function) {
119
-            spl_autoload_unregister($function);
120
-        }
121
-
122
-        foreach ($functions as $function) {
123
-            if (\is_array($function) && $function[0] instanceof self) {
124
-                $function = $function[0]->getClassLoader();
125
-            }
126
-
127
-            spl_autoload_register($function);
128
-        }
129
-    }
130
-
131
-    /**
132
-     * @return string|null
133
-     */
134
-    public function findFile($class)
135
-    {
136
-        return $this->isFinder ? $this->classLoader[0]->findFile($class) ?: null : null;
137
-    }
138
-
139
-    /**
140
-     * Loads the given class or interface.
141
-     *
142
-     * @param string $class The name of the class
143
-     *
144
-     * @throws \RuntimeException
145
-     */
146
-    public function loadClass($class)
147
-    {
148
-        $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
149
-
150
-        try {
151
-            if ($this->isFinder && !isset($this->loaded[$class])) {
152
-                $this->loaded[$class] = true;
153
-                if (!$file = $this->classLoader[0]->findFile($class) ?: false) {
154
-                    // no-op
155
-                } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
156
-                    include $file;
157
-
158
-                    return;
159
-                } elseif (false === include $file) {
160
-                    return;
161
-                }
162
-            } else {
163
-                ($this->classLoader)($class);
164
-                $file = false;
165
-            }
166
-        } finally {
167
-            error_reporting($e);
168
-        }
169
-
170
-        $this->checkClass($class, $file);
171
-    }
172
-
173
-    private function checkClass($class, $file = null)
174
-    {
175
-        $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
176
-
177
-        if (null !== $file && $class && '\\' === $class[0]) {
178
-            $class = substr($class, 1);
179
-        }
180
-
181
-        if ($exists) {
182
-            if (isset(self::$checkedClasses[$class])) {
183
-                return;
184
-            }
185
-            self::$checkedClasses[$class] = true;
186
-
187
-            $refl = new \ReflectionClass($class);
188
-            if (null === $file && $refl->isInternal()) {
189
-                return;
190
-            }
191
-            $name = $refl->getName();
192
-
193
-            if ($name !== $class && 0 === strcasecmp($name, $class)) {
194
-                throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
195
-            }
196
-
197
-            $deprecations = $this->checkAnnotations($refl, $name);
198
-
199
-            foreach ($deprecations as $message) {
200
-                @trigger_error($message, E_USER_DEPRECATED);
201
-            }
202
-        }
203
-
204
-        if (!$file) {
205
-            return;
206
-        }
207
-
208
-        if (!$exists) {
209
-            if (false !== strpos($class, '/')) {
210
-                throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
211
-            }
212
-
213
-            throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
214
-        }
215
-
216
-        if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) {
217
-            throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2]));
218
-        }
219
-    }
220
-
221
-    public function checkAnnotations(\ReflectionClass $refl, $class)
222
-    {
223
-        $deprecations = [];
224
-
225
-        // Don't trigger deprecations for classes in the same vendor
226
-        if (2 > $len = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) {
227
-            $len = 0;
228
-            $ns = '';
229
-        } else {
230
-            $ns = str_replace('_', '\\', substr($class, 0, $len));
231
-        }
232
-
233
-        // Detect annotations on the class
234
-        if (false !== $doc = $refl->getDocComment()) {
235
-            foreach (['final', 'deprecated', 'internal'] as $annotation) {
236
-                if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
237
-                    self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
238
-                }
239
-            }
240
-
241
-            if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) {
242
-                foreach ($notice as $method) {
243
-                    $static = '' !== $method[1];
244
-                    $name = $method[2];
245
-                    $description = $method[3] ?? null;
246
-                    if (false === strpos($name, '(')) {
247
-                        $name .= '()';
248
-                    }
249
-                    if (null !== $description) {
250
-                        $description = trim($description);
251
-                        if (!isset($method[4])) {
252
-                            $description .= '.';
253
-                        }
254
-                    }
255
-                    self::$method[$class][] = [$class, $name, $static, $description];
256
-                }
257
-            }
258
-        }
259
-
260
-        $parent = get_parent_class($class);
261
-        $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
262
-        if ($parent) {
263
-            $parentAndOwnInterfaces[$parent] = $parent;
264
-
265
-            if (!isset(self::$checkedClasses[$parent])) {
266
-                $this->checkClass($parent);
267
-            }
268
-
269
-            if (isset(self::$final[$parent])) {
270
-                $deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $class);
271
-            }
272
-        }
273
-
274
-        // Detect if the parent is annotated
275
-        foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) {
276
-            if (!isset(self::$checkedClasses[$use])) {
277
-                $this->checkClass($use);
278
-            }
279
-            if (isset(self::$deprecated[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) {
280
-                $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
281
-                $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
282
-
283
-                $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $class, $type, $verb, $use, self::$deprecated[$use]);
284
-            }
285
-            if (isset(self::$internal[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len)) {
286
-                $deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class);
287
-            }
288
-            if (isset(self::$method[$use])) {
289
-                if ($refl->isAbstract()) {
290
-                    if (isset(self::$method[$class])) {
291
-                        self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
292
-                    } else {
293
-                        self::$method[$class] = self::$method[$use];
294
-                    }
295
-                } elseif (!$refl->isInterface()) {
296
-                    $hasCall = $refl->hasMethod('__call');
297
-                    $hasStaticCall = $refl->hasMethod('__callStatic');
298
-                    foreach (self::$method[$use] as $method) {
299
-                        list($interface, $name, $static, $description) = $method;
300
-                        if ($static ? $hasStaticCall : $hasCall) {
301
-                            continue;
302
-                        }
303
-                        $realName = substr($name, 0, strpos($name, '('));
304
-                        if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) {
305
-                            $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $class, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description);
306
-                        }
307
-                    }
308
-                }
309
-            }
310
-        }
311
-
312
-        if (trait_exists($class)) {
313
-            return $deprecations;
314
-        }
315
-
316
-        // Inherit @final, @internal and @param annotations for methods
317
-        self::$finalMethods[$class] = [];
318
-        self::$internalMethods[$class] = [];
319
-        self::$annotatedParameters[$class] = [];
320
-        foreach ($parentAndOwnInterfaces as $use) {
321
-            foreach (['finalMethods', 'internalMethods', 'annotatedParameters'] as $property) {
322
-                if (isset(self::${$property}[$use])) {
323
-                    self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
324
-                }
325
-            }
326
-        }
327
-
328
-        foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
329
-            if ($method->class !== $class) {
330
-                continue;
331
-            }
332
-
333
-            if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
334
-                list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
335
-                $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
336
-            }
337
-
338
-            if (isset(self::$internalMethods[$class][$method->name])) {
339
-                list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
340
-                if (strncmp($ns, $declaringClass, $len)) {
341
-                    $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
342
-                }
343
-            }
344
-
345
-            // To read method annotations
346
-            $doc = $method->getDocComment();
347
-
348
-            if (isset(self::$annotatedParameters[$class][$method->name])) {
349
-                $definedParameters = [];
350
-                foreach ($method->getParameters() as $parameter) {
351
-                    $definedParameters[$parameter->name] = true;
352
-                }
353
-
354
-                foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
355
-                    if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) {
356
-                        $deprecations[] = sprintf($deprecation, $class);
357
-                    }
358
-                }
359
-            }
360
-
361
-            if (!$doc) {
362
-                continue;
363
-            }
364
-
365
-            $finalOrInternal = false;
366
-
367
-            foreach (['final', 'internal'] as $annotation) {
368
-                if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
369
-                    $message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
370
-                    self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
371
-                    $finalOrInternal = true;
372
-                }
373
-            }
374
-
375
-            if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) {
376
-                continue;
377
-            }
378
-            if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
379
-                continue;
380
-            }
381
-            if (!isset(self::$annotatedParameters[$class][$method->name])) {
382
-                $definedParameters = [];
383
-                foreach ($method->getParameters() as $parameter) {
384
-                    $definedParameters[$parameter->name] = true;
385
-                }
386
-            }
387
-            foreach ($matches as list(, $parameterType, $parameterName)) {
388
-                if (!isset($definedParameters[$parameterName])) {
389
-                    $parameterType = trim($parameterType);
390
-                    self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $method->class);
391
-                }
392
-            }
393
-        }
394
-
395
-        return $deprecations;
396
-    }
397
-
398
-    public function checkCase(\ReflectionClass $refl, $file, $class)
399
-    {
400
-        $real = explode('\\', $class.strrchr($file, '.'));
401
-        $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
402
-
403
-        $i = \count($tail) - 1;
404
-        $j = \count($real) - 1;
405
-
406
-        while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
407
-            --$i;
408
-            --$j;
409
-        }
410
-
411
-        array_splice($tail, 0, $i + 1);
412
-
413
-        if (!$tail) {
414
-            return;
415
-        }
416
-
417
-        $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
418
-        $tailLen = \strlen($tail);
419
-        $real = $refl->getFileName();
420
-
421
-        if (2 === self::$caseCheck) {
422
-            $real = $this->darwinRealpath($real);
423
-        }
424
-
425
-        if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
426
-            && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
427
-        ) {
428
-            return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
429
-        }
430
-    }
431
-
432
-    /**
433
-     * `realpath` on MacOSX doesn't normalize the case of characters.
434
-     */
435
-    private function darwinRealpath($real)
436
-    {
437
-        $i = 1 + strrpos($real, '/');
438
-        $file = substr($real, $i);
439
-        $real = substr($real, 0, $i);
440
-
441
-        if (isset(self::$darwinCache[$real])) {
442
-            $kDir = $real;
443
-        } else {
444
-            $kDir = strtolower($real);
445
-
446
-            if (isset(self::$darwinCache[$kDir])) {
447
-                $real = self::$darwinCache[$kDir][0];
448
-            } else {
449
-                $dir = getcwd();
450
-                chdir($real);
451
-                $real = getcwd().'/';
452
-                chdir($dir);
453
-
454
-                $dir = $real;
455
-                $k = $kDir;
456
-                $i = \strlen($dir) - 1;
457
-                while (!isset(self::$darwinCache[$k])) {
458
-                    self::$darwinCache[$k] = [$dir, []];
459
-                    self::$darwinCache[$dir] = &self::$darwinCache[$k];
460
-
461
-                    while ('/' !== $dir[--$i]) {
462
-                    }
463
-                    $k = substr($k, 0, ++$i);
464
-                    $dir = substr($dir, 0, $i--);
465
-                }
466
-            }
467
-        }
468
-
469
-        $dirFiles = self::$darwinCache[$kDir][1];
470
-
471
-        if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) {
472
-            // Get the file name from "file_name.php(123) : eval()'d code"
473
-            $file = substr($file, 0, strrpos($file, '(', -17));
474
-        }
475
-
476
-        if (isset($dirFiles[$file])) {
477
-            return $real .= $dirFiles[$file];
478
-        }
479
-
480
-        $kFile = strtolower($file);
481
-
482
-        if (!isset($dirFiles[$kFile])) {
483
-            foreach (scandir($real, 2) as $f) {
484
-                if ('.' !== $f[0]) {
485
-                    $dirFiles[$f] = $f;
486
-                    if ($f === $file) {
487
-                        $kFile = $k = $file;
488
-                    } elseif ($f !== $k = strtolower($f)) {
489
-                        $dirFiles[$k] = $f;
490
-                    }
491
-                }
492
-            }
493
-            self::$darwinCache[$kDir][1] = $dirFiles;
494
-        }
495
-
496
-        return $real .= $dirFiles[$kFile];
497
-    }
498
-
499
-    /**
500
-     * `class_implements` includes interfaces from the parents so we have to manually exclude them.
501
-     *
502
-     * @param string       $class
503
-     * @param string|false $parent
504
-     *
505
-     * @return string[]
506
-     */
507
-    private function getOwnInterfaces($class, $parent)
508
-    {
509
-        $ownInterfaces = class_implements($class, false);
510
-
511
-        if ($parent) {
512
-            foreach (class_implements($parent, false) as $interface) {
513
-                unset($ownInterfaces[$interface]);
514
-            }
515
-        }
516
-
517
-        foreach ($ownInterfaces as $interface) {
518
-            foreach (class_implements($interface) as $interface) {
519
-                unset($ownInterfaces[$interface]);
520
-            }
521
-        }
522
-
523
-        return $ownInterfaces;
524
-    }
525
-}
Browse code

initial commit

Emmanuel ROY authored on 09/08/2019 08:39:02
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,525 @@
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\Debug;
13
+
14
+use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
15
+
16
+/**
17
+ * Autoloader checking if the class is really defined in the file found.
18
+ *
19
+ * The ClassLoader will wrap all registered autoloaders
20
+ * and will throw an exception if a file is found but does
21
+ * not declare the class.
22
+ *
23
+ * @author Fabien Potencier <fabien@symfony.com>
24
+ * @author Christophe Coevoet <stof@notk.org>
25
+ * @author Nicolas Grekas <p@tchwork.com>
26
+ * @author Guilhem Niot <guilhem.niot@gmail.com>
27
+ */
28
+class DebugClassLoader
29
+{
30
+    private $classLoader;
31
+    private $isFinder;
32
+    private $loaded = [];
33
+    private static $caseCheck;
34
+    private static $checkedClasses = [];
35
+    private static $final = [];
36
+    private static $finalMethods = [];
37
+    private static $deprecated = [];
38
+    private static $internal = [];
39
+    private static $internalMethods = [];
40
+    private static $annotatedParameters = [];
41
+    private static $darwinCache = ['/' => ['/', []]];
42
+    private static $method = [];
43
+
44
+    public function __construct(callable $classLoader)
45
+    {
46
+        $this->classLoader = $classLoader;
47
+        $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
48
+
49
+        if (!isset(self::$caseCheck)) {
50
+            $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
51
+            $i = strrpos($file, \DIRECTORY_SEPARATOR);
52
+            $dir = substr($file, 0, 1 + $i);
53
+            $file = substr($file, 1 + $i);
54
+            $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
55
+            $test = realpath($dir.$test);
56
+
57
+            if (false === $test || false === $i) {
58
+                // filesystem is case sensitive
59
+                self::$caseCheck = 0;
60
+            } elseif (substr($test, -\strlen($file)) === $file) {
61
+                // filesystem is case insensitive and realpath() normalizes the case of characters
62
+                self::$caseCheck = 1;
63
+            } elseif (false !== stripos(PHP_OS, 'darwin')) {
64
+                // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
65
+                self::$caseCheck = 2;
66
+            } else {
67
+                // filesystem case checks failed, fallback to disabling them
68
+                self::$caseCheck = 0;
69
+            }
70
+        }
71
+    }
72
+
73
+    /**
74
+     * Gets the wrapped class loader.
75
+     *
76
+     * @return callable The wrapped class loader
77
+     */
78
+    public function getClassLoader()
79
+    {
80
+        return $this->classLoader;
81
+    }
82
+
83
+    /**
84
+     * Wraps all autoloaders.
85
+     */
86
+    public static function enable()
87
+    {
88
+        // Ensures we don't hit https://bugs.php.net/42098
89
+        class_exists('Symfony\Component\Debug\ErrorHandler');
90
+        class_exists('Psr\Log\LogLevel');
91
+
92
+        if (!\is_array($functions = spl_autoload_functions())) {
93
+            return;
94
+        }
95
+
96
+        foreach ($functions as $function) {
97
+            spl_autoload_unregister($function);
98
+        }
99
+
100
+        foreach ($functions as $function) {
101
+            if (!\is_array($function) || !$function[0] instanceof self) {
102
+                $function = [new static($function), 'loadClass'];
103
+            }
104
+
105
+            spl_autoload_register($function);
106
+        }
107
+    }
108
+
109
+    /**
110
+     * Disables the wrapping.
111
+     */
112
+    public static function disable()
113
+    {
114
+        if (!\is_array($functions = spl_autoload_functions())) {
115
+            return;
116
+        }
117
+
118
+        foreach ($functions as $function) {
119
+            spl_autoload_unregister($function);
120
+        }
121
+
122
+        foreach ($functions as $function) {
123
+            if (\is_array($function) && $function[0] instanceof self) {
124
+                $function = $function[0]->getClassLoader();
125
+            }
126
+
127
+            spl_autoload_register($function);
128
+        }
129
+    }
130
+
131
+    /**
132
+     * @return string|null
133
+     */
134
+    public function findFile($class)
135
+    {
136
+        return $this->isFinder ? $this->classLoader[0]->findFile($class) ?: null : null;
137
+    }
138
+
139
+    /**
140
+     * Loads the given class or interface.
141
+     *
142
+     * @param string $class The name of the class
143
+     *
144
+     * @throws \RuntimeException
145
+     */
146
+    public function loadClass($class)
147
+    {
148
+        $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
149
+
150
+        try {
151
+            if ($this->isFinder && !isset($this->loaded[$class])) {
152
+                $this->loaded[$class] = true;
153
+                if (!$file = $this->classLoader[0]->findFile($class) ?: false) {
154
+                    // no-op
155
+                } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
156
+                    include $file;
157
+
158
+                    return;
159
+                } elseif (false === include $file) {
160
+                    return;
161
+                }
162
+            } else {
163
+                ($this->classLoader)($class);
164
+                $file = false;
165
+            }
166
+        } finally {
167
+            error_reporting($e);
168
+        }
169
+
170
+        $this->checkClass($class, $file);
171
+    }
172
+
173
+    private function checkClass($class, $file = null)
174
+    {
175
+        $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
176
+
177
+        if (null !== $file && $class && '\\' === $class[0]) {
178
+            $class = substr($class, 1);
179
+        }
180
+
181
+        if ($exists) {
182
+            if (isset(self::$checkedClasses[$class])) {
183
+                return;
184
+            }
185
+            self::$checkedClasses[$class] = true;
186
+
187
+            $refl = new \ReflectionClass($class);
188
+            if (null === $file && $refl->isInternal()) {
189
+                return;
190
+            }
191
+            $name = $refl->getName();
192
+
193
+            if ($name !== $class && 0 === strcasecmp($name, $class)) {
194
+                throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
195
+            }
196
+
197
+            $deprecations = $this->checkAnnotations($refl, $name);
198
+
199
+            foreach ($deprecations as $message) {
200
+                @trigger_error($message, E_USER_DEPRECATED);
201
+            }
202
+        }
203
+
204
+        if (!$file) {
205
+            return;
206
+        }
207
+
208
+        if (!$exists) {
209
+            if (false !== strpos($class, '/')) {
210
+                throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class));
211
+            }
212
+
213
+            throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
214
+        }
215
+
216
+        if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) {
217
+            throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2]));
218
+        }
219
+    }
220
+
221
+    public function checkAnnotations(\ReflectionClass $refl, $class)
222
+    {
223
+        $deprecations = [];
224
+
225
+        // Don't trigger deprecations for classes in the same vendor
226
+        if (2 > $len = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) {
227
+            $len = 0;
228
+            $ns = '';
229
+        } else {
230
+            $ns = str_replace('_', '\\', substr($class, 0, $len));
231
+        }
232
+
233
+        // Detect annotations on the class
234
+        if (false !== $doc = $refl->getDocComment()) {
235
+            foreach (['final', 'deprecated', 'internal'] as $annotation) {
236
+                if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
237
+                    self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
238
+                }
239
+            }
240
+
241
+            if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) {
242
+                foreach ($notice as $method) {
243
+                    $static = '' !== $method[1];
244
+                    $name = $method[2];
245
+                    $description = $method[3] ?? null;
246
+                    if (false === strpos($name, '(')) {
247
+                        $name .= '()';
248
+                    }
249
+                    if (null !== $description) {
250
+                        $description = trim($description);
251
+                        if (!isset($method[4])) {
252
+                            $description .= '.';
253
+                        }
254
+                    }
255
+                    self::$method[$class][] = [$class, $name, $static, $description];
256
+                }
257
+            }
258
+        }
259
+
260
+        $parent = get_parent_class($class);
261
+        $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
262
+        if ($parent) {
263
+            $parentAndOwnInterfaces[$parent] = $parent;
264
+
265
+            if (!isset(self::$checkedClasses[$parent])) {
266
+                $this->checkClass($parent);
267
+            }
268
+
269
+            if (isset(self::$final[$parent])) {
270
+                $deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $class);
271
+            }
272
+        }
273
+
274
+        // Detect if the parent is annotated
275
+        foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) {
276
+            if (!isset(self::$checkedClasses[$use])) {
277
+                $this->checkClass($use);
278
+            }
279
+            if (isset(self::$deprecated[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) {
280
+                $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
281
+                $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
282
+
283
+                $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $class, $type, $verb, $use, self::$deprecated[$use]);
284
+            }
285
+            if (isset(self::$internal[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len)) {
286
+                $deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class);
287
+            }
288
+            if (isset(self::$method[$use])) {
289
+                if ($refl->isAbstract()) {
290
+                    if (isset(self::$method[$class])) {
291
+                        self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
292
+                    } else {
293
+                        self::$method[$class] = self::$method[$use];
294
+                    }
295
+                } elseif (!$refl->isInterface()) {
296
+                    $hasCall = $refl->hasMethod('__call');
297
+                    $hasStaticCall = $refl->hasMethod('__callStatic');
298
+                    foreach (self::$method[$use] as $method) {
299
+                        list($interface, $name, $static, $description) = $method;
300
+                        if ($static ? $hasStaticCall : $hasCall) {
301
+                            continue;
302
+                        }
303
+                        $realName = substr($name, 0, strpos($name, '('));
304
+                        if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) {
305
+                            $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $class, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description);
306
+                        }
307
+                    }
308
+                }
309
+            }
310
+        }
311
+
312
+        if (trait_exists($class)) {
313
+            return $deprecations;
314
+        }
315
+
316
+        // Inherit @final, @internal and @param annotations for methods
317
+        self::$finalMethods[$class] = [];
318
+        self::$internalMethods[$class] = [];
319
+        self::$annotatedParameters[$class] = [];
320
+        foreach ($parentAndOwnInterfaces as $use) {
321
+            foreach (['finalMethods', 'internalMethods', 'annotatedParameters'] as $property) {
322
+                if (isset(self::${$property}[$use])) {
323
+                    self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
324
+                }
325
+            }
326
+        }
327
+
328
+        foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
329
+            if ($method->class !== $class) {
330
+                continue;
331
+            }
332
+
333
+            if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
334
+                list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
335
+                $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
336
+            }
337
+
338
+            if (isset(self::$internalMethods[$class][$method->name])) {
339
+                list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
340
+                if (strncmp($ns, $declaringClass, $len)) {
341
+                    $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
342
+                }
343
+            }
344
+
345
+            // To read method annotations
346
+            $doc = $method->getDocComment();
347
+
348
+            if (isset(self::$annotatedParameters[$class][$method->name])) {
349
+                $definedParameters = [];
350
+                foreach ($method->getParameters() as $parameter) {
351
+                    $definedParameters[$parameter->name] = true;
352
+                }
353
+
354
+                foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
355
+                    if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) {
356
+                        $deprecations[] = sprintf($deprecation, $class);
357
+                    }
358
+                }
359
+            }
360
+
361
+            if (!$doc) {
362
+                continue;
363
+            }
364
+
365
+            $finalOrInternal = false;
366
+
367
+            foreach (['final', 'internal'] as $annotation) {
368
+                if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
369
+                    $message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
370
+                    self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
371
+                    $finalOrInternal = true;
372
+                }
373
+            }
374
+
375
+            if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) {
376
+                continue;
377
+            }
378
+            if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
379
+                continue;
380
+            }
381
+            if (!isset(self::$annotatedParameters[$class][$method->name])) {
382
+                $definedParameters = [];
383
+                foreach ($method->getParameters() as $parameter) {
384
+                    $definedParameters[$parameter->name] = true;
385
+                }
386
+            }
387
+            foreach ($matches as list(, $parameterType, $parameterName)) {
388
+                if (!isset($definedParameters[$parameterName])) {
389
+                    $parameterType = trim($parameterType);
390
+                    self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $method->class);
391
+                }
392
+            }
393
+        }
394
+
395
+        return $deprecations;
396
+    }
397
+
398
+    public function checkCase(\ReflectionClass $refl, $file, $class)
399
+    {
400
+        $real = explode('\\', $class.strrchr($file, '.'));
401
+        $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file));
402
+
403
+        $i = \count($tail) - 1;
404
+        $j = \count($real) - 1;
405
+
406
+        while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
407
+            --$i;
408
+            --$j;
409
+        }
410
+
411
+        array_splice($tail, 0, $i + 1);
412
+
413
+        if (!$tail) {
414
+            return;
415
+        }
416
+
417
+        $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
418
+        $tailLen = \strlen($tail);
419
+        $real = $refl->getFileName();
420
+
421
+        if (2 === self::$caseCheck) {
422
+            $real = $this->darwinRealpath($real);
423
+        }
424
+
425
+        if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
426
+            && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
427
+        ) {
428
+            return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
429
+        }
430
+    }
431
+
432
+    /**
433
+     * `realpath` on MacOSX doesn't normalize the case of characters.
434
+     */
435
+    private function darwinRealpath($real)
436
+    {
437
+        $i = 1 + strrpos($real, '/');
438
+        $file = substr($real, $i);
439
+        $real = substr($real, 0, $i);
440
+
441
+        if (isset(self::$darwinCache[$real])) {
442
+            $kDir = $real;
443
+        } else {
444
+            $kDir = strtolower($real);
445
+
446
+            if (isset(self::$darwinCache[$kDir])) {
447
+                $real = self::$darwinCache[$kDir][0];
448
+            } else {
449
+                $dir = getcwd();
450
+                chdir($real);
451
+                $real = getcwd().'/';
452
+                chdir($dir);
453
+
454
+                $dir = $real;
455
+                $k = $kDir;
456
+                $i = \strlen($dir) - 1;
457
+                while (!isset(self::$darwinCache[$k])) {
458
+                    self::$darwinCache[$k] = [$dir, []];
459
+                    self::$darwinCache[$dir] = &self::$darwinCache[$k];
460
+
461
+                    while ('/' !== $dir[--$i]) {
462
+                    }
463
+                    $k = substr($k, 0, ++$i);
464
+                    $dir = substr($dir, 0, $i--);
465
+                }
466
+            }
467
+        }
468
+
469
+        $dirFiles = self::$darwinCache[$kDir][1];
470
+
471
+        if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) {
472
+            // Get the file name from "file_name.php(123) : eval()'d code"
473
+            $file = substr($file, 0, strrpos($file, '(', -17));
474
+        }
475
+
476
+        if (isset($dirFiles[$file])) {
477
+            return $real .= $dirFiles[$file];
478
+        }
479
+
480
+        $kFile = strtolower($file);
481
+
482
+        if (!isset($dirFiles[$kFile])) {
483
+            foreach (scandir($real, 2) as $f) {
484
+                if ('.' !== $f[0]) {
485
+                    $dirFiles[$f] = $f;
486
+                    if ($f === $file) {
487
+                        $kFile = $k = $file;
488
+                    } elseif ($f !== $k = strtolower($f)) {
489
+                        $dirFiles[$k] = $f;
490
+                    }
491
+                }
492
+            }
493
+            self::$darwinCache[$kDir][1] = $dirFiles;
494
+        }
495
+
496
+        return $real .= $dirFiles[$kFile];
497
+    }
498
+
499
+    /**
500
+     * `class_implements` includes interfaces from the parents so we have to manually exclude them.
501
+     *
502
+     * @param string       $class
503
+     * @param string|false $parent
504
+     *
505
+     * @return string[]
506
+     */
507
+    private function getOwnInterfaces($class, $parent)
508
+    {
509
+        $ownInterfaces = class_implements($class, false);
510
+
511
+        if ($parent) {
512
+            foreach (class_implements($parent, false) as $interface) {
513
+                unset($ownInterfaces[$interface]);
514
+            }
515
+        }
516
+
517
+        foreach ($ownInterfaces as $interface) {
518
+            foreach (class_implements($interface) as $interface) {
519
+                unset($ownInterfaces[$interface]);
520
+            }
521
+        }
522
+
523
+        return $ownInterfaces;
524
+    }
525
+}