annotate vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\HttpKernel\DependencyInjection;
Chris@0 13
Chris@0 14 use Composer\Autoload\ClassLoader;
Chris@0 15 use Symfony\Component\Debug\DebugClassLoader;
Chris@0 16 use Symfony\Component\DependencyInjection\ContainerBuilder;
Chris@0 17 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
Chris@0 18 use Symfony\Component\HttpKernel\Kernel;
Chris@0 19
Chris@0 20 /**
Chris@0 21 * Sets the classes to compile in the cache for the container.
Chris@0 22 *
Chris@0 23 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 24 */
Chris@0 25 class AddClassesToCachePass implements CompilerPassInterface
Chris@0 26 {
Chris@0 27 private $kernel;
Chris@0 28
Chris@0 29 public function __construct(Kernel $kernel)
Chris@0 30 {
Chris@0 31 $this->kernel = $kernel;
Chris@0 32 }
Chris@0 33
Chris@0 34 /**
Chris@0 35 * {@inheritdoc}
Chris@0 36 */
Chris@0 37 public function process(ContainerBuilder $container)
Chris@0 38 {
Chris@0 39 $classes = array();
Chris@0 40 $annotatedClasses = array();
Chris@0 41 foreach ($container->getExtensions() as $extension) {
Chris@0 42 if ($extension instanceof Extension) {
Chris@0 43 $classes = array_merge($classes, $extension->getClassesToCompile());
Chris@0 44 $annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile());
Chris@0 45 }
Chris@0 46 }
Chris@0 47
Chris@0 48 $classes = $container->getParameterBag()->resolveValue($classes);
Chris@0 49 $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses);
Chris@0 50 $existingClasses = $this->getClassesInComposerClassMaps();
Chris@0 51
Chris@0 52 $this->kernel->setClassCache($this->expandClasses($classes, $existingClasses));
Chris@0 53 $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses));
Chris@0 54 }
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Expands the given class patterns using a list of existing classes.
Chris@0 58 *
Chris@0 59 * @param array $patterns The class patterns to expand
Chris@0 60 * @param array $classes The existing classes to match against the patterns
Chris@0 61 *
Chris@0 62 * @return array A list of classes derivated from the patterns
Chris@0 63 */
Chris@0 64 private function expandClasses(array $patterns, array $classes)
Chris@0 65 {
Chris@0 66 $expanded = array();
Chris@0 67
Chris@0 68 // Explicit classes declared in the patterns are returned directly
Chris@0 69 foreach ($patterns as $key => $pattern) {
Chris@0 70 if (substr($pattern, -1) !== '\\' && false === strpos($pattern, '*')) {
Chris@0 71 unset($patterns[$key]);
Chris@0 72 $expanded[] = ltrim($pattern, '\\');
Chris@0 73 }
Chris@0 74 }
Chris@0 75
Chris@0 76 // Match patterns with the classes list
Chris@0 77 $regexps = $this->patternsToRegexps($patterns);
Chris@0 78
Chris@0 79 foreach ($classes as $class) {
Chris@0 80 $class = ltrim($class, '\\');
Chris@0 81
Chris@0 82 if ($this->matchAnyRegexps($class, $regexps)) {
Chris@0 83 $expanded[] = $class;
Chris@0 84 }
Chris@0 85 }
Chris@0 86
Chris@0 87 return array_unique($expanded);
Chris@0 88 }
Chris@0 89
Chris@0 90 private function getClassesInComposerClassMaps()
Chris@0 91 {
Chris@0 92 $classes = array();
Chris@0 93
Chris@0 94 foreach (spl_autoload_functions() as $function) {
Chris@0 95 if (!is_array($function)) {
Chris@0 96 continue;
Chris@0 97 }
Chris@0 98
Chris@0 99 if ($function[0] instanceof DebugClassLoader) {
Chris@0 100 $function = $function[0]->getClassLoader();
Chris@0 101 }
Chris@0 102
Chris@0 103 if (is_array($function) && $function[0] instanceof ClassLoader) {
Chris@0 104 $classes += array_filter($function[0]->getClassMap());
Chris@0 105 }
Chris@0 106 }
Chris@0 107
Chris@0 108 return array_keys($classes);
Chris@0 109 }
Chris@0 110
Chris@0 111 private function patternsToRegexps($patterns)
Chris@0 112 {
Chris@0 113 $regexps = array();
Chris@0 114
Chris@0 115 foreach ($patterns as $pattern) {
Chris@0 116 // Escape user input
Chris@0 117 $regex = preg_quote(ltrim($pattern, '\\'));
Chris@0 118
Chris@0 119 // Wildcards * and **
Chris@0 120 $regex = strtr($regex, array('\\*\\*' => '.*?', '\\*' => '[^\\\\]*?'));
Chris@0 121
Chris@0 122 // If this class does not end by a slash, anchor the end
Chris@0 123 if (substr($regex, -1) !== '\\') {
Chris@0 124 $regex .= '$';
Chris@0 125 }
Chris@0 126
Chris@0 127 $regexps[] = '{^\\\\'.$regex.'}';
Chris@0 128 }
Chris@0 129
Chris@0 130 return $regexps;
Chris@0 131 }
Chris@0 132
Chris@0 133 private function matchAnyRegexps($class, $regexps)
Chris@0 134 {
Chris@0 135 $blacklisted = false !== strpos($class, 'Test');
Chris@0 136
Chris@0 137 foreach ($regexps as $regex) {
Chris@0 138 if ($blacklisted && false === strpos($regex, 'Test')) {
Chris@0 139 continue;
Chris@0 140 }
Chris@0 141
Chris@0 142 if (preg_match($regex, '\\'.$class)) {
Chris@0 143 return true;
Chris@0 144 }
Chris@0 145 }
Chris@0 146
Chris@0 147 return false;
Chris@0 148 }
Chris@0 149 }