matomo
/
app
/
vendor
/
prefixed
/
symfony
/
http-kernel
/
DependencyInjection
/
AddAnnotatedClassesToCachePass.php
AddAnnotatedClassesToCachePass.php
1 year ago
ConfigurableExtension.php
2 years ago
ControllerArgumentValueResolverPass.php
2 years ago
Extension.php
2 years ago
FragmentRendererPass.php
1 year ago
LazyLoadingFragmentHandler.php
1 year ago
LoggerPass.php
1 year ago
MergeExtensionConfigurationPass.php
2 years ago
RegisterControllerArgumentLocatorsPass.php
1 year ago
RegisterLocaleAwareServicesPass.php
2 years ago
RemoveEmptyControllerArgumentLocatorsPass.php
1 year ago
ResettableServicePass.php
1 year ago
ServicesResetter.php
2 years ago
AddAnnotatedClassesToCachePass.php
119 lines
| 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 | namespace Matomo\Dependencies\Symfony\Component\HttpKernel\DependencyInjection; |
| 12 | |
| 13 | use Composer\Autoload\ClassLoader; |
| 14 | use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; |
| 15 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; |
| 16 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
| 17 | use Matomo\Dependencies\Symfony\Component\ErrorHandler\DebugClassLoader; |
| 18 | use Matomo\Dependencies\Symfony\Component\HttpKernel\Kernel; |
| 19 | /** |
| 20 | * Sets the classes to compile in the cache for the container. |
| 21 | * |
| 22 | * @author Fabien Potencier <fabien@symfony.com> |
| 23 | */ |
| 24 | class AddAnnotatedClassesToCachePass implements CompilerPassInterface |
| 25 | { |
| 26 | private $kernel; |
| 27 | public function __construct(Kernel $kernel) |
| 28 | { |
| 29 | $this->kernel = $kernel; |
| 30 | } |
| 31 | /** |
| 32 | * {@inheritdoc} |
| 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 | $annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses); |
| 43 | $existingClasses = $this->getClassesInComposerClassMaps(); |
| 44 | $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); |
| 45 | $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); |
| 46 | } |
| 47 | /** |
| 48 | * Expands the given class patterns using a list of existing classes. |
| 49 | * |
| 50 | * @param array $patterns The class patterns to expand |
| 51 | * @param array $classes The existing classes to match against the patterns |
| 52 | */ |
| 53 | private function expandClasses(array $patterns, array $classes) : array |
| 54 | { |
| 55 | $expanded = []; |
| 56 | // Explicit classes declared in the patterns are returned directly |
| 57 | foreach ($patterns as $key => $pattern) { |
| 58 | if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) { |
| 59 | unset($patterns[$key]); |
| 60 | $expanded[] = ltrim($pattern, '\\'); |
| 61 | } |
| 62 | } |
| 63 | // Match patterns with the classes list |
| 64 | $regexps = $this->patternsToRegexps($patterns); |
| 65 | foreach ($classes as $class) { |
| 66 | $class = ltrim($class, '\\'); |
| 67 | if ($this->matchAnyRegexps($class, $regexps)) { |
| 68 | $expanded[] = $class; |
| 69 | } |
| 70 | } |
| 71 | return array_unique($expanded); |
| 72 | } |
| 73 | private function getClassesInComposerClassMaps() : array |
| 74 | { |
| 75 | $classes = []; |
| 76 | foreach (spl_autoload_functions() as $function) { |
| 77 | if (!\is_array($function)) { |
| 78 | continue; |
| 79 | } |
| 80 | if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) { |
| 81 | $function = $function[0]->getClassLoader(); |
| 82 | } |
| 83 | if (\is_array($function) && $function[0] instanceof ClassLoader) { |
| 84 | $classes += array_filter($function[0]->getClassMap()); |
| 85 | } |
| 86 | } |
| 87 | return array_keys($classes); |
| 88 | } |
| 89 | private function patternsToRegexps(array $patterns) : array |
| 90 | { |
| 91 | $regexps = []; |
| 92 | foreach ($patterns as $pattern) { |
| 93 | // Escape user input |
| 94 | $regex = preg_quote(ltrim($pattern, '\\')); |
| 95 | // Wildcards * and ** |
| 96 | $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); |
| 97 | // If this class does not end by a slash, anchor the end |
| 98 | if ('\\' !== substr($regex, -1)) { |
| 99 | $regex .= '$'; |
| 100 | } |
| 101 | $regexps[] = '{^\\\\' . $regex . '}'; |
| 102 | } |
| 103 | return $regexps; |
| 104 | } |
| 105 | private function matchAnyRegexps(string $class, array $regexps) : bool |
| 106 | { |
| 107 | $isTest = str_contains($class, 'Test'); |
| 108 | foreach ($regexps as $regex) { |
| 109 | if ($isTest && !str_contains($regex, 'Test')) { |
| 110 | continue; |
| 111 | } |
| 112 | if (preg_match($regex, '\\' . $class)) { |
| 113 | return \true; |
| 114 | } |
| 115 | } |
| 116 | return \false; |
| 117 | } |
| 118 | } |
| 119 |