[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/symfony/dependency-injection/ -> ServiceLocator.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;
  13  
  14  use Psr\Container\ContainerInterface as PsrContainerInterface;
  15  use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
  16  use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  17  
  18  /**
  19   * @author Robin Chalas <robin.chalas@gmail.com>
  20   * @author Nicolas Grekas <p@tchwork.com>
  21   */
  22  class ServiceLocator implements PsrContainerInterface
  23  {
  24      private $factories;
  25      private $loading = [];
  26      private $externalId;
  27      private $container;
  28  
  29      /**
  30       * @param callable[] $factories
  31       */
  32      public function __construct(array $factories)
  33      {
  34          $this->factories = $factories;
  35      }
  36  
  37      /**
  38       * {@inheritdoc}
  39       */
  40      public function has($id)
  41      {
  42          return isset($this->factories[$id]);
  43      }
  44  
  45      /**
  46       * {@inheritdoc}
  47       */
  48      public function get($id)
  49      {
  50          if (!isset($this->factories[$id])) {
  51              throw new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $this->createServiceNotFoundMessage($id));
  52          }
  53  
  54          if (isset($this->loading[$id])) {
  55              $ids = array_values($this->loading);
  56              $ids = \array_slice($this->loading, array_search($id, $ids));
  57              $ids[] = $id;
  58  
  59              throw new ServiceCircularReferenceException($id, $ids);
  60          }
  61  
  62          $this->loading[$id] = $id;
  63          try {
  64              return $this->factories[$id]();
  65          } finally {
  66              unset($this->loading[$id]);
  67          }
  68      }
  69  
  70      public function __invoke($id)
  71      {
  72          return isset($this->factories[$id]) ? $this->get($id) : null;
  73      }
  74  
  75      /**
  76       * @internal
  77       */
  78      public function withContext($externalId, Container $container)
  79      {
  80          $locator = clone $this;
  81          $locator->externalId = $externalId;
  82          $locator->container = $container;
  83  
  84          return $locator;
  85      }
  86  
  87      private function createServiceNotFoundMessage($id)
  88      {
  89          if ($this->loading) {
  90              return sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives());
  91          }
  92  
  93          $class = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3);
  94          $class = isset($class[2]['object']) ? \get_class($class[2]['object']) : null;
  95          $externalId = $this->externalId ?: $class;
  96  
  97          $msg = [];
  98          $msg[] = sprintf('Service "%s" not found:', $id);
  99  
 100          if (!$this->container) {
 101              $class = null;
 102          } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) {
 103              $msg[] = 'even though it exists in the app\'s container,';
 104          } else {
 105              try {
 106                  $this->container->get($id);
 107                  $class = null;
 108              } catch (ServiceNotFoundException $e) {
 109                  if ($e->getAlternatives()) {
 110                      $msg[] = sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or'));
 111                  } else {
 112                      $class = null;
 113                  }
 114              }
 115          }
 116          if ($externalId) {
 117              $msg[] = sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives());
 118          } else {
 119              $msg[] = sprintf('the current service locator %s', $this->formatAlternatives());
 120          }
 121  
 122          if (!$class) {
 123              // no-op
 124          } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) {
 125              $msg[] = sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class));
 126          } else {
 127              $msg[] = 'Try using dependency injection instead.';
 128          }
 129  
 130          return implode(' ', $msg);
 131      }
 132  
 133      private function formatAlternatives(array $alternatives = null, $separator = 'and')
 134      {
 135          $format = '"%s"%s';
 136          if (null === $alternatives) {
 137              if (!$alternatives = array_keys($this->factories)) {
 138                  return 'is empty...';
 139              }
 140              $format = sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : '');
 141          }
 142          $last = array_pop($alternatives);
 143  
 144          return sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? sprintf(' %s "%s"', $separator, $last) : '');
 145      }
 146  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1