Add the kernel.controller_arguments event

This commit is contained in:
Christophe Coevoet 2016-04-05 08:12:12 +02:00
parent 45b557a5a7
commit af02e2abe1
8 changed files with 118 additions and 7 deletions

View File

@ -10,6 +10,7 @@ CHANGELOG
* added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface`
* added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel`
* added `Symfony\Component\HttpKernel\Controller\ArgumentResolver`
* added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved
3.0.0
-----
@ -22,8 +23,8 @@ CHANGELOG
* removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()`
* removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()`
* removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()`
* removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()`
* removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()`
* removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()`
* removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()`
* removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()`
* removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()`
* removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`

View File

@ -61,7 +61,7 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher
protected function postDispatch($eventName, Event $event)
{
switch ($eventName) {
case KernelEvents::CONTROLLER:
case KernelEvents::CONTROLLER_ARGUMENTS:
$this->stopwatch->start('controller', 'section');
break;
case KernelEvents::RESPONSE:

View File

@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Event;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Allows filtering of controller arguments.
*
* You can call getController() to retrieve the controller and getArguments
* to retrieve the current arguments. With setArguments() you can replace
* arguments that are used to call the controller.
*
* Arguments set in the event must be compatible with the signature of the
* controller.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class FilterControllerArgumentsEvent extends FilterControllerEvent
{
private $arguments;
public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, $requestType)
{
parent::__construct($kernel, $controller, $request, $requestType);
$this->arguments = $arguments;
}
/**
* @return array
*/
public function getArguments()
{
return $this->arguments;
}
/**
* @param array $arguments
*/
public function setArguments(array $arguments)
{
$this->arguments = $arguments;
}
}

View File

@ -53,8 +53,6 @@ class FilterControllerEvent extends KernelEvent
* Sets a new controller.
*
* @param callable $controller
*
* @throws \LogicException
*/
public function setController(callable $controller)
{

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\HttpKernel;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
@ -138,6 +139,11 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
// controller arguments
$arguments = $this->argumentResolver->getArguments($request, $controller);
$event = new FilterControllerArgumentsEvent($this, $controller, $arguments, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER_ARGUMENTS, $event);
$controller = $event->getController();
$arguments = $event->getArguments();
// call controller
$response = call_user_func_array($controller, $arguments);

View File

@ -76,6 +76,19 @@ final class KernelEvents
*/
const CONTROLLER = 'kernel.controller';
/**
* The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved.
*
* This event allows you to change the arguments that will be passed to
* the controller. The event listener method receives a
* Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent instance.
*
* @Event
*
* @var string
*/
const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments';
/**
* The RESPONSE event occurs once a response was created for
* replying to a request.

View File

@ -34,6 +34,7 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
'__section__',
'kernel.request',
'kernel.controller',
'kernel.controller_arguments',
'controller',
'kernel.response',
'kernel.terminate',

View File

@ -15,6 +15,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
@ -233,6 +234,42 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', $kernel->handle(new Request())->getContent());
}
public function testHandleAllowChangingControllerArguments()
{
$dispatcher = new EventDispatcher();
$dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
$event->setArguments(array('foo'));
});
$kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); });
$this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
}
public function testHandleAllowChangingControllerAndArguments()
{
$dispatcher = new EventDispatcher();
$dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
$oldController = $event->getController();
$oldArguments = $event->getArguments();
$newController = function ($id) use ($oldController, $oldArguments) {
$response = call_user_func_array($oldController, $oldArguments);
$response->headers->set('X-Id', $id);
return $response;
};
$event->setController($newController);
$event->setArguments(array('bar'));
});
$kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }, null, array('foo'));
$this->assertResponseEquals(new Response('foo', 200, array('X-Id' => 'bar')), $kernel->handle(new Request()));
}
public function testTerminate()
{
$dispatcher = new EventDispatcher();
@ -265,7 +302,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$kernel->handle($request, HttpKernelInterface::MASTER_REQUEST);
}
private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null)
private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array())
{
if (null === $controller) {
$controller = function () { return new Response('Hello'); };
@ -281,7 +318,7 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
$argumentResolver
->expects($this->any())
->method('getArguments')
->will($this->returnValue(array()));
->will($this->returnValue($arguments));
return new HttpKernel($eventDispatcher, $controllerResolver, $requestStack, $argumentResolver);
}