* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; /** * @author Guilhem N. */ class FactoryReturnTypePass implements CompilerPassInterface { /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { // works only since php 7.0 and hhvm 3.11 if (!method_exists(\ReflectionMethod::class, 'getReturnType')) { return; } foreach ($container->getDefinitions() as $id => $definition) { $this->updateDefinition($container, $id, $definition); } } private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $previous = array()) { // circular reference if (isset($previous[$id])) { return; } $factory = $definition->getFactory(); if (null === $factory || null !== $definition->getClass()) { return; } $class = null; if (is_string($factory)) { try { $m = new \ReflectionFunction($factory); } catch (\ReflectionException $e) { return; } } else { if ($factory[0] instanceof Reference) { $previous[$id] = true; $factoryDefinition = $container->findDefinition((string) $factory[0]); $this->updateDefinition($container, strtolower($factory[0]), $factoryDefinition, $previous); $class = $factoryDefinition->getClass(); } else { $class = $factory[0]; } try { $m = new \ReflectionMethod($class, $factory[1]); } catch (\ReflectionException $e) { return; } } $returnType = $m->getReturnType(); if (null !== $returnType && !$returnType->isBuiltin()) { $returnType = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType->__toString(); if (null !== $class) { $declaringClass = $m->getDeclaringClass()->getName(); if ('self' === strtolower($returnType)) { $returnType = $declaringClass; } elseif ('parent' === strtolower($returnType)) { $returnType = get_parent_class($declaringClass) ?: null; } } $definition->setClass($returnType); } } }