vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php line 60

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\DependencyInjection\Compiler;
  11. use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
  12. use Symfony\Component\DependencyInjection\ContainerBuilder;
  13. use Symfony\Component\DependencyInjection\Definition;
  14. use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  15. use Symfony\Component\DependencyInjection\Reference;
  16. /**
  17.  * @author Nicolas Grekas <p@tchwork.com>
  18.  */
  19. abstract class AbstractRecursivePass implements CompilerPassInterface
  20. {
  21.     /**
  22.      * @var ContainerBuilder
  23.      */
  24.     protected $container;
  25.     protected $currentId;
  26.     /**
  27.      * {@inheritdoc}
  28.      */
  29.     public function process(ContainerBuilder $container)
  30.     {
  31.         $this->container $container;
  32.         try {
  33.             $this->processValue($container->getDefinitions(), true);
  34.         } finally {
  35.             $this->container null;
  36.         }
  37.     }
  38.     /**
  39.      * Processes a value found in a definition tree.
  40.      *
  41.      * @param mixed $value
  42.      * @param bool  $isRoot
  43.      *
  44.      * @return mixed The processed value
  45.      */
  46.     protected function processValue($value$isRoot false)
  47.     {
  48.         if (\is_array($value)) {
  49.             foreach ($value as $k => $v) {
  50.                 if ($isRoot) {
  51.                     $this->currentId $k;
  52.                 }
  53.                 if ($v !== $processedValue $this->processValue($v$isRoot)) {
  54.                     $value[$k] = $processedValue;
  55.                 }
  56.             }
  57.         } elseif ($value instanceof ArgumentInterface) {
  58.             $value->setValues($this->processValue($value->getValues()));
  59.         } elseif ($value instanceof Definition) {
  60.             $value->setArguments($this->processValue($value->getArguments()));
  61.             $value->setProperties($this->processValue($value->getProperties()));
  62.             $value->setMethodCalls($this->processValue($value->getMethodCalls()));
  63.             $changes $value->getChanges();
  64.             if (isset($changes['factory'])) {
  65.                 $value->setFactory($this->processValue($value->getFactory()));
  66.             }
  67.             if (isset($changes['configurator'])) {
  68.                 $value->setConfigurator($this->processValue($value->getConfigurator()));
  69.             }
  70.         }
  71.         return $value;
  72.     }
  73.     /**
  74.      * @param bool $required
  75.      *
  76.      * @return \ReflectionFunctionAbstract|null
  77.      *
  78.      * @throws RuntimeException
  79.      */
  80.     protected function getConstructor(Definition $definition$required)
  81.     {
  82.         if ($definition->isSynthetic()) {
  83.             return null;
  84.         }
  85.         if (\is_string($factory $definition->getFactory())) {
  86.             if (!\function_exists($factory)) {
  87.                 throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.'$this->currentId$factory));
  88.             }
  89.             $r = new \ReflectionFunction($factory);
  90.             if (false !== $r->getFileName() && file_exists($r->getFileName())) {
  91.                 $this->container->fileExists($r->getFileName());
  92.             }
  93.             return $r;
  94.         }
  95.         if ($factory) {
  96.             list($class$method) = $factory;
  97.             if ($class instanceof Reference) {
  98.                 $class $this->container->findDefinition((string) $class)->getClass();
  99.             } elseif (null === $class) {
  100.                 $class $definition->getClass();
  101.             }
  102.             if ('__construct' === $method) {
  103.                 throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.'$this->currentId));
  104.             }
  105.             return $this->getReflectionMethod(new Definition($class), $method);
  106.         }
  107.         $class $definition->getClass();
  108.         try {
  109.             if (!$r $this->container->getReflectionClass($class)) {
  110.                 throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.'$this->currentId$class));
  111.             }
  112.         } catch (\ReflectionException $e) {
  113.             throw new RuntimeException(sprintf('Invalid service "%s": %s.'$this->currentIdlcfirst(rtrim($e->getMessage(), '.'))));
  114.         }
  115.         if (!$r $r->getConstructor()) {
  116.             if ($required) {
  117.                 throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.'$this->currentIdsprintf($class !== $this->currentId ' "%s"' ''$class)));
  118.             }
  119.         } elseif (!$r->isPublic()) {
  120.             throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.'$this->currentIdsprintf($class !== $this->currentId 'constructor of class "%s"' 'its constructor'$class)));
  121.         }
  122.         return $r;
  123.     }
  124.     /**
  125.      * @param string $method
  126.      *
  127.      * @throws RuntimeException
  128.      *
  129.      * @return \ReflectionFunctionAbstract
  130.      */
  131.     protected function getReflectionMethod(Definition $definition$method)
  132.     {
  133.         if ('__construct' === $method) {
  134.             return $this->getConstructor($definitiontrue);
  135.         }
  136.         if (!$class $definition->getClass()) {
  137.             throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.'$this->currentId));
  138.         }
  139.         if (!$r $this->container->getReflectionClass($class)) {
  140.             throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.'$this->currentId$class));
  141.         }
  142.         if (!$r->hasMethod($method)) {
  143.             throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.'$this->currentId$class !== $this->currentId $class.'::'.$method $method));
  144.         }
  145.         $r $r->getMethod($method);
  146.         if (!$r->isPublic()) {
  147.             throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.'$this->currentId$class !== $this->currentId $class.'::'.$method $method));
  148.         }
  149.         return $r;
  150.     }
  151. }