From 2ff474fc3a2a49090f4636d6a13620920d702b93 Mon Sep 17 00:00:00 2001 From: Jeremy Mikola Date: Wed, 8 Dec 2010 18:58:26 -0500 Subject: [PATCH] [HttpKernel][FrameworkBundle] Rename BaseHttpKernel to HttpKernel The original HttpKernel class can be deleted, as it's request-stashing will be moved to the Kernel class. FrameworkBundle's list of compiled classes must also be modified to respect this change. --- .../FrameworkExtension.php | 1 - .../Component/HttpKernel/BaseHttpKernel.php | 141 -------------- .../Component/HttpKernel/HttpKernel.php | 109 +++++++++-- .../HttpKernel/BaseHttpKernelTest.php | 176 ------------------ .../HttpKernel/Cache/TestHttpKernel.php | 4 +- .../Component/HttpKernel/HttpKernelTest.php | 141 +++++++++++++- .../Component/HttpKernel/TestHttpKernel.php | 4 +- 7 files changed, 232 insertions(+), 344 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/BaseHttpKernel.php delete mode 100644 tests/Symfony/Tests/Component/HttpKernel/BaseHttpKernelTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 00de9277104c..cf4e5bbd49c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -123,7 +123,6 @@ public function configLoad($config, ContainerBuilder $container) 'Symfony\\Component\\HttpFoundation\\Response', 'Symfony\\Component\\HttpFoundation\\ResponseHeaderBag', - 'Symfony\\Component\\HttpKernel\\BaseHttpKernel', 'Symfony\\Component\\HttpKernel\\HttpKernel', 'Symfony\\Component\\HttpKernel\\ResponseListener', 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', diff --git a/src/Symfony/Component/HttpKernel/BaseHttpKernel.php b/src/Symfony/Component/HttpKernel/BaseHttpKernel.php deleted file mode 100644 index 67a29331c7eb..000000000000 --- a/src/Symfony/Component/HttpKernel/BaseHttpKernel.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * BaseHttpKernel notifies events to convert a Request object to a Response one. - * - * @author Fabien Potencier - */ -class BaseHttpKernel implements HttpKernelInterface -{ - protected $dispatcher; - protected $resolver; - - /** - * Constructor - * - * @param EventDispatcher $dispatcher An event dispatcher instance - * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance - */ - public function __construct(EventDispatcher $dispatcher, ControllerResolverInterface $resolver) - { - $this->dispatcher = $dispatcher; - $this->resolver = $resolver; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) - { - try { - return $this->handleRaw($request, $type); - } catch (\Exception $e) { - if (false === $catch) { - throw $e; - } - - // exception - $event = new Event($this, 'core.exception', array('request_type' => $type, 'request' => $request, 'exception' => $e)); - $this->dispatcher->notifyUntil($event); - if ($event->isProcessed()) { - return $this->filterResponse($event->getReturnValue(), $request, 'A "core.exception" listener returned a non response object.', $type); - } - - throw $e; - } - } - - /** - * Handles a request to convert it to a response. - * - * Exceptions are not caught. - * - * @param Request $request A Request instance - * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) - * - * @return Response A Response instance - * - * @throws \LogicException If one of the listener does not behave as expected - * @throws NotFoundHttpException When controller cannot be found - */ - protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) - { - // request - $event = new Event($this, 'core.request', array('request_type' => $type, 'request' => $request)); - $this->dispatcher->notifyUntil($event); - if ($event->isProcessed()) { - return $this->filterResponse($event->getReturnValue(), $request, 'A "core.request" listener returned a non response object.', $type); - } - - // load controller - if (false === $controller = $this->resolver->getController($request)) { - throw new NotFoundHttpException('Unable to find the controller.'); - } - - $event = new Event($this, 'core.controller', array('request_type' => $type, 'request' => $request)); - $this->dispatcher->filter($event, $controller); - $controller = $event->getReturnValue(); - - // controller must be a callable - if (!is_callable($controller)) { - throw new \LogicException(sprintf('The controller must be a callable (%s).', var_export($controller, true))); - } - - // controller arguments - $arguments = $this->resolver->getArguments($request, $controller); - - // call controller - $retval = call_user_func_array($controller, $arguments); - - // view - $event = new Event($this, 'core.view', array('request_type' => $type, 'request' => $request)); - $this->dispatcher->filter($event, $retval); - - return $this->filterResponse($event->getReturnValue(), $request, sprintf('The controller must return a response (instead of %s).', is_object($event->getReturnValue()) ? 'an object of class '.get_class($event->getReturnValue()) : is_array($event->getReturnValue()) ? 'an array' : str_replace("\n", '', var_export($event->getReturnValue(), true))), $type); - } - - /** - * Filters a response object. - * - * @param Response $response A Response instance - * @param string $message A error message in case the response is not a Response object - * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) - * - * @return Response The filtered Response instance - * - * @throws \RuntimeException if the passed object is not a Response instance - */ - protected function filterResponse($response, $request, $message, $type) - { - if (!$response instanceof Response) { - throw new \RuntimeException($message); - } - - $event = $this->dispatcher->filter(new Event($this, 'core.response', array('request_type' => $type, 'request' => $request)), $response); - $response = $event->getReturnValue(); - - if (!$response instanceof Response) { - throw new \RuntimeException('A "core.response" listener returned a non response object.'); - } - - return $response; - } -} diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 9bfd22ea30a9..38dc0d9b54d8 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -2,11 +2,12 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Response; /* * This file is part of the Symfony package. @@ -22,22 +23,21 @@ * * @author Fabien Potencier */ -class HttpKernel extends BaseHttpKernel +class HttpKernel implements HttpKernelInterface { - protected $container; + protected $dispatcher; + protected $resolver; /** * Constructor * - * @param ContainerInterface $container An ContainerInterface instance * @param EventDispatcher $dispatcher An event dispatcher instance * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance */ - public function __construct(ContainerInterface $container, EventDispatcher $dispatcher, ControllerResolverInterface $resolver) + public function __construct(EventDispatcher $dispatcher, ControllerResolverInterface $resolver) { - $this->container = $container; - - parent::__construct($dispatcher, $resolver); + $this->dispatcher = $dispatcher; + $this->resolver = $resolver; } /** @@ -45,13 +45,96 @@ public function __construct(ContainerInterface $container, EventDispatcher $disp */ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { - $masterRequest = HttpKernelInterface::MASTER_REQUEST === $type ? $request : $this->container->get('request'); + try { + return $this->handleRaw($request, $type); + } catch (\Exception $e) { + if (false === $catch) { + throw $e; + } + + // exception + $event = new Event($this, 'core.exception', array('request_type' => $type, 'request' => $request, 'exception' => $e)); + $this->dispatcher->notifyUntil($event); + if ($event->isProcessed()) { + return $this->filterResponse($event->getReturnValue(), $request, 'A "core.exception" listener returned a non response object.', $type); + } + + throw $e; + } + } + + /** + * Handles a request to convert it to a response. + * + * Exceptions are not caught. + * + * @param Request $request A Request instance + * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) + * + * @return Response A Response instance + * + * @throws \LogicException If one of the listener does not behave as expected + * @throws NotFoundHttpException When controller cannot be found + */ + protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) + { + // request + $event = new Event($this, 'core.request', array('request_type' => $type, 'request' => $request)); + $this->dispatcher->notifyUntil($event); + if ($event->isProcessed()) { + return $this->filterResponse($event->getReturnValue(), $request, 'A "core.request" listener returned a non response object.', $type); + } + + // load controller + if (false === $controller = $this->resolver->getController($request)) { + throw new NotFoundHttpException('Unable to find the controller.'); + } - $this->container->set('request', $request); + $event = new Event($this, 'core.controller', array('request_type' => $type, 'request' => $request)); + $this->dispatcher->filter($event, $controller); + $controller = $event->getReturnValue(); + + // controller must be a callable + if (!is_callable($controller)) { + throw new \LogicException(sprintf('The controller must be a callable (%s).', var_export($controller, true))); + } + + // controller arguments + $arguments = $this->resolver->getArguments($request, $controller); + + // call controller + $retval = call_user_func_array($controller, $arguments); + + // view + $event = new Event($this, 'core.view', array('request_type' => $type, 'request' => $request)); + $this->dispatcher->filter($event, $retval); + + return $this->filterResponse($event->getReturnValue(), $request, sprintf('The controller must return a response (instead of %s).', is_object($event->getReturnValue()) ? 'an object of class '.get_class($event->getReturnValue()) : is_array($event->getReturnValue()) ? 'an array' : str_replace("\n", '', var_export($event->getReturnValue(), true))), $type); + } + + /** + * Filters a response object. + * + * @param Response $response A Response instance + * @param string $message A error message in case the response is not a Response object + * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) + * + * @return Response The filtered Response instance + * + * @throws \RuntimeException if the passed object is not a Response instance + */ + protected function filterResponse($response, $request, $message, $type) + { + if (!$response instanceof Response) { + throw new \RuntimeException($message); + } - $response = parent::handle($request, $type, $catch); + $event = $this->dispatcher->filter(new Event($this, 'core.response', array('request_type' => $type, 'request' => $request)), $response); + $response = $event->getReturnValue(); - $this->container->set('request', $masterRequest); + if (!$response instanceof Response) { + throw new \RuntimeException('A "core.response" listener returned a non response object.'); + } return $response; } diff --git a/tests/Symfony/Tests/Component/HttpKernel/BaseHttpKernelTest.php b/tests/Symfony/Tests/Component/HttpKernel/BaseHttpKernelTest.php deleted file mode 100644 index 510236354693..000000000000 --- a/tests/Symfony/Tests/Component/HttpKernel/BaseHttpKernelTest.php +++ /dev/null @@ -1,176 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Tests\Component\HttpKernel; - -use Symfony\Component\HttpKernel\BaseHttpKernel; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\EventDispatcher\EventDispatcher; - -class BaseHttpKernelTest extends \PHPUnit_Framework_TestCase -{ - /** - * @expectedException RuntimeException - */ - public function testHandleWhenControllerThrowsAnExceptionAndRawIsTrue() - { - $kernel = new BaseHttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); - - $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true); - } - - /** - * @expectedException RuntimeException - */ - public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalseAndNoListenerIsRegistered() - { - $kernel = new BaseHttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); - - $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false); - } - - public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.exception', function ($event) - { - $event->setReturnValue(new Response($event->get('exception')->getMessage())); - - return true; - }); - - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); - - $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); - } - - public function testHandleWhenAListenerReturnsAResponse() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.request', function ($event) - { - $event->setReturnValue(new Response('hello')); - - return true; - }); - - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver()); - - $this->assertEquals('hello', $kernel->handle(new Request())->getContent()); - } - - /** - * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException - */ - public function testHandleWhenNoControllerIsFound() - { - $dispatcher = new EventDispatcher(); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver(false)); - - $kernel->handle(new Request()); - } - - /** - * @expectedException LogicException - */ - public function testHandleWhenNoControllerIsNotACallable() - { - $dispatcher = new EventDispatcher(); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver('foobar')); - - $kernel->handle(new Request()); - } - - /** - * @expectedException RuntimeException - */ - public function testHandleWhenControllerDoesNotReturnAResponse() - { - $dispatcher = new EventDispatcher(); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); - - $kernel->handle(new Request()); - } - - public function testHandleWhenControllerDoesNotReturnAResponseButAViewIsRegistered() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.view', function ($event, $retval) - { - return new Response($retval); - }); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); - - $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); - } - - /** - * @expectedException RuntimeException - */ - public function testHandleWhenAViewDoesNotReturnAResponse() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.view', function ($event, $retval) - { - return $retval; - }); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); - - $kernel->handle(new Request()); - } - - /** - * @expectedException RuntimeException - */ - public function testHandleWhenAResponseListenerDoesNotReturnAResponse() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.response', function ($event, $response) - { - return 'foo'; - }); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver()); - - $kernel->handle(new Request()); - } - - public function testHandleWithAResponseListener() - { - $dispatcher = new EventDispatcher(); - $dispatcher->connect('core.response', function ($event, $response) - { - return new Response('foo'); - }); - $kernel = new BaseHttpKernel($dispatcher, $this->getResolver()); - - $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); - } - - protected function getResolver($controller = null) - { - if (null === $controller) { - $controller = function () { return new Response('Hello'); }; - } - $resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface'); - $resolver->expects($this->any()) - ->method('getController') - ->will($this->returnValue($controller)) - ; - $resolver->expects($this->any()) - ->method('getArguments') - ->will($this->returnValue(array())) - ; - - return $resolver; - } -} diff --git a/tests/Symfony/Tests/Component/HttpKernel/Cache/TestHttpKernel.php b/tests/Symfony/Tests/Component/HttpKernel/Cache/TestHttpKernel.php index 842b6bdd30f8..007f580f27d4 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/Cache/TestHttpKernel.php +++ b/tests/Symfony/Tests/Component/HttpKernel/Cache/TestHttpKernel.php @@ -11,13 +11,13 @@ namespace Symfony\Tests\Component\HttpKernel\Cache; -use Symfony\Component\HttpKernel\BaseHttpKernel; +use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -class TestHttpKernel extends BaseHttpKernel implements ControllerResolverInterface +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { protected $body; protected $status; diff --git a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php index df2ba647d936..dbe61399048c 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php @@ -19,18 +19,141 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase { - public function testHandleSetsTheRequest() + /** + * @expectedException RuntimeException + */ + public function testHandleWhenControllerThrowsAnExceptionAndRawIsTrue() { - $request = Request::create('/'); - $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); - $container->expects($this->exactly(2)) - ->method('set') - ->with('request', $request) - ; + $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); + + $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalseAndNoListenerIsRegistered() + { + $kernel = new HttpKernel(new EventDispatcher(), $this->getResolver(function () { throw new \RuntimeException(); })); + + $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false); + } + + public function testHandleWhenControllerThrowsAnExceptionAndRawIsFalse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.exception', function ($event) + { + $event->setReturnValue(new Response($event->get('exception')->getMessage())); + + return true; + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { throw new \RuntimeException('foo'); })); + + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + } + + public function testHandleWhenAListenerReturnsAResponse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.request', function ($event) + { + $event->setReturnValue(new Response('hello')); + + return true; + }); + + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + + $this->assertEquals('hello', $kernel->handle(new Request())->getContent()); + } + + /** + * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException + */ + public function testHandleWhenNoControllerIsFound() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(false)); + + $kernel->handle(new Request()); + } + + /** + * @expectedException LogicException + */ + public function testHandleWhenNoControllerIsNotACallable() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver('foobar')); + + $kernel->handle(new Request()); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenControllerDoesNotReturnAResponse() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); + + $kernel->handle(new Request()); + } + + public function testHandleWhenControllerDoesNotReturnAResponseButAViewIsRegistered() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.view', function ($event, $retval) + { + return new Response($retval); + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); - $kernel = new HttpKernel($container, new EventDispatcher(), $this->getResolver()); + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenAViewDoesNotReturnAResponse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.view', function ($event, $retval) + { + return $retval; + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver(function () { return 'foo'; })); + + $kernel->handle(new Request()); + } + + /** + * @expectedException RuntimeException + */ + public function testHandleWhenAResponseListenerDoesNotReturnAResponse() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.response', function ($event, $response) + { + return 'foo'; + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + + $kernel->handle(new Request()); + } + + public function testHandleWithAResponseListener() + { + $dispatcher = new EventDispatcher(); + $dispatcher->connect('core.response', function ($event, $response) + { + return new Response('foo'); + }); + $kernel = new HttpKernel($dispatcher, $this->getResolver()); - $kernel->handle($request); + $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); } protected function getResolver($controller = null) diff --git a/tests/Symfony/Tests/Component/HttpKernel/TestHttpKernel.php b/tests/Symfony/Tests/Component/HttpKernel/TestHttpKernel.php index 3962b3d80447..d0f208f753dc 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/TestHttpKernel.php +++ b/tests/Symfony/Tests/Component/HttpKernel/TestHttpKernel.php @@ -11,13 +11,13 @@ namespace Symfony\Tests\Component\HttpKernel; -use Symfony\Component\HttpKernel\BaseHttpKernel; +use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -class TestHttpKernel extends BaseHttpKernel implements ControllerResolverInterface +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { public function __construct() {