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