From e712e89e9f9d83b5a46a3e19d3c0f943b1d32b73 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sat, 21 Jun 2014 08:25:07 -0400 Subject: [PATCH] [FrameworkBundle] Simplify "invokable" controllers as services --- .../Controller/ControllerResolver.php | 4 + .../Controller/ControllerResolverTest.php | 155 ++++++++++++++++++ .../Controller/ControllerResolverTest.php | 29 ++-- 3 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index 69c8f1d03fde..bd4cb040e215 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -63,6 +63,10 @@ protected function createController($controller) list($service, $method) = explode(':', $controller, 2); return array($this->container->get($service), $method); + } elseif ($this->container->has($controller) && + method_exists($service = $this->container->get($controller), '__invoke') + ) { + return $service; } else { throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php new file mode 100644 index 000000000000..9e8701ff21d6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -0,0 +1,155 @@ +createControllerResolver(); + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController::testAction'); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerInterface', $controller[0]->getContainer()); + $this->assertSame('testAction', $controller[1]); + } + + public function testGetControllerWithBundleNotation() + { + $shortName = 'FooBundle:Default:test'; + $parser = $this->createMockParser(); + $parser->expects($this->once()) + ->method('parse') + ->with($shortName) + ->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController::testAction')) + ; + + $resolver = $this->createControllerResolver(null, $parser); + $request = Request::create('/'); + $request->attributes->set('_controller', $shortName); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf('Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController', $controller[0]); + $this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerInterface', $controller[0]->getContainer()); + $this->assertSame('testAction', $controller[1]); + } + + public function testGetControllerService() + { + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($this)) + ; + + $resolver = $this->createControllerResolver(null, null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo:controllerMethod1'); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf(get_class($this), $controller[0]); + $this->assertSame('controllerMethod1', $controller[1]); + } + + public function testGetControllerInvokableService() + { + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->will($this->returnValue(true)) + ; + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->will($this->returnValue($this)) + ; + + $resolver = $this->createControllerResolver(null, null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo'); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf(get_class($this), $controller); + } + + /** + * @dataProvider getUndefinedControllers + */ + public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) + { + $this->setExpectedException($exceptionName, $exceptionMessage); + + parent::testGetControllerOnNonUndefinedFunction($controller); + } + + public function getUndefinedControllers() + { + return array( + array('foo', '\LogicException', 'Unable to parse the controller name "foo".'), + array('foo::bar', '\InvalidArgumentException', 'Class "foo" does not exist.'), + array('stdClass', '\LogicException', 'Unable to parse the controller name "stdClass".'), + array( + 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar', + '\InvalidArgumentException', + 'Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar" for URI "/" is not callable.' + ) + ); + } + + protected function createControllerResolver(LoggerInterface $logger = null, ControllerNameParser $parser = null, ContainerInterface $container = null) + { + if (!$parser) { + $parser = $this->createMockParser(); + } + + if (!$container) { + $container = $this->createMockContainer(); + } + + return new ControllerResolver($container, $parser, $logger); + } + + protected function createMockParser() + { + return $this->getMock('Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser', array(), array(), '', false); + } + + protected function createMockContainer() + { + return $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + } +} + +class ContainerAwareController implements ContainerAwareInterface +{ + private $container; + + public function setContainer(ContainerInterface $container = null) + { + $this->container = $container; + } + + public function getContainer() + { + return $this->container; + } + + public function testAction() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 0631ab660eb5..ed769d24219e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolver; -use Symfony\Component\HttpKernel\Tests\Logger; use Symfony\Component\HttpFoundation\Request; class ControllerResolverTest extends \PHPUnit_Framework_TestCase @@ -21,7 +21,7 @@ public function testGetControllerWithoutControllerParameter() { $logger = $this->getMock('Psr\Log\LoggerInterface'); $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing'); - $resolver = new ControllerResolver($logger); + $resolver = $this->createControllerResolver($logger); $request = Request::create('/'); $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); @@ -29,7 +29,7 @@ public function testGetControllerWithoutControllerParameter() public function testGetControllerWithLambda() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $lambda = function () {}); @@ -39,7 +39,7 @@ public function testGetControllerWithLambda() public function testGetControllerWithObjectAndInvokeMethod() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $this); @@ -49,7 +49,7 @@ public function testGetControllerWithObjectAndInvokeMethod() public function testGetControllerWithObjectAndMethod() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', array($this, 'controllerMethod1')); @@ -59,7 +59,7 @@ public function testGetControllerWithObjectAndMethod() public function testGetControllerWithClassAndMethod() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4')); @@ -69,7 +69,7 @@ public function testGetControllerWithClassAndMethod() public function testGetControllerWithObjectAndMethodAsString() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1'); @@ -79,7 +79,7 @@ public function testGetControllerWithObjectAndMethodAsString() public function testGetControllerWithClassAndInvokeMethod() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest'); @@ -92,7 +92,7 @@ public function testGetControllerWithClassAndInvokeMethod() */ public function testGetControllerOnObjectWithoutInvokeMethod() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', new \stdClass()); @@ -101,7 +101,7 @@ public function testGetControllerOnObjectWithoutInvokeMethod() public function testGetControllerWithFunction() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'); @@ -115,7 +115,7 @@ public function testGetControllerWithFunction() */ public function testGetControllerOnNonUndefinedFunction($controller) { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $request->attributes->set('_controller', $controller); @@ -134,7 +134,7 @@ public function getUndefinedControllers() public function testGetArguments() { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); $controller = array(new self(), 'testGetArguments'); @@ -207,6 +207,11 @@ public function testCreateControllerCanReturnAnyCallable() $mock->getController($request); } + protected function createControllerResolver(LoggerInterface $logger = null) + { + return new ControllerResolver($logger); + } + public function __invoke($foo, $bar = null) { }