Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

RegisterControllerArgumentLocatorsPass.php

Zuletzt modifiziert: 01.05.2026, 11:27 - Dateigröße: 8.29 KiB


 001  <?php
 002   
 003  /*
 004   * This file is part of the Symfony package.
 005   *
 006   * (c) Fabien Potencier <fabien@symfony.com>
 007   *
 008   * For the full copyright and license information, please view the LICENSE
 009   * file that was distributed with this source code.
 010   */
 011   
 012  namespace Symfony\Component\HttpKernel\DependencyInjection;
 013   
 014  use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 015  use Symfony\Component\DependencyInjection\ChildDefinition;
 016  use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 017  use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
 018  use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 019  use Symfony\Component\DependencyInjection\ContainerBuilder;
 020  use Symfony\Component\DependencyInjection\ContainerInterface;
 021  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
 022  use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
 023  use Symfony\Component\DependencyInjection\Reference;
 024  use Symfony\Component\DependencyInjection\TypedReference;
 025  use Symfony\Component\HttpFoundation\Request;
 026   
 027  /**
 028   * Creates the service-locators required by ServiceValueResolver.
 029   *
 030   * @author Nicolas Grekas <p@tchwork.com>
 031   */
 032  class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
 033  {
 034      private $resolverServiceId;
 035      private $controllerTag;
 036   
 037      public function __construct($resolverServiceId = 'argument_resolver.service', $controllerTag = 'controller.service_arguments')
 038      {
 039          $this->resolverServiceId = $resolverServiceId;
 040          $this->controllerTag = $controllerTag;
 041      }
 042   
 043      public function process(ContainerBuilder $container)
 044      {
 045          if (false === $container->hasDefinition($this->resolverServiceId)) {
 046              return;
 047          }
 048   
 049          $parameterBag = $container->getParameterBag();
 050          $controllers = [];
 051   
 052          foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) {
 053              $def = $container->getDefinition($id);
 054              $def->setPublic(true);
 055              $class = $def->getClass();
 056              $autowire = $def->isAutowired();
 057              $bindings = $def->getBindings();
 058   
 059              // resolve service class, taking parent definitions into account
 060              while ($def instanceof ChildDefinition) {
 061                  $def = $container->findDefinition($def->getParent());
 062                  $class = $class ?: $def->getClass();
 063                  $bindings += $def->getBindings();
 064              }
 065              $class = $parameterBag->resolveValue($class);
 066   
 067              if (!$r = $container->getReflectionClass($class)) {
 068                  throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
 069              }
 070              $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class);
 071   
 072              // get regular public methods
 073              $methods = [];
 074              $arguments = [];
 075              foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) {
 076                  if ('setContainer' === $r->name && $isContainerAware) {
 077                      continue;
 078                  }
 079                  if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) {
 080                      $methods[strtolower($r->name)] = [$r, $r->getParameters()];
 081                  }
 082              }
 083   
 084              // validate and collect explicit per-actions and per-arguments service references
 085              foreach ($tags as $attributes) {
 086                  if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) {
 087                      $autowire = true;
 088                      continue;
 089                  }
 090                  foreach (['action', 'argument', 'id'] as $k) {
 091                      if (!isset($attributes[$k][0])) {
 092                          throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id));
 093                      }
 094                  }
 095                  if (!isset($methods[$action = strtolower($attributes['action'])])) {
 096                      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));
 097                  }
 098                  list($r, $parameters) = $methods[$action];
 099                  $found = false;
 100   
 101                  foreach ($parameters as $p) {
 102                      if ($attributes['argument'] === $p->name) {
 103                          if (!isset($arguments[$r->name][$p->name])) {
 104                              $arguments[$r->name][$p->name] = $attributes['id'];
 105                          }
 106                          $found = true;
 107                          break;
 108                      }
 109                  }
 110   
 111                  if (!$found) {
 112                      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));
 113                  }
 114              }
 115   
 116              foreach ($methods as list($r, $parameters)) {
 117                  /** @var \ReflectionMethod $r */
 118   
 119                  // create a per-method map of argument-names to service/type-references
 120                  $args = [];
 121                  foreach ($parameters as $p) {
 122                      /** @var \ReflectionParameter $p */
 123                      $type = $target = ProxyHelper::getTypeHint($r, $p, true);
 124                      $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
 125   
 126                      if (isset($arguments[$r->name][$p->name])) {
 127                          $target = $arguments[$r->name][$p->name];
 128                          if ('?' !== $target[0]) {
 129                              $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
 130                          } elseif ('' === $target = (string) substr($target, 1)) {
 131                              throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id));
 132                          } elseif ($p->allowsNull() && !$p->isOptional()) {
 133                              $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
 134                          }
 135                      } elseif (isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) {
 136                          $binding = $bindings[$bindingName];
 137   
 138                          list($bindingValue, $bindingId) = $binding->getValues();
 139   
 140                          if (!$bindingValue instanceof Reference) {
 141                              continue;
 142                          }
 143   
 144                          $binding->setValues([$bindingValue, $bindingId, true]);
 145                          $args[$p->name] = $bindingValue;
 146   
 147                          continue;
 148                      } elseif (!$type || !$autowire) {
 149                          continue;
 150                      }
 151   
 152                      if (Request::class === $type) {
 153                          continue;
 154                      }
 155   
 156                      if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) {
 157                          $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);
 158   
 159                          // see if the type-hint lives in the same namespace as the controller
 160                          if (0 === strncmp($type, $class, strrpos($class, '\\'))) {
 161                              $message .= ' Did you forget to add a use statement?';
 162                          }
 163   
 164                          throw new InvalidArgumentException($message);
 165                      }
 166   
 167                      $args[$p->name] = $type ? new TypedReference($target, $type, $r->class, $invalidBehavior) : new Reference($target, $invalidBehavior);
 168                  }
 169                  // register the maps as a per-method service-locators
 170                  if ($args) {
 171                      $controllers[$id.':'.$r->name] = ServiceLocatorTagPass::register($container, $args);
 172                  }
 173              }
 174          }
 175   
 176          $container->getDefinition($this->resolverServiceId)
 177              ->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers));
 178      }
 179  }
 180