diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index a106866ec0..5846bbb65a 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -11,9 +11,11 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -65,11 +67,15 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface if (!$r = $container->getReflectionClass($class)) { throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } + $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); // get regular public methods $methods = array(); $arguments = array(); foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { + if ('setContainer' === $r->name && $isContainerAware) { + continue; + } if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { $methods[strtolower($r->name)] = array($r, $r->getParameters()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index bfae7efde3..cf1bfdd56d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -13,6 +13,8 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ServiceLocator; @@ -187,6 +189,21 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); $this->assertEquals($expected, $locator->getArgument(0)); } + + public function testSkipSetContainer() + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.service')->addArgument(array()); + + $container->register('foo', ContainerAwareRegisterTestController::class) + ->addTag('controller.service_arguments'); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); + $this->assertSame(array('foo:fooAction'), array_keys($locator)); + } } class RegisterTestController @@ -204,6 +221,15 @@ class RegisterTestController } } +class ContainerAwareRegisterTestController implements ContainerAwareInterface +{ + use ContainerAwareTrait; + + public function fooAction(ControllerDummy $bar) + { + } +} + class ControllerDummy { }