[ Index ]

PHP Cross Reference of phpBB-3.3.7-deutsch

title

Body

[close]

/vendor/symfony/dependency-injection/Compiler/ -> ServiceLocatorTagPass.php (source)

   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\DependencyInjection\Compiler;
  13  
  14  use Symfony\Component\DependencyInjection\Alias;
  15  use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
  16  use Symfony\Component\DependencyInjection\ContainerBuilder;
  17  use Symfony\Component\DependencyInjection\Definition;
  18  use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  19  use Symfony\Component\DependencyInjection\Reference;
  20  use Symfony\Component\DependencyInjection\ServiceLocator;
  21  
  22  /**
  23   * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances.
  24   *
  25   * @author Nicolas Grekas <p@tchwork.com>
  26   */
  27  final class ServiceLocatorTagPass extends AbstractRecursivePass
  28  {
  29      protected function processValue($value, $isRoot = false)
  30      {
  31          if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
  32              return parent::processValue($value, $isRoot);
  33          }
  34  
  35          if (!$value->getClass()) {
  36              $value->setClass(ServiceLocator::class);
  37          }
  38  
  39          $arguments = $value->getArguments();
  40          if (!isset($arguments[0]) || !\is_array($arguments[0])) {
  41              throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
  42          }
  43  
  44          $i = 0;
  45  
  46          foreach ($arguments[0] as $k => $v) {
  47              if ($v instanceof ServiceClosureArgument) {
  48                  continue;
  49              }
  50              if (!$v instanceof Reference) {
  51                  throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k));
  52              }
  53  
  54              if ($i === $k) {
  55                  unset($arguments[0][$k]);
  56  
  57                  $k = (string) $v;
  58                  ++$i;
  59              } elseif (\is_int($k)) {
  60                  $i = null;
  61              }
  62              $arguments[0][$k] = new ServiceClosureArgument($v);
  63          }
  64          ksort($arguments[0]);
  65  
  66          $value->setArguments($arguments);
  67  
  68          $id = 'service_locator.'.ContainerBuilder::hash($value);
  69  
  70          if ($isRoot) {
  71              if ($id !== $this->currentId) {
  72                  $this->container->setAlias($id, new Alias($this->currentId, false));
  73              }
  74  
  75              return $value;
  76          }
  77  
  78          $this->container->setDefinition($id, $value->setPublic(false));
  79  
  80          return new Reference($id);
  81      }
  82  
  83      /**
  84       * @param Reference[] $refMap
  85       * @param string|null $callerId
  86       *
  87       * @return Reference
  88       */
  89      public static function register(ContainerBuilder $container, array $refMap, $callerId = null)
  90      {
  91          foreach ($refMap as $id => $ref) {
  92              if (!$ref instanceof Reference) {
  93                  throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', \is_object($ref) ? \get_class($ref) : \gettype($ref), $id));
  94              }
  95              $refMap[$id] = new ServiceClosureArgument($ref);
  96          }
  97          ksort($refMap);
  98  
  99          $locator = (new Definition(ServiceLocator::class))
 100              ->addArgument($refMap)
 101              ->setPublic(false)
 102              ->addTag('container.service_locator');
 103  
 104          if (null !== $callerId && $container->hasDefinition($callerId)) {
 105              $locator->setBindings($container->getDefinition($callerId)->getBindings());
 106          }
 107  
 108          if (!$container->hasDefinition($id = 'service_locator.'.ContainerBuilder::hash($locator))) {
 109              $container->setDefinition($id, $locator);
 110          }
 111  
 112          if (null !== $callerId) {
 113              $locatorId = $id;
 114              // Locators are shared when they hold the exact same list of factories;
 115              // to have them specialized per consumer service, we use a cloning factory
 116              // to derivate customized instances from the prototype one.
 117              $container->register($id .= '.'.$callerId, ServiceLocator::class)
 118                  ->setPublic(false)
 119                  ->setFactory([new Reference($locatorId), 'withContext'])
 120                  ->addArgument($callerId)
 121                  ->addArgument(new Reference('service_container'));
 122          }
 123  
 124          return new Reference($id);
 125      }
 126  }


Generated: Thu Mar 24 21:31:15 2022 Cross-referenced by PHPXref 0.7.1