From e35d3452043bf9322eeb51d97efda36f481b1c94 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 22 Jul 2010 19:57:45 +0200 Subject: [PATCH] changed HttpKernel workflow to allow more flexibility --- ...llerManager.php => ControllerResolver.php} | 13 ++-- .../Resources/config/templating.xml | 2 +- .../FrameworkBundle/Resources/config/web.xml | 11 +--- .../Templating/Helper/ActionsHelper.php | 12 ++-- .../Controller/ControllerLoaderListener.php | 65 ------------------- ...ce.php => ControllerResolverInterface.php} | 12 ++-- .../Components/HttpKernel/HttpKernel.php | 59 ++++++++--------- .../HttpKernel/HttpKernelInterface.php | 10 +-- .../Framework/Resources/config/services.xml | 1 + .../HttpKernel/Cache/TestHttpKernel.php | 16 +++-- .../Components/HttpKernel/TestHttpKernel.php | 16 +++-- 11 files changed, 73 insertions(+), 144 deletions(-) rename src/Symfony/Bundle/FrameworkBundle/Controller/{ControllerManager.php => ControllerResolver.php} (94%) delete mode 100644 src/Symfony/Components/HttpKernel/Controller/ControllerLoaderListener.php rename src/Symfony/Components/HttpKernel/Controller/{ControllerManagerInterface.php => ControllerResolverInterface.php} (78%) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerManager.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php similarity index 94% rename from src/Symfony/Bundle/FrameworkBundle/Controller/ControllerManager.php rename to src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index 86c98f579ae3..bc37dab89c3f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerManager.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -3,7 +3,7 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; use Symfony\Components\HttpKernel\LoggerInterface; -use Symfony\Components\HttpKernel\Controller\ControllerManagerInterface; +use Symfony\Components\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Components\HttpKernel\HttpKernelInterface; use Symfony\Components\HttpFoundation\Request; use Symfony\Components\EventDispatcher\Event; @@ -19,13 +19,13 @@ */ /** - * ControllerManager. + * ControllerResolver. * * @package Symfony * @subpackage Bundle_FrameworkBundle * @author Fabien Potencier */ -class ControllerManager implements ControllerManagerInterface +class ControllerResolver implements ControllerResolverInterface { protected $container; protected $logger; @@ -122,7 +122,7 @@ public function render($controller, array $options = array()) * @param \Symfony\Components\HttpFoundation\Request $request A Request instance * * @return mixed|Boolean A PHP callable representing the Controller, - * or false if this manager is not able to determine the controller + * or false if this resolver is not able to determine the controller * * @throws \InvalidArgumentException|\LogicException If the controller can't be found */ @@ -190,10 +190,9 @@ public function getController(Request $request) * * @throws \RuntimeException When value for argument given is not provided */ - public function getMethodArguments(Request $request, $controller) + public function getArguments(Request $request, $controller) { - $event = $this->container->get('event_dispatcher')->filter(new Event($this, 'controller_manager.filter_controller_arguments', array('controller' => $controller, 'request' => $request)), $request->attributes->all()); - $attributes = $event->getReturnValue(); + $attributes = $request->attributes->all(); list($controller, $method) = $controller; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml index 7e7a6782535c..3145b981914b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml @@ -83,7 +83,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 301ead9b156e..530b259370df 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -6,8 +6,7 @@ Symfony\Bundle\FrameworkBundle\RequestListener - Symfony\Bundle\FrameworkBundle\Controller\ControllerManager - Symfony\Components\HttpKernel\Controller\ControllerLoaderListener + Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver Symfony\Components\HttpKernel\ResponseListener Symfony\Bundle\FrameworkBundle\Controller\ExceptionListener FrameworkBundle:Exception:exception @@ -16,17 +15,11 @@ - + - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php index 1e763aa4ee93..62f745466644 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php @@ -4,7 +4,7 @@ use Symfony\Components\Templating\Helper\Helper; use Symfony\Components\OutputEscaper\Escaper; -use Symfony\Bundle\FrameworkBundle\Controller\ControllerManager; +use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; /* * This file is part of the Symfony framework. @@ -24,16 +24,16 @@ */ class ActionsHelper extends Helper { - protected $manager; + protected $resolver; /** * Constructor. * * @param Constructor $container A ContainerInterface instance */ - public function __construct(ControllerManager $manager) + public function __construct(ControllerResolver $resolver) { - $this->manager = $manager; + $this->resolver = $resolver; } /** @@ -55,7 +55,7 @@ public function output($controller, array $options = array()) * @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI * @param array $options An array of options * - * @see Symfony\Bundle\FrameworkBundle\Controller\ControllerManager::render() + * @see Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver::render() */ public function render($controller, array $options = array()) { @@ -69,7 +69,7 @@ public function render($controller, array $options = array()) $options['query'] = Escaper::unescape($options['query']); } - return $this->manager->render($controller, $options); + return $this->resolver->render($controller, $options); } /** diff --git a/src/Symfony/Components/HttpKernel/Controller/ControllerLoaderListener.php b/src/Symfony/Components/HttpKernel/Controller/ControllerLoaderListener.php deleted file mode 100644 index 728a87927c0f..000000000000 --- a/src/Symfony/Components/HttpKernel/Controller/ControllerLoaderListener.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -/** - * ControllerLoaderListener listen to the core.load_controller and finds the controller - * to execute based on the request parameters. - * - * @package Symfony - * @subpackage Bundle_FrameworkBundle - * @author Fabien Potencier - */ -class ControllerLoaderListener -{ - protected $manager; - - public function __construct(ControllerManagerInterface $manager) - { - $this->manager = $manager; - } - - /** - * Registers a core.load_controller listener. - * - * @param Symfony\Components\EventDispatcher\EventDispatcher $dispatcher An EventDispatcher instance - */ - public function register(EventDispatcher $dispatcher) - { - $dispatcher->connect('core.load_controller', array($this, 'resolve')); - } - - /** - * Creates the Controller associated with the given Request. - * - * @param Event $event An Event instance - * - * @return Boolean true if the controller has been found, false otherwise - */ - public function resolve(Event $event) - { - $request = $event->getParameter('request'); - - if (false === $controller = $this->manager->getController($request)) { - return false; - } - - $arguments = $this->manager->getMethodArguments($request, $controller); - - $event->setReturnValue(array($controller, $arguments)); - - return true; - } -} diff --git a/src/Symfony/Components/HttpKernel/Controller/ControllerManagerInterface.php b/src/Symfony/Components/HttpKernel/Controller/ControllerResolverInterface.php similarity index 78% rename from src/Symfony/Components/HttpKernel/Controller/ControllerManagerInterface.php rename to src/Symfony/Components/HttpKernel/Controller/ControllerResolverInterface.php index 01c8793ae24e..59e33ae7651a 100644 --- a/src/Symfony/Components/HttpKernel/Controller/ControllerManagerInterface.php +++ b/src/Symfony/Components/HttpKernel/Controller/ControllerResolverInterface.php @@ -14,7 +14,7 @@ */ /** - * A ControllerManagerInterface implementation knows how to determine the + * A ControllerResolverInterface implementation knows how to determine the * controller to execute based on a Request object. * * It can also determine the arguments to pass to the Controller. @@ -25,21 +25,21 @@ * @subpackage Bundle_FrameworkBundle * @author Fabien Potencier */ -interface ControllerManagerInterface +interface ControllerResolverInterface { /** * Returns the Controller instance associated with a Request. * - * As several managers can exist for a single application, a manager must + * As several resolvers can exist for a single application, a resolver must * return false when it is not able to determine the controller. * - * The manager must only throw an exception when it should be able to load + * The resolver must only throw an exception when it should be able to load * controller but cannot because of some errors made by the developer. * * @param \Symfony\Components\HttpFoundation\Request $request A Request instance * * @return mixed|Boolean A PHP callable representing the Controller, - * or false if this manager is not able to determine the controller + * or false if this resolver is not able to determine the controller * * @throws \InvalidArgumentException|\LogicException If the controller can't be found */ @@ -53,5 +53,5 @@ public function getController(Request $request); * * @throws \RuntimeException When value for argument given is not provided */ - public function getMethodArguments(Request $request, $controller); + public function getArguments(Request $request, $controller); } diff --git a/src/Symfony/Components/HttpKernel/HttpKernel.php b/src/Symfony/Components/HttpKernel/HttpKernel.php index 0f858bfb451e..33c9e478af7c 100644 --- a/src/Symfony/Components/HttpKernel/HttpKernel.php +++ b/src/Symfony/Components/HttpKernel/HttpKernel.php @@ -4,6 +4,7 @@ use Symfony\Components\EventDispatcher\Event; use Symfony\Components\EventDispatcher\EventDispatcher; +use Symfony\Components\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Components\HttpKernel\Exception\NotFoundHttpException; use Symfony\Components\HttpFoundation\Request; use Symfony\Components\HttpFoundation\Response; @@ -27,16 +28,19 @@ class HttpKernel implements HttpKernelInterface { protected $dispatcher; + protected $resolver; protected $request; /** * Constructor * - * @param EventDispatcher $dispatcher An event dispatcher instance + * @param \Symfony\Components\EventDispatcher\EventDispatcher $dispatcher An event dispatcher instance + * @param \Symfony\Components\HttpKernel\Controller\ControllerResolverInterface $resolver A ControllerResolverInterface instance */ - public function __construct(EventDispatcher $dispatcher) + public function __construct(EventDispatcher $dispatcher, ControllerResolverInterface $resolver) { $this->dispatcher = $dispatcher; + $this->resolver = $resolver; } /** @@ -55,11 +59,11 @@ public function getRequest() * All exceptions are caught, and a core.exception event is notified * for user management. * - * @param Request $request A Request instance - * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) - * @param Boolean $raw Whether to catch exceptions or not + * @param \Symfony\Components\HttpFoundation\Request $request A Request instance + * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) + * @param Boolean $raw Whether to catch exceptions or not * - * @return Response A Response instance + * @return \Symfony\Components\HttpFoundation\Response A Response instance * * @throws \Exception When an Exception occurs during processing * and couldn't be caught by event processing or $raw is true @@ -100,13 +104,13 @@ public function handle(Request $request = null, $type = HttpKernelInterface::MAS * * Exceptions are not caught. * - * @param Request $request A Request instance - * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) + * @param \Symfony\Components\HttpFoundation\Request $request A Request instance + * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) * - * @return Response A Response instance + * @return \Symfony\Components\HttpFoundation\Response A Response instance * - * @throws \LogicException If one of the listener does not behave as expected - * @throws NotFoundHttpException When controller cannot be found + * @throws \LogicException If one of the listener does not behave as expected + * @throws \Symfony\Components\HttpKernel\Exception\NotFoundHttpException When controller cannot be found */ protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) { @@ -117,30 +121,23 @@ protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) } // load controller - $event = $this->dispatcher->notifyUntil(new Event($this, 'core.load_controller', array('request_type' => $type, 'request' => $request))); - if (!$event->isProcessed()) { + if (false === $controller = $this->resolver->getController($request)) { throw new NotFoundHttpException('Unable to find the controller.'); } - list($controller, $arguments) = $event->getReturnValue(); + $event = $this->dispatcher->filter(new Event($this, 'core.controller', array('request' => $request)), $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 - $event = $this->dispatcher->notifyUntil(new Event($this, 'core.controller', array('request_type' => $type, 'request' => $request, 'controller' => &$controller, 'arguments' => &$arguments))); - if ($event->isProcessed()) { - try { - return $this->filterResponse($event->getReturnValue(), $request, 'A "core.controller" listener returned a non response object.', $type); - } catch (\Exception $e) { - $retval = $event->getReturnValue(); - } - } else { - // call controller - $retval = call_user_func_array($controller, $arguments); - } + // controller arguments + $arguments = $this->resolver->getArguments($request, $controller); + + // call controller + $retval = call_user_func_array($controller, $arguments); // view $event = $this->dispatcher->filter(new Event($this, 'core.view', array('request_type' => $type, 'request' => $request)), $retval); @@ -151,7 +148,7 @@ protected function handleRaw(Request $request, $type = self::MASTER_REQUEST) /** * Handles a request that need to be embedded. * - * @param Request $request A Request instance + * @param \Symfony\Components\HttpFoundation\Request $request A Request instance * @param Boolean $raw Whether to catch exceptions or not * * @return string|false The Response content or false if there is a problem @@ -182,11 +179,11 @@ protected function handleEmbedded(Request $request, $raw = false) /** * 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, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) + * @param \Symfony\Components\HttpFoundation\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, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) * - * @return Response The filtered Response instance + * @return \Symfony\Components\HttpFoundation\Response The filtered Response instance * * @throws \RuntimeException if the passed object is not a Response instance */ diff --git a/src/Symfony/Components/HttpKernel/HttpKernelInterface.php b/src/Symfony/Components/HttpKernel/HttpKernelInterface.php index b17e0a20377a..4bda7823cbf0 100644 --- a/src/Symfony/Components/HttpKernel/HttpKernelInterface.php +++ b/src/Symfony/Components/HttpKernel/HttpKernelInterface.php @@ -29,18 +29,18 @@ interface HttpKernelInterface /** * Handles a request to convert it to a response. * - * @param Request $request A Request instance - * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) - * @param Boolean $raw Whether to catch exceptions or not + * @param \Symfony\Components\HttpFoundation\Request $request A Request instance + * @param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST, HttpKernelInterface::FORWARDED_REQUEST, or HttpKernelInterface::EMBEDDED_REQUEST) + * @param Boolean $raw Whether to catch exceptions or not * - * @return Response $response A Response instance + * @return \Symfony\Components\HttpFoundation\Response $response A Response instance */ public function handle(Request $request = null, $type = self::MASTER_REQUEST, $raw = false); /** * Gets the Request instance associated with the master request. * - * @return Request A Request instance + * @return \Symfony\Components\HttpFoundation\Request A Request instance */ public function getRequest(); } diff --git a/src/Symfony/Framework/Resources/config/services.xml b/src/Symfony/Framework/Resources/config/services.xml index 6ffe647711d6..230d1afe005a 100644 --- a/src/Symfony/Framework/Resources/config/services.xml +++ b/src/Symfony/Framework/Resources/config/services.xml @@ -29,6 +29,7 @@ + diff --git a/tests/Symfony/Tests/Components/HttpKernel/Cache/TestHttpKernel.php b/tests/Symfony/Tests/Components/HttpKernel/Cache/TestHttpKernel.php index 633cd713c7e7..5881c6639a58 100644 --- a/tests/Symfony/Tests/Components/HttpKernel/Cache/TestHttpKernel.php +++ b/tests/Symfony/Tests/Components/HttpKernel/Cache/TestHttpKernel.php @@ -15,9 +15,9 @@ use Symfony\Components\HttpFoundation\Request; use Symfony\Components\HttpFoundation\Response; use Symfony\Components\EventDispatcher\EventDispatcher; -use Symfony\Components\EventDispatcher\Event; +use Symfony\Components\HttpKernel\Controller\ControllerResolverInterface; -class TestHttpKernel extends HttpKernel +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { protected $body; protected $status; @@ -33,15 +33,17 @@ public function __construct($body, $status, $headers, \Closure $customizer = nul $this->customizer = $customizer; $this->called = false; - $this->dispatcher = new EventDispatcher(); - $this->dispatcher->connect('core.load_controller', array($this, 'loadController')); + parent::__construct(new EventDispatcher(), $this); } - public function loadController(Event $event) + public function getController(Request $request) { - $event->setReturnValue(array(array($this, 'callController'), array($event['request']))); + return array($this, 'callController'); + } - return true; + public function getArguments(Request $request, $controller) + { + return array($request); } public function callController(Request $request) diff --git a/tests/Symfony/Tests/Components/HttpKernel/TestHttpKernel.php b/tests/Symfony/Tests/Components/HttpKernel/TestHttpKernel.php index db3c2a6510dd..cfe775b3e215 100644 --- a/tests/Symfony/Tests/Components/HttpKernel/TestHttpKernel.php +++ b/tests/Symfony/Tests/Components/HttpKernel/TestHttpKernel.php @@ -15,21 +15,23 @@ use Symfony\Components\HttpFoundation\Request; use Symfony\Components\HttpFoundation\Response; use Symfony\Components\EventDispatcher\EventDispatcher; -use Symfony\Components\EventDispatcher\Event; +use Symfony\Components\HttpKernel\Controller\ControllerResolverInterface; -class TestHttpKernel extends HttpKernel +class TestHttpKernel extends HttpKernel implements ControllerResolverInterface { public function __construct() { - $this->dispatcher = new EventDispatcher(); - $this->dispatcher->connect('core.load_controller', array($this, 'loadController')); + parent::__construct(new EventDispatcher(), $this); } - public function loadController(Event $event) + public function getController(Request $request) { - $event->setReturnValue(array(array($this, 'callController'), array($event['request']))); + return array($this, 'callController'); + } - return true; + public function getArguments(Request $request, $controller) + { + return array($request); } public function callController(Request $request)