diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 499f39c6c95c0..6a1c8baf7f9dd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -36,6 +36,7 @@
use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\HttpKernel\DependencyInjection\RegisterArgumentResolversPass;
/**
* Bundle.
@@ -88,6 +89,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SerializerPass());
+ $container->addCompilerPass(new RegisterArgumentResolversPass());
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
index 63cbe6b00d682..09d60727bdb87 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
@@ -14,6 +14,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
index af7d37449a6cb..b75b810d97e11 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
@@ -17,6 +17,16 @@
+
+
+
+
+
+
+
+
+
+
%kernel.charset%
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
index 4e804bf079701..c444aff651645 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php
@@ -65,12 +65,12 @@ public function testGetControllerService()
$resolver = $this->createControllerResolver(null, null, $container);
$request = Request::create('/');
- $request->attributes->set('_controller', 'foo:controllerMethod1');
+ $request->attributes->set('_controller', 'foo:controllerMethod');
$controller = $resolver->getController($request);
$this->assertInstanceOf(get_class($this), $controller[0]);
- $this->assertSame('controllerMethod1', $controller[1]);
+ $this->assertSame('controllerMethod', $controller[1]);
}
public function testGetControllerInvokableService()
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index db09b59b9cd6e..0dd47ac13d342 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -18,7 +18,7 @@
"require": {
"php": ">=5.5.9",
"symfony/asset": "~2.7|~3.0",
- "symfony/dependency-injection" : "~2.7|~3.0",
+ "symfony/dependency-injection" : "~3.0",
"symfony/config" : "~2.7|~3.0",
"symfony/event-dispatcher": "~2.7|~3.0",
"symfony/http-foundation": "~2.7|~3.0",
diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md
index 088e1803f4d11..b533cf3d32d5f 100644
--- a/src/Symfony/Component/HttpKernel/CHANGELOG.md
+++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md
@@ -4,6 +4,8 @@ CHANGELOG
3.0.0
-----
+ * added argument resolvers
+ * deprecated `Symfony\Component\HttpKernel\Controller\ControllerResolver#getArguments()` and `doGetArguments()`, use argument resolvers instead
* removed `Symfony\Component\HttpKernel\Kernel::init()`
* removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()`
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php
new file mode 100644
index 0000000000000..ba4815a1d8af8
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Resolves arguments typehinting for the Request object.
+ *
+ * @author Wouter J
+ */
+class RequestArgumentResolver implements ArgumentResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, \ReflectionParameter $parameter)
+ {
+ $class = $parameter->getClass();
+
+ return $class && $class->isInstance($request);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, \ReflectionParameter $parameter)
+ {
+ return $request;
+ }
+}
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php
new file mode 100644
index 0000000000000..9f5c84f81a15a
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php
@@ -0,0 +1,39 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Resolves arguments which names are equal to the name of a request attribute.
+ *
+ * @author Wouter J
+ */
+class RequestAttributesArgumentResolver implements ArgumentResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, \ReflectionParameter $parameter)
+ {
+ return $request->attributes->has($parameter->name);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, \ReflectionParameter $parameter)
+ {
+ return $request->attributes->get($parameter->name);
+ }
+}
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php
new file mode 100644
index 0000000000000..766c9f3666256
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * An ArgumentResolverInterface implementation resolves the arguments of
+ * controllers.
+ *
+ * @author Wouter J
+ */
+interface ArgumentResolverInterface
+{
+ /**
+ * Checks if the current parameter can be resolved by this argument
+ * resolver.
+ *
+ * @param Request $request
+ * @param \ReflectionParameter $parameter
+ *
+ * @return bool
+ */
+ public function supports(Request $request, \ReflectionParameter $parameter);
+
+ /**
+ * Resolves the current parameter into an argument.
+ *
+ * @param Request $request
+ * @param \ReflectionParameter $parameter
+ *
+ * @return mixed The resolved argument
+ */
+ public function resolve(Request $request, \ReflectionParameter $parameter);
+}
diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php
new file mode 100644
index 0000000000000..dd1cd4bd2a186
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php
@@ -0,0 +1,92 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * The ArgumentResolverManager chains over the registered argument resolvers to
+ * resolve all controller arguments.
+ *
+ * @author Wouter J
+ */
+class ArgumentResolverManager
+{
+ /**
+ * @var ArgumentResolverInterface[]
+ */
+ protected $resolvers = array();
+
+ /**
+ * Adds an argument resolver.
+ *
+ * @param ArgumentResolverInterface $resolver
+ */
+ public function add(ArgumentResolverInterface $resolver)
+ {
+ $this->resolvers[] = $resolver;
+ }
+
+ /**
+ * Returns the arguments to pass to the controller.
+ *
+ * @param Request $request A Request instance
+ * @param callable $controller A PHP callable
+ *
+ * @return array an array of arguments to pass to the controller
+ *
+ * @throws \RuntimeException When a parameter cannot be resolved
+ */
+ public function getArguments(Request $request, $controller)
+ {
+ if (!is_callable($controller)) {
+ throw new \InvalidArgumentException(sprintf('Expected a callable as second parameter, got "%s".', is_object($controller) ? get_class($controller) : gettype($controller)));
+ }
+
+ if (is_array($controller)) {
+ $controllerReflection = new \ReflectionMethod($controller[0], $controller[1]);
+ } elseif (is_object($controller) && !$controller instanceof \Closure) {
+ $controllerReflection = new \ReflectionObject($controller);
+ $controllerReflection = $controllerReflection->getMethod('__invoke');
+ } else {
+ $controllerReflection = new \ReflectionFunction($controller);
+ }
+
+ $parameters = $controllerReflection->getParameters();
+ $arguments = array();
+
+ foreach ($parameters as $parameter) {
+ foreach ($this->resolvers as $argumentResolver) {
+ if ($argumentResolver->supports($request, $parameter)) {
+ $arguments[] = $argumentResolver->resolve($request, $parameter);
+ continue 2;
+ }
+ }
+
+ if ($parameter->isDefaultValueAvailable()) {
+ $arguments[] = $parameter->getDefaultValue();
+ } else {
+ if (is_array($controller)) {
+ $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
+ } elseif (is_object($controller)) {
+ $repr = get_class($controller);
+ } else {
+ $repr = $controller;
+ }
+
+ throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value and none of the argument resolvers could resolve its value).', $repr, $parameter->name));
+ }
+ }
+
+ return $arguments;
+ }
+}
diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php
index 94df05eee415f..5e4f2d0c9404c 100644
--- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php
+++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php
@@ -86,52 +86,6 @@ public function getController(Request $request)
return $callable;
}
- /**
- * {@inheritdoc}
- *
- * @api
- */
- public function getArguments(Request $request, $controller)
- {
- if (is_array($controller)) {
- $r = new \ReflectionMethod($controller[0], $controller[1]);
- } elseif (is_object($controller) && !$controller instanceof \Closure) {
- $r = new \ReflectionObject($controller);
- $r = $r->getMethod('__invoke');
- } else {
- $r = new \ReflectionFunction($controller);
- }
-
- return $this->doGetArguments($request, $controller, $r->getParameters());
- }
-
- protected function doGetArguments(Request $request, $controller, array $parameters)
- {
- $attributes = $request->attributes->all();
- $arguments = array();
- foreach ($parameters as $param) {
- if (array_key_exists($param->name, $attributes)) {
- $arguments[] = $attributes[$param->name];
- } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
- $arguments[] = $request;
- } elseif ($param->isDefaultValueAvailable()) {
- $arguments[] = $param->getDefaultValue();
- } else {
- if (is_array($controller)) {
- $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
- } elseif (is_object($controller)) {
- $repr = get_class($controller);
- } else {
- $repr = $controller;
- }
-
- throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
- }
- }
-
- return $arguments;
- }
-
/**
* Returns a callable for the given controller.
*
diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php
index 6f805ed2dab77..c643e29daef22 100644
--- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php
+++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php
@@ -46,18 +46,4 @@ interface ControllerResolverInterface
* @api
*/
public function getController(Request $request);
-
- /**
- * Returns the arguments to pass to the controller.
- *
- * @param Request $request A Request instance
- * @param callable $controller A PHP callable
- *
- * @return array An array of arguments to pass to the controller
- *
- * @throws \RuntimeException When value for argument given is not provided
- *
- * @api
- */
- public function getArguments(Request $request, $controller);
}
diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
index 4d249f69ef7ac..6dd0b61e0cba1 100644
--- a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
+++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
@@ -15,6 +15,7 @@
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -39,10 +40,11 @@ class ContainerAwareHttpKernel extends HttpKernel
* @param ContainerInterface $container A ContainerInterface instance
* @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance
* @param RequestStack $requestStack A stack for master/sub requests
+ * @param ArgumentResolverManager $argumentResolver An ArgumentResolverManager instance
*/
- public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null)
+ public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null, ArgumentResolverManager $argumentResolver = null)
{
- parent::__construct($dispatcher, $controllerResolver, $requestStack);
+ parent::__construct($dispatcher, $controllerResolver, $requestStack, $argumentResolver);
$this->container = $container;
diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php
new file mode 100644
index 0000000000000..b4f72a012ff2b
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php
@@ -0,0 +1,56 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Compiler pass to register argument resolvers.
+ *
+ * @author Wouter J
+ */
+class RegisterArgumentResolversPass implements CompilerPassInterface
+{
+ /**
+ * @var string
+ */
+ private $managerService;
+
+ /**
+ * @var string
+ */
+ private $resolverTag;
+
+ public function __construct($managerService = 'argument_resolver.manager', $resolverTag = 'kernel.argument_resolver')
+ {
+ $this->managerService = $managerService;
+ $this->resolverTag = $resolverTag;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->managerService) && !$container->hasAlias($this->managerService)) {
+ return;
+ }
+
+ $definition = $container->findDefinition($this->managerService);
+
+ foreach ($container->findTaggedServiceIds($this->resolverTag) as $id => $resolvers) {
+ $definition->addMethodCall('add', array(new Reference($id)));
+ }
+ }
+}
diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php
index 82ffa95d71208..12b81149acc0e 100644
--- a/src/Symfony/Component/HttpKernel/HttpKernel.php
+++ b/src/Symfony/Component/HttpKernel/HttpKernel.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\HttpKernel;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
@@ -37,22 +39,25 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
{
protected $dispatcher;
protected $resolver;
+ protected $argumentResolver;
protected $requestStack;
/**
* Constructor.
*
- * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
- * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance
- * @param RequestStack $requestStack A stack for master/sub requests
+ * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance
+ * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance
+ * @param RequestStack $requestStack A stack for master/sub requests
+ * @param ArgumentResolverManager $argumentResolver An ArgumentResolverManager instance
*
* @api
*/
- public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null)
+ public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverManager $argumentResolver = null)
{
$this->dispatcher = $dispatcher;
$this->resolver = $resolver;
$this->requestStack = $requestStack ?: new RequestStack();
+ $this->argumentResolver = $argumentResolver;
}
/**
@@ -141,7 +146,7 @@ private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
$controller = $event->getController();
// controller arguments
- $arguments = $this->resolver->getArguments($request, $controller);
+ $arguments = $this->getArgumentResolver()->getArguments($request, $controller);
// call controller
$response = call_user_func_array($controller, $arguments);
@@ -290,4 +295,19 @@ private function varToString($var)
return (string) $var;
}
+
+ /**
+ * @return ArgumentResolverManager
+ */
+ protected function getArgumentResolver()
+ {
+ if (null === $this->argumentResolver) {
+ // to keep BC
+ $this->argumentResolver = new ArgumentResolverManager();
+ $this->argumentResolver->add(new ArgumentResolver\RequestArgumentResolver());
+ $this->argumentResolver->add(new ArgumentResolver\RequestAttributesArgumentResolver());
+ }
+
+ return $this->argumentResolver;
+ }
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php
new file mode 100644
index 0000000000000..0ad048c551e78
--- /dev/null
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php
@@ -0,0 +1,132 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpKernel\Tests\Controller;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager;
+
+class ArgumentResolverManagerTest extends \PHPUnit_Framework_TestCase
+{
+ protected $manager;
+ protected $resolver1;
+ protected $resolver2;
+ protected $request;
+
+ public function setUp()
+ {
+ $this->resolver1 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
+ $this->resolver2 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
+
+ $this->manager = new ArgumentResolverManager();
+ $this->manager->add($this->resolver1);
+ $this->manager->add($this->resolver2);
+
+ $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
+ }
+
+ public function testGetArgumentsWithoutControllerParameters()
+ {
+ $this->assertArguments(array(), function () { });
+ }
+
+ public function testGetArgumentsFirstResolverAccepts()
+ {
+ $this->promiseResolverToMatch($this->resolver1, 'resolved_value');
+
+ $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter());
+ }
+
+ public function testGetArgumentsSecondResolverAccepts()
+ {
+ $this->promiseResolverToNotMatch($this->resolver1);
+ $this->promiseResolverToMatch($this->resolver2, 'resolved_value');
+
+ $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter());
+ }
+
+ /**
+ * @expectedException RuntimeException
+ */
+ public function testGetArgumentsFailsIfNoResolverAccepts()
+ {
+ $this->promiseResolverToNotMatch($this->resolver1);
+ $this->promiseResolverToNotMatch($this->resolver2);
+
+ $this->manager->getArguments($this->request, $this->getControllerWithOneParameter());
+ }
+
+ public function testGetArgumentResolvingMultipleParameters()
+ {
+ $this->resolver1->expects($this->any())
+ ->method('supports')
+ ->will($this->onConsecutiveCalls(false, true, true));
+ $this->resolver1->expects($this->any())
+ ->method('resolve')
+ ->will($this->onConsecutiveCalls('1st resolved by 1', '2nd resolved by 1'));
+
+ $this->resolver2->expects($this->any())
+ ->method('supports')
+ ->will($this->onConsecutiveCalls(true, false, true));
+ $this->resolver2->expects($this->any())
+ ->method('resolve')
+ ->will($this->onConsecutiveCalls('1st resolved by 2', '2nd resolved by 2'));
+
+ $this->assertArguments(
+ array('1st resolved by 2', '1st resolved by 1', '2nd resolved by 1'),
+ function ($a, $b, $c) { }
+ );
+ }
+
+ public function testControllerWithOneOptionalParameterWhichDoesNotMatch()
+ {
+ $this->promiseResolverToNotMatch($this->resolver1);
+ $this->promiseResolverToNotMatch($this->resolver2);
+
+ $this->assertArguments(array('default'), function ($a = 'default') { });
+ }
+
+ public function testControllerWithOneOptionalParameterWhichDoesMatch()
+ {
+ $this->promiseResolverToMatch($this->resolver1, 'resolved by 1');
+ $this->promiseResolverToNotMatch($this->resolver2);
+
+ $this->assertArguments(array('resolved by 1'), function ($a = 'default') { });
+ }
+
+ public function testControllerWithOneParameterWithNullDefault()
+ {
+ $this->promiseResolverToNotMatch($this->resolver1);
+ $this->promiseResolverToNotMatch($this->resolver2);
+
+ $this->assertArguments(array(null), function ($a = null) { });
+ }
+
+ private function assertArguments(array $expected, $controller)
+ {
+ $this->assertEquals($expected, $this->manager->getArguments($this->request, $controller));
+ }
+
+ private function promiseResolverToMatch($resolver, $return)
+ {
+ $resolver->expects($this->any())->method('supports')->will($this->returnValue(true));
+ $resolver->expects($this->any())->method('resolve')->will($this->returnValue($return));
+ }
+
+ private function promiseResolverToNotMatch($resolver)
+ {
+ $resolver->expects($this->any())->method('supports')->will($this->returnValue(false));
+ }
+
+ private function getControllerWithOneParameter()
+ {
+ return function ($a) { };
+ }
+}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
index 4b886ee10977d..ba78109af9cb0 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php
@@ -52,9 +52,9 @@ public function testGetControllerWithObjectAndMethod()
$resolver = $this->createControllerResolver();
$request = Request::create('/');
- $request->attributes->set('_controller', array($this, 'controllerMethod1'));
+ $request->attributes->set('_controller', array($this, 'controllerMethod'));
$controller = $resolver->getController($request);
- $this->assertSame(array($this, 'controllerMethod1'), $controller);
+ $this->assertSame(array($this, 'controllerMethod'), $controller);
}
public function testGetControllerWithClassAndMethod()
@@ -62,9 +62,9 @@ public function testGetControllerWithClassAndMethod()
$resolver = $this->createControllerResolver();
$request = Request::create('/');
- $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'));
+ $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'staticControllerMethod'));
$controller = $resolver->getController($request);
- $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'), $controller);
+ $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'staticControllerMethod'), $controller);
}
public function testGetControllerWithObjectAndMethodAsString()
@@ -72,7 +72,7 @@ public function testGetControllerWithObjectAndMethodAsString()
$resolver = $this->createControllerResolver();
$request = Request::create('/');
- $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1');
+ $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod');
$controller = $resolver->getController($request);
$this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable');
}
@@ -132,67 +132,6 @@ public function getUndefinedControllers()
);
}
- public function testGetArguments()
- {
- $resolver = $this->createControllerResolver();
-
- $request = Request::create('/');
- $controller = array(new self(), 'testGetArguments');
- $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments');
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $controller = array(new self(), 'controllerMethod1');
- $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method');
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $controller = array(new self(), 'controllerMethod2');
- $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present');
-
- $request->attributes->set('bar', 'bar');
- $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes');
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $controller = function ($foo) {};
- $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller));
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $controller = function ($foo, $bar = 'bar') {};
- $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller));
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $controller = new self();
- $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller));
- $request->attributes->set('bar', 'bar');
- $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller));
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $request->attributes->set('foobar', 'foobar');
- $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function';
- $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller));
-
- $request = Request::create('/');
- $request->attributes->set('foo', 'foo');
- $request->attributes->set('foobar', 'foobar');
- $controller = array(new self(), 'controllerMethod3');
-
- try {
- $resolver->getArguments($request, $controller);
- $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value');
- } 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 testCreateControllerCanReturnAnyCallable()
{
$mock = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolver', array('createController'));
@@ -212,23 +151,11 @@ public function __invoke($foo, $bar = null)
{
}
- public function controllerMethod1($foo)
- {
- }
-
- protected function controllerMethod2($foo, $bar = null)
- {
- }
-
- protected function controllerMethod3($foo, $bar = null, $foobar)
- {
- }
-
- protected static function controllerMethod4()
+ public function controllerMethod($foo)
{
}
- protected function controllerMethod5(Request $request)
+ protected static function staticControllerMethod()
{
}
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php
index c2cafc37b8cfa..5931086c60ea7 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php
@@ -96,9 +96,11 @@ public function testAddListenerNested()
protected function getHttpKernel($dispatcher, $controller)
{
$resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
- $resolver->expects($this->once())->method('getController')->will($this->returnValue($controller));
- $resolver->expects($this->once())->method('getArguments')->will($this->returnValue(array()));
+ $resolver->expects($this->any())->method('getController')->will($this->returnValue($controller));
- return new HttpKernel($dispatcher, $resolver);
+ $argumentResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverManager');
+ $argumentResolver->expects($this->any())->method('getArguments')->will($this->returnValue(array()));
+
+ return new HttpKernel($dispatcher, $resolver, null, $argumentResolver);
}
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
index 0b110d4a21b2f..73416da86132f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
@@ -42,7 +42,7 @@ public function testHandle($type)
$dispatcher = new EventDispatcher();
$resolver = $this->getResolverMockFor($controller, $request);
$stack = new RequestStack();
- $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);
+ $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack, $this->getArgumentsResolverMockFor($controller, $request));
$actual = $kernel->handle($request, $type);
@@ -67,7 +67,7 @@ public function testVerifyRequestStackPushPopDuringHandle($type)
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$dispatcher = new EventDispatcher();
$resolver = $this->getResolverMockFor($controller, $request);
- $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);
+ $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack, $this->getArgumentsResolverMockFor($controller, $request));
$kernel->handle($request, $type);
}
@@ -95,7 +95,7 @@ public function testHandleRestoresThePreviousRequestOnException($type)
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
$resolver = $this->getResolverMockFor($controller, $request);
$stack = new RequestStack();
- $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack);
+ $kernel = new ContainerAwareHttpKernel($dispatcher, $container, $resolver, $stack, $this->getArgumentsResolverMockFor($controller, $request));
try {
$kernel->handle($request, $type);
@@ -118,16 +118,21 @@ public function getProviderTypes()
private function getResolverMockFor($controller, $request)
{
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
- $resolver->expects($this->once())
+ $resolver->expects($this->any())
->method('getController')
->with($request)
->will($this->returnValue($controller));
- $resolver->expects($this->once())
+
+ return $resolver;
+ }
+
+ private function getArgumentsResolverMockFor($controller, $request)
+ {
+ $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ArgumentsResolverManager');
+ $resolver->expects($this->any())
->method('getArguments')
->with($request, $controller)
->will($this->returnValue(array()));
-
- return $resolver;
}
private function expectsSetRequestWithAt($container, $with, $at)
diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php
index 4e487a478a600..cddda31189e4f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php
@@ -144,7 +144,7 @@ public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
{
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
$resolver
- ->expects($this->once())
+ ->expects($this->any())
->method('getController')
->will($this->returnValue(function () {
ob_start();
@@ -152,13 +152,15 @@ public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
throw new \RuntimeException();
}))
;
- $resolver
- ->expects($this->once())
+
+ $argumentResolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverManager');
+ $argumentResolver
+ ->expects($this->any())
->method('getArguments')
->will($this->returnValue(array()))
;
- $kernel = new HttpKernel(new EventDispatcher(), $resolver);
+ $kernel = new HttpKernel(new EventDispatcher(), $resolver, null, $argumentResolver);
$renderer = new InlineFragmentRenderer($kernel);
// simulate a main request with output buffering