Skip to content

Commit

Permalink
Implement ControllerResolver::getArguments()
Browse files Browse the repository at this point in the history
This is needed to support the ServiceControllerServiceProvider because it decorates the default ControllerResolver and calls getArguments() on it.

This commit also enhances compatibility with Silex by allowing to inject
- the Application object by type hint
- the current Request object by type hint (injecting the Request object by parameter name is removed because Silex also doesn't support it).
  • Loading branch information
jdreesen committed Oct 20, 2015
1 parent dd9452f commit 0ee3381
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 24 deletions.
4 changes: 3 additions & 1 deletion src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function __construct(ContainerBuilder $containerBuilder = null, array $va
$containerBuilder = $containerBuilder ?: new ContainerBuilder();
$containerBuilder->addDefinitions([
ContainerInterface::class => $this->containerInteropProxy,
\Silex\Application::class => $this,
get_class($this) => $this,
]);
$containerBuilder->wrapContainer($this->containerInteropProxy);
$this->phpdi = $containerBuilder->build();
Expand All @@ -44,7 +46,7 @@ public function __construct(ContainerBuilder $containerBuilder = null, array $va

// Override the controller resolver with ours
$this['resolver'] = function () {
return new ControllerResolver($this->phpdi);
return new ControllerResolver($this->containerInteropProxy, $this->phpdi);
};
}

Expand Down
62 changes: 54 additions & 8 deletions src/Controller/ControllerResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
namespace DI\Bridge\Silex\Controller;

use DI\InvokerInterface;
use Interop\Container\ContainerInterface;
use Invoker\ParameterResolver\AssociativeArrayResolver;
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
use Invoker\ParameterResolver\ParameterResolver;
use Invoker\ParameterResolver\ResolverChain;
use Invoker\Reflection\CallableReflection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;

Expand All @@ -11,13 +17,24 @@
*/
class ControllerResolver implements ControllerResolverInterface
{
/**
* @var ContainerInterface
*/
private $container;

/**
* @var InvokerInterface
*/
private $invoker;

public function __construct(InvokerInterface $invoker)
/**
* @var ParameterResolver|null
*/
private $parameterResolver;

public function __construct(ContainerInterface $container, InvokerInterface $invoker)
{
$this->container = $container;
$this->invoker = $invoker;
}

Expand All @@ -33,12 +50,7 @@ public function getController(Request $request)
}

return function () use ($request, $controller) {
$parameters = [
'request' => $request,
];
$parameters += $request->attributes->all();

return $this->invoker->call($controller, $parameters);
return $this->invoker->call($controller, $this->getArguments($request, $controller));
};
}

Expand All @@ -47,6 +59,40 @@ public function getController(Request $request)
*/
public function getArguments(Request $request, $controller)
{
return array();
$controllerReflection = CallableReflection::create($controller);

$resolvedArguments = [];
foreach ($controllerReflection->getParameters() as $index => $parameter) {
if ($parameter->getClass() && $parameter->getClass()->isInstance($request)) {
$resolvedArguments[$index] = $request;

break;
}
}

$arguments = $this->getParameterResolver()->getParameters(
$controllerReflection,
$request->attributes->all(),
$resolvedArguments
);

ksort($arguments);

return $arguments;
}

/**
* @return ParameterResolver
*/
private function getParameterResolver()
{
if (null === $this->parameterResolver) {
$this->parameterResolver = new ResolverChain([
new AssociativeArrayResolver,
new TypeHintContainerResolver($this->container),
]);
}

return $this->parameterResolver;
}
}
7 changes: 7 additions & 0 deletions tests/Fixture/Application.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace DI\Bridge\Silex\Test\Fixture;

class Application extends \DI\Bridge\Silex\Application
{
}
63 changes: 48 additions & 15 deletions tests/FunctionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,6 @@ public function should_pass_url_placeholders()
$this->assertEquals('Hello john', $response->getContent());
}

/**
* @test
*/
public function should_pass_request_object()
{
$app = $this->createApplication();

$app->get('/', function (Request $request) {
return 'Hello ' . $request->get('name');
});

$response = $app->handle(Request::create('/?name=john'));
$this->assertEquals('Hello john', $response->getContent());
}

/**
* @test
*/
Expand Down Expand Up @@ -142,4 +127,52 @@ public function should_pass_the_container_based_on_type_hint()
$response = $app->handle(Request::create('/'));
$this->assertEquals('bar', $response->getContent());
}

/**
* @test
*/
public function should_pass_the_silex_application_based_on_type_hint()
{
$app = $this->createApplication();
$app['foo'] = 'bar';

$app->get('/', function (\Silex\Application $a) {
return $a['foo'];
});

$response = $app->handle(Request::create('/'));
$this->assertEquals('bar', $response->getContent());
}

/**
* @test
*/
public function should_pass_the_own_application_based_on_type_hint()
{
$app = new \DI\Bridge\Silex\Test\Fixture\Application(null, [
'foo' => 'bar',
]);

$app->get('/', function (\DI\Bridge\Silex\Test\Fixture\Application $a) {
return $a['foo'];
});

$response = $app->handle(Request::create('/'));
$this->assertEquals('bar', $response->getContent());
}

/**
* @test
*/
public function should_pass_request_object_based_on_type_hint()
{
$app = $this->createApplication();

$app->get('/', function (Request $r) {
return 'Hello ' . $r->get('name');
});

$response = $app->handle(Request::create('/?name=john'));
$this->assertEquals('Hello john', $response->getContent());
}
}
20 changes: 20 additions & 0 deletions tests/ProvidersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace DI\Bridge\Silex\Test;

use DI\Bridge\Silex\Test\Fixture\Controller;
use DI\ContainerBuilder;
use Silex\Provider\ServiceControllerServiceProvider;
use Silex\Provider\SwiftmailerServiceProvider;
use Silex\Provider\TwigServiceProvider;
use Symfony\Component\HttpFoundation\Request;
Expand Down Expand Up @@ -83,4 +85,22 @@ public function test_mailer()
$response = $app->handle(Request::create('/'));
$this->assertEquals('OK', $response->getContent());
}

/**
* @see https://github.com/PHP-DI/Silex-Bridge/issues/7
* @test
*/
public function test_service_controller_service_provider()
{
$app = $this->createApplication();

$app->register(new ServiceControllerServiceProvider, [
'service.controller' => new Controller(),
]);

$app->get('/{name}', 'service.controller:hello');

$response = $app->handle(Request::create('/john'));
$this->assertEquals('Hello john', $response->getContent());
}
}

0 comments on commit 0ee3381

Please sign in to comment.