Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 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\HttpKernel\DependencyInjection;
13
 
14
use Composer\Autoload\ClassLoader;
15
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\ErrorHandler\DebugClassLoader;
18
use Symfony\Component\HttpKernel\Kernel;
19
 
20
/**
21
 * Sets the classes to compile in the cache for the container.
22
 *
23
 * @author Fabien Potencier <fabien@symfony.com>
24
 */
25
class AddAnnotatedClassesToCachePass implements CompilerPassInterface
26
{
27
    private Kernel $kernel;
28
 
29
    public function __construct(Kernel $kernel)
30
    {
31
        $this->kernel = $kernel;
32
    }
33
 
34
    public function process(ContainerBuilder $container)
35
    {
36
        $annotatedClasses = [];
37
        foreach ($container->getExtensions() as $extension) {
38
            if ($extension instanceof Extension) {
39
                $annotatedClasses[] = $extension->getAnnotatedClassesToCompile();
40
            }
41
        }
42
 
43
        $annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses);
44
 
45
        $existingClasses = $this->getClassesInComposerClassMaps();
46
 
47
        $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses);
48
        $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses));
49
    }
50
 
51
    /**
52
     * Expands the given class patterns using a list of existing classes.
53
     *
54
     * @param array $patterns The class patterns to expand
55
     * @param array $classes  The existing classes to match against the patterns
56
     */
57
    private function expandClasses(array $patterns, array $classes): array
58
    {
59
        $expanded = [];
60
 
61
        // Explicit classes declared in the patterns are returned directly
62
        foreach ($patterns as $key => $pattern) {
63
            if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) {
64
                unset($patterns[$key]);
65
                $expanded[] = ltrim($pattern, '\\');
66
            }
67
        }
68
 
69
        // Match patterns with the classes list
70
        $regexps = $this->patternsToRegexps($patterns);
71
 
72
        foreach ($classes as $class) {
73
            $class = ltrim($class, '\\');
74
 
75
            if ($this->matchAnyRegexps($class, $regexps)) {
76
                $expanded[] = $class;
77
            }
78
        }
79
 
80
        return array_unique($expanded);
81
    }
82
 
83
    private function getClassesInComposerClassMaps(): array
84
    {
85
        $classes = [];
86
 
87
        foreach (spl_autoload_functions() as $function) {
88
            if (!\is_array($function)) {
89
                continue;
90
            }
91
 
92
            if ($function[0] instanceof DebugClassLoader) {
93
                $function = $function[0]->getClassLoader();
94
            }
95
 
96
            if (\is_array($function) && $function[0] instanceof ClassLoader) {
97
                $classes += array_filter($function[0]->getClassMap());
98
            }
99
        }
100
 
101
        return array_keys($classes);
102
    }
103
 
104
    private function patternsToRegexps(array $patterns): array
105
    {
106
        $regexps = [];
107
 
108
        foreach ($patterns as $pattern) {
109
            // Escape user input
110
            $regex = preg_quote(ltrim($pattern, '\\'));
111
 
112
            // Wildcards * and **
113
            $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']);
114
 
115
            // If this class does not end by a slash, anchor the end
116
            if (!str_ends_with($regex, '\\')) {
117
                $regex .= '$';
118
            }
119
 
120
            $regexps[] = '{^\\\\'.$regex.'}';
121
        }
122
 
123
        return $regexps;
124
    }
125
 
126
    private function matchAnyRegexps(string $class, array $regexps): bool
127
    {
128
        $isTest = str_contains($class, 'Test');
129
 
130
        foreach ($regexps as $regex) {
131
            if ($isTest && !str_contains($regex, 'Test')) {
132
                continue;
133
            }
134
 
135
            if (preg_match($regex, '\\'.$class)) {
136
                return true;
137
            }
138
        }
139
 
140
        return false;
141
    }
142
}