Skip to content

Commit

Permalink
[HttpKernel] added support for controllers as arrays and object with …
Browse files Browse the repository at this point in the history
…an __invoke method

Controllers can now be any valid PHP callable
  • Loading branch information
fabpot committed Apr 16, 2011
1 parent db8b118 commit c6818d8
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
Expand Up @@ -60,7 +60,7 @@ public function getController(Request $request)
return false;
}

if ($controller instanceof \Closure) {
if (is_array($controller) || method_exists($controller, '__invoke')) {
return $controller;
}

Expand Down Expand Up @@ -92,15 +92,21 @@ public function getArguments(Request $request, $controller)
if (is_array($controller)) {
$r = new \ReflectionMethod($controller[0], $controller[1]);
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
} elseif (is_object($controller)) {
$r = new \ReflectionObject($controller);
$r = $r->getMethod('__invoke');
$repr = get_class($controller);
} else {
$r = new \ReflectionFunction($controller);
$repr = 'Closure';
$repr = $controller;
}

$arguments = array();
foreach ($r->getParameters() as $param) {
if (array_key_exists($param->getName(), $attributes)) {
$arguments[] = $attributes[$param->getName()];
} elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
$arguments[] = $request;
} elseif ($param->isDefaultValueAvailable()) {
$arguments[] = $param->getDefaultValue();
} else {
Expand Down
Expand Up @@ -36,6 +36,18 @@ public function testGetController()
$controller = $resolver->getController($request);
$this->assertSame($lambda, $controller);

$request->attributes->set('_controller', $this);
$controller = $resolver->getController($request);
$this->assertSame($this, $controller);

$request->attributes->set('_controller', array($this, 'controllerMethod1'));
$controller = $resolver->getController($request);
$this->assertSame(array($this, 'controllerMethod1'), $controller);

$request->attributes->set('_controller', array('Symfony\Tests\Component\HttpKernel\ControllerResolverTest', 'controllerMethod4'));
$controller = $resolver->getController($request);
$this->assertSame(array('Symfony\Tests\Component\HttpKernel\ControllerResolverTest', 'controllerMethod4'), $controller);

$request->attributes->set('_controller', 'foo');
try {
$resolver->getController($request);
Expand Down Expand Up @@ -98,6 +110,14 @@ public function testGetArguments()
} catch (\Exception $e) {
$this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
}

$request = Request::create('/');
$controller = array(new self(), 'controllerMethod5');
$this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request');
}

public function __invoke()
{
}

protected function controllerMethod1($foo)
Expand All @@ -111,4 +131,12 @@ protected function controllerMethod2($foo, $bar = null)
protected function controllerMethod3($foo, $bar = null, $foobar)
{
}

static protected function controllerMethod4()
{
}

protected function controllerMethod5(Request $request)
{
}
}
64 changes: 64 additions & 0 deletions tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php
Expand Up @@ -88,6 +88,47 @@ public function testHandleWhenNoControllerIsNotACallable()
$kernel->handle(new Request());
}

public function testHandleWhenNoControllerIsAClosure()
{
$response = new Response('foo');
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(function () use ($response) { return $response; }));

$this->assertSame($response, $kernel->handle(new Request()));
}

public function testHandleWhenNoControllerIsAnObjectWithInvoke()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(new Controller()));

$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}

public function testHandleWhenNoControllerIsAFunction()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver('Symfony\Tests\Component\HttpKernel\controller_func'));

$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}

public function testHandleWhenNoControllerIsAnArray()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(array(new Controller(), 'controller')));

$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}

public function testHandleWhenNoControllerIsAStaticArray()
{
$dispatcher = new EventDispatcher();
$kernel = new HttpKernel($dispatcher, $this->getResolver(array('Symfony\Tests\Component\HttpKernel\Controller', 'staticcontroller')));

$this->assertEquals(new Response('foo'), $kernel->handle(new Request()));
}

/**
* @expectedException LogicException
*/
Expand Down Expand Up @@ -140,3 +181,26 @@ protected function getResolver($controller = null)
return $resolver;
}
}

class Controller
{
public function __invoke()
{
return new Response('foo');
}

public function controller()
{
return new Response('foo');
}

static public function staticController()
{
return new Response('foo');
}
}

function controller_func()
{
return new Response('foo');
}

0 comments on commit c6818d8

Please sign in to comment.