PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / prefixed / symfony / http-kernel / DependencyInjection / RegisterControllerArgumentLocatorsPass.php
matomo / app / vendor / prefixed / symfony / http-kernel / DependencyInjection Last commit date
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
RegisterControllerArgumentLocatorsPass.php
191 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 Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
14 use Symfony\Component\DependencyInjection\Attribute\Target;
15 use Symfony\Component\DependencyInjection\ChildDefinition;
16 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17 use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
18 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
19 use Symfony\Component\DependencyInjection\ContainerBuilder;
20 use Symfony\Component\DependencyInjection\ContainerInterface;
21 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
22 use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
23 use Symfony\Component\DependencyInjection\Reference;
24 use Symfony\Component\DependencyInjection\TypedReference;
25 use Matomo\Dependencies\Symfony\Component\HttpFoundation\Request;
26 use Matomo\Dependencies\Symfony\Component\HttpFoundation\Response;
27 use Matomo\Dependencies\Symfony\Component\HttpFoundation\Session\SessionInterface;
28 /**
29 * Creates the service-locators required by ServiceValueResolver.
30 *
31 * @author Nicolas Grekas <p@tchwork.com>
32 */
33 class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
34 {
35 private $resolverServiceId;
36 private $controllerTag;
37 private $controllerLocator;
38 private $notTaggedControllerResolverServiceId;
39 public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller')
40 {
41 if (0 < \func_num_args()) {
42 trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
43 }
44 $this->resolverServiceId = $resolverServiceId;
45 $this->controllerTag = $controllerTag;
46 $this->controllerLocator = $controllerLocator;
47 $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId;
48 }
49 public function process(ContainerBuilder $container)
50 {
51 if (\false === $container->hasDefinition($this->resolverServiceId) && \false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) {
52 return;
53 }
54 $parameterBag = $container->getParameterBag();
55 $controllers = [];
56 $publicAliases = [];
57 foreach ($container->getAliases() as $id => $alias) {
58 if ($alias->isPublic() && !$alias->isPrivate()) {
59 $publicAliases[(string) $alias][] = $id;
60 }
61 }
62 foreach ($container->findTaggedServiceIds($this->controllerTag, \true) as $id => $tags) {
63 $def = $container->getDefinition($id);
64 $def->setPublic(\true);
65 $def->setLazy(\false);
66 $class = $def->getClass();
67 $autowire = $def->isAutowired();
68 $bindings = $def->getBindings();
69 // resolve service class, taking parent definitions into account
70 while ($def instanceof ChildDefinition) {
71 $def = $container->findDefinition($def->getParent());
72 $class = $class ?: $def->getClass();
73 $bindings += $def->getBindings();
74 }
75 $class = $parameterBag->resolveValue($class);
76 if (!($r = $container->getReflectionClass($class))) {
77 throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
78 }
79 $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class);
80 // get regular public methods
81 $methods = [];
82 $arguments = [];
83 foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) {
84 if ('setContainer' === $r->name && $isContainerAware) {
85 continue;
86 }
87 if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) {
88 $methods[strtolower($r->name)] = [$r, $r->getParameters()];
89 }
90 }
91 // validate and collect explicit per-actions and per-arguments service references
92 foreach ($tags as $attributes) {
93 if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) {
94 $autowire = \true;
95 continue;
96 }
97 foreach (['action', 'argument', 'id'] as $k) {
98 if (!isset($attributes[$k][0])) {
99 throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id));
100 }
101 }
102 if (!isset($methods[$action = strtolower($attributes['action'])])) {
103 throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class));
104 }
105 [$r, $parameters] = $methods[$action];
106 $found = \false;
107 foreach ($parameters as $p) {
108 if ($attributes['argument'] === $p->name) {
109 if (!isset($arguments[$r->name][$p->name])) {
110 $arguments[$r->name][$p->name] = $attributes['id'];
111 }
112 $found = \true;
113 break;
114 }
115 }
116 if (!$found) {
117 throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class));
118 }
119 }
120 foreach ($methods as [$r, $parameters]) {
121 /** @var \ReflectionMethod $r */
122 // create a per-method map of argument-names to service/type-references
123 $args = [];
124 foreach ($parameters as $p) {
125 /** @var \ReflectionParameter $p */
126 $type = ltrim($target = (string) ProxyHelper::getTypeHint($r, $p), '\\');
127 $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
128 if (isset($arguments[$r->name][$p->name])) {
129 $target = $arguments[$r->name][$p->name];
130 if ('?' !== $target[0]) {
131 $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
132 } elseif ('' === ($target = (string) substr($target, 1))) {
133 throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id));
134 } elseif ($p->allowsNull() && !$p->isOptional()) {
135 $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
136 }
137 } elseif (isset($bindings[$bindingName = $type . ' $' . ($name = Target::parseName($p))]) || isset($bindings[$bindingName = '$' . $name]) || isset($bindings[$bindingName = $type])) {
138 $binding = $bindings[$bindingName];
139 [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues();
140 $binding->setValues([$bindingValue, $bindingId, \true, $bindingType, $bindingFile]);
141 if (!$bindingValue instanceof Reference) {
142 $args[$p->name] = new Reference('.value.' . $container->hash($bindingValue));
143 $container->register((string) $args[$p->name], 'mixed')->setFactory('current')->addArgument([$bindingValue]);
144 } else {
145 $args[$p->name] = $bindingValue;
146 }
147 continue;
148 } elseif (!$type || !$autowire || '\\' !== $target[0]) {
149 continue;
150 } elseif (is_subclass_of($type, \UnitEnum::class)) {
151 // do not attempt to register enum typed arguments if not already present in bindings
152 continue;
153 } elseif (!$p->allowsNull()) {
154 $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
155 }
156 if (Request::class === $type || SessionInterface::class === $type || Response::class === $type) {
157 continue;
158 }
159 if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, \false)) {
160 $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type);
161 // see if the type-hint lives in the same namespace as the controller
162 if (0 === strncmp($type, $class, strrpos($class, '\\'))) {
163 $message .= ' Did you forget to add a use statement?';
164 }
165 $container->register($erroredId = '.errored.' . $container->hash($message), $type)->addError($message);
166 $args[$p->name] = new Reference($erroredId, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE);
167 } else {
168 $target = ltrim($target, '\\');
169 $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, Target::parseName($p)) : new Reference($target, $invalidBehavior);
170 }
171 }
172 // register the maps as a per-method service-locators
173 if ($args) {
174 $controllers[$id . '::' . $r->name] = ServiceLocatorTagPass::register($container, $args);
175 foreach ($publicAliases[$id] ?? [] as $alias) {
176 $controllers[$alias . '::' . $r->name] = clone $controllers[$id . '::' . $r->name];
177 }
178 }
179 }
180 }
181 $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers);
182 if ($container->hasDefinition($this->resolverServiceId)) {
183 $container->getDefinition($this->resolverServiceId)->replaceArgument(0, $controllerLocatorRef);
184 }
185 if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) {
186 $container->getDefinition($this->notTaggedControllerResolverServiceId)->replaceArgument(0, $controllerLocatorRef);
187 }
188 $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef);
189 }
190 }
191