Skip to content

Commit

Permalink
Add the kernel.controller_arguments event
Browse files Browse the repository at this point in the history
  • Loading branch information
stof committed Apr 7, 2016
1 parent 45b557a commit af02e2a
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/Symfony/Component/HttpKernel/CHANGELOG.md
Expand Up @@ -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
-----
Expand All @@ -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`
Expand Down
Expand Up @@ -61,7 +61,7 @@ protected function preDispatch($eventName, Event $event)
protected function postDispatch($eventName, Event $event)
{
switch ($eventName) {
case KernelEvents::CONTROLLER:
case KernelEvents::CONTROLLER_ARGUMENTS:
$this->stopwatch->start('controller', 'section');
break;
case KernelEvents::RESPONSE:
Expand Down
@@ -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;
}
}
Expand Up @@ -53,8 +53,6 @@ public function getController()
* Sets a new controller.
*
* @param callable $controller
*
* @throws \LogicException
*/
public function setController(callable $controller)
{
Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Component/HttpKernel/HttpKernel.php
Expand Up @@ -14,6 +14,7 @@
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;
Expand Down Expand Up @@ -138,6 +139,11 @@ private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
// 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);

Expand Down
13 changes: 13 additions & 0 deletions src/Symfony/Component/HttpKernel/KernelEvents.php
Expand Up @@ -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.
Expand Down
Expand Up @@ -34,6 +34,7 @@ public function testStopwatchSections()
'__section__',
'kernel.request',
'kernel.controller',
'kernel.controller_arguments',
'controller',
'kernel.response',
'kernel.terminate',
Expand Down
41 changes: 39 additions & 2 deletions src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php
Expand Up @@ -15,6 +15,7 @@
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;
Expand Down Expand Up @@ -233,6 +234,42 @@ public function testHandleWithAResponseListener()
$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();
Expand Down Expand Up @@ -265,7 +302,7 @@ public function testVerifyRequestStackPushPopDuringHandle()
$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'); };
Expand All @@ -281,7 +318,7 @@ private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $contr
$argumentResolver
->expects($this->any())
->method('getArguments')
->will($this->returnValue(array()));
->will($this->returnValue($arguments));

return new HttpKernel($eventDispatcher, $controllerResolver, $requestStack, $argumentResolver);
}
Expand Down

0 comments on commit af02e2a

Please sign in to comment.