[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ -> CheckReferenceValidityPass.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\Definition;
  15  use Symfony\Component\DependencyInjection\ContainerInterface;
  16  use Symfony\Component\DependencyInjection\Reference;
  17  use Symfony\Component\DependencyInjection\ContainerBuilder;
  18  use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  19  use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
  20  use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
  21  
  22  /**
  23   * Checks the validity of references.
  24   *
  25   * The following checks are performed by this pass:
  26   * - target definitions are not abstract
  27   * - target definitions are of equal or wider scope
  28   * - target definitions are in the same scope hierarchy
  29   *
  30   * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  31   */
  32  class CheckReferenceValidityPass implements CompilerPassInterface
  33  {
  34      private $container;
  35      private $currentId;
  36      private $currentDefinition;
  37      private $currentScope;
  38      private $currentScopeAncestors;
  39      private $currentScopeChildren;
  40  
  41      /**
  42       * Processes the ContainerBuilder to validate References.
  43       *
  44       * @param ContainerBuilder $container
  45       */
  46      public function process(ContainerBuilder $container)
  47      {
  48          $this->container = $container;
  49  
  50          $children = $this->container->getScopeChildren();
  51          $ancestors = array();
  52  
  53          $scopes = $this->container->getScopes();
  54          foreach ($scopes as $name => $parent) {
  55              $ancestors[$name] = array($parent);
  56  
  57              while (isset($scopes[$parent])) {
  58                  $ancestors[$name][] = $parent = $scopes[$parent];
  59              }
  60          }
  61  
  62          foreach ($container->getDefinitions() as $id => $definition) {
  63              if ($definition->isSynthetic() || $definition->isAbstract()) {
  64                  continue;
  65              }
  66  
  67              $this->currentId = $id;
  68              $this->currentDefinition = $definition;
  69              $this->currentScope = $scope = $definition->getScope();
  70  
  71              if (ContainerInterface::SCOPE_CONTAINER === $scope) {
  72                  $this->currentScopeChildren = array_keys($scopes);
  73                  $this->currentScopeAncestors = array();
  74              } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
  75                  $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
  76                  $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
  77              }
  78  
  79              $this->validateReferences($definition->getArguments());
  80              $this->validateReferences($definition->getMethodCalls());
  81              $this->validateReferences($definition->getProperties());
  82          }
  83      }
  84  
  85      /**
  86       * Validates an array of References.
  87       *
  88       * @param array $arguments An array of Reference objects
  89       *
  90       * @throws RuntimeException when there is a reference to an abstract definition.
  91       */
  92      private function validateReferences(array $arguments)
  93      {
  94          foreach ($arguments as $argument) {
  95              if (is_array($argument)) {
  96                  $this->validateReferences($argument);
  97              } elseif ($argument instanceof Reference) {
  98                  $targetDefinition = $this->getDefinition((string) $argument);
  99  
 100                  if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
 101                      throw new RuntimeException(sprintf(
 102                          'The definition "%s" has a reference to an abstract definition "%s". '
 103                         .'Abstract definitions cannot be the target of references.',
 104                         $this->currentId,
 105                         $argument
 106                      ));
 107                  }
 108  
 109                  $this->validateScope($argument, $targetDefinition);
 110              }
 111          }
 112      }
 113  
 114      /**
 115       * Validates the scope of a single Reference.
 116       *
 117       * @param Reference  $reference
 118       * @param Definition $definition
 119       *
 120       * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
 121       * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
 122       */
 123      private function validateScope(Reference $reference, Definition $definition = null)
 124      {
 125          if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
 126              return;
 127          }
 128  
 129          if (!$reference->isStrict()) {
 130              return;
 131          }
 132  
 133          if (null === $definition) {
 134              return;
 135          }
 136  
 137          if ($this->currentScope === $scope = $definition->getScope()) {
 138              return;
 139          }
 140  
 141          $id = (string) $reference;
 142  
 143          if (in_array($scope, $this->currentScopeChildren, true)) {
 144              throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
 145          }
 146  
 147          if (!in_array($scope, $this->currentScopeAncestors, true)) {
 148              throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
 149          }
 150      }
 151  
 152      /**
 153       * Returns the Definition given an id.
 154       *
 155       * @param string $id Definition identifier
 156       *
 157       * @return Definition
 158       */
 159      private function getDefinition($id)
 160      {
 161          if (!$this->container->hasDefinition($id)) {
 162              return;
 163          }
 164  
 165          return $this->container->getDefinition($id);
 166      }
 167  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1