From 0743526e2f2b67fe65f9e7802cb8e941de083ffd Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 28 Feb 2014 13:25:25 +0100 Subject: [PATCH 1/5] Refactored argument resolving out of the ControllerResolver --- .../FrameworkBundle/FrameworkBundle.php | 2 + .../Resources/config/services.xml | 1 + .../FrameworkBundle/Resources/config/web.xml | 10 ++ src/Symfony/Component/HttpKernel/CHANGELOG.md | 2 + .../RequestArgumentResolver.php | 41 ++++++ .../RequestAttributesArgumentResolver.php | 41 ++++++ .../Controller/ArgumentResolverInterface.php | 44 +++++++ .../Controller/ArgumentResolverManager.php | 88 +++++++++++++ .../Controller/ControllerResolver.php | 5 + .../ContainerAwareHttpKernel.php | 6 +- .../RegisterArgumentResolversPass.php | 56 +++++++++ .../Component/HttpKernel/HttpKernel.php | 30 ++++- .../ArgumentResolverManagerTest.php | 118 ++++++++++++++++++ .../Debug/TraceableEventDispatcherTest.php | 8 +- .../ContainerAwareHttpKernelTest.php | 19 +-- .../Fragment/InlineFragmentRendererTest.php | 10 +- 16 files changed, 460 insertions(+), 21 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php create mode 100644 src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php create mode 100644 src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php create mode 100644 src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php 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/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..7f89d7fa2d329 --- /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 accepts(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..ce1af652c59a6 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.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 which names are equal to the name of a request attribute. + * + * @author Wouter J + */ +class RequestAttributesArgumentResolver implements ArgumentResolverInterface +{ + /** + * {@inheritDoc} + */ + public function accepts(Request $request, \ReflectionParameter $parameter) + { + return array_key_exists($parameter->name, $request->attributes->all()); + } + + /** + * {@inheritDoc} + */ + public function resolve(Request $request, \ReflectionParameter $parameter) + { + $attributes = $request->attributes->all(); + + return $attributes[$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..a58256568d536 --- /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 Boolean + */ + public function accepts(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..5c4e394ebb295 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php @@ -0,0 +1,88 @@ + + * + * 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 addResolver(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_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->accepts($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..03561fb3f1c5c 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -90,6 +90,8 @@ public function getController(Request $request) * {@inheritdoc} * * @api + * + * @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead */ public function getArguments(Request $request, $controller) { @@ -105,6 +107,9 @@ public function getArguments(Request $request, $controller) return $this->doGetArguments($request, $controller, $r->getParameters()); } + /** + * @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead + */ protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); 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..e80a1593684bb --- /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 + */ + protected $managerService; + + /** + * @var string + */ + protected $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('addResolver', array(new Reference($id))); + } + } +} diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 82ffa95d71208..e465da9f28684 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->addResolver(new ArgumentResolver\RequestArgumentResolver()); + $this->argumentResolver->addResolver(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..fb1514edcfaa9 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php @@ -0,0 +1,118 @@ + + * + * 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->manager = new ArgumentResolverManager(); + $this->resolver1 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface'); + $this->resolver2 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface'); + $this->manager->addResolver($this->resolver1); + $this->manager->addResolver($this->resolver2); + + $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + } + + public function testGetArgumentsFirstResolverAccepts() + { + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); + $this->resolver1->expects($this->any()) + ->method('resolve') + ->will($this->returnValue('resolved_value')); + + $controller = $this->getControllerWithOneArgument(); + + $arguments = $this->manager->getArguments($this->request, $controller); + $this->assertEquals(array('resolved_value'), $arguments); + } + + public function testGetArgumentsSecondResolverAccepts() + { + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(true)); + $this->resolver2->expects($this->any()) + ->method('resolve') + ->will($this->returnValue('resolved_value')); + + $controller = $this->getControllerWithOneArgument(); + + $arguments = $this->manager->getArguments($this->request, $controller); + $this->assertEquals(array('resolved_value'), $arguments); + } + + /** + * @expectedException RuntimeException + */ + public function testGetArgumentsFailsIfNoResolverAccepts() + { + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + + $controller = $this->getControllerWithOneArgument(); + $this->manager->getArguments($this->request, $controller); + } + + public function testGetArgumentResolvingMultipleArguments() + { + $this->resolver1->expects($this->any()) + ->method('accepts') + ->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('accepts') + ->will($this->onConsecutiveCalls(true, false, true)); + $this->resolver2->expects($this->any()) + ->method('resolve') + ->will($this->onConsecutiveCalls('1st resolved by 2', '2nd resolved by 2')); + + $controller = function ($a, $b, $c) { }; + + $arguments = $this->manager->getArguments($this->request, $controller); + $this->assertEquals(array('1st resolved by 2', '1st resolved by 1', '2nd resolved by 1'), $arguments); + } + + public function testControllerWithOneOptionalArgumentWhichDoesNotMatch() + { + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + + $arguments = $this->manager->getArguments($this->request, function ($a = 'default') { }); + $this->assertEquals(array('default'), $arguments); + } + + public function testControllerWithOneOptionalArgumentWhichDoMatch() + { + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); + $this->resolver1->expects($this->any())->method('resolve')->will($this->returnValue('resolved by 1')); + $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + + $arguments = $this->manager->getArguments($this->request, function ($a = 'default') { }); + $this->assertEquals(array('resolved by 1'), $arguments); + } + + protected function getControllerWithOneArgument() + { + return function ($a) { }; + } +} 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 From 667e141bc79be83fa926228b691031daa630fddf Mon Sep 17 00:00:00 2001 From: WouterJ Date: Thu, 19 Feb 2015 19:56:57 +0100 Subject: [PATCH 2/5] Revisit PR --- .../RequestArgumentResolver.php | 4 +- .../RequestAttributesArgumentResolver.php | 8 ++- .../Controller/ArgumentResolverInterface.php | 8 +-- .../Controller/ArgumentResolverManager.php | 8 ++- .../Controller/ControllerResolver.php | 51 ------------------- .../ControllerResolverInterface.php | 14 ----- .../RegisterArgumentResolversPass.php | 6 +-- .../Component/HttpKernel/HttpKernel.php | 4 +- .../ArgumentResolverManagerTest.php | 6 +-- 9 files changed, 23 insertions(+), 86 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php index 7f89d7fa2d329..105f835654620 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php @@ -24,10 +24,10 @@ class RequestArgumentResolver implements ArgumentResolverInterface /** * {@inheritDoc} */ - public function accepts(Request $request, \ReflectionParameter $parameter) + public function supports(Request $request, \ReflectionParameter $parameter) { $class = $parameter->getClass(); - + return $class && $class->isInstance($request); } diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php index ce1af652c59a6..67269e0a4a893 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php @@ -24,9 +24,9 @@ class RequestAttributesArgumentResolver implements ArgumentResolverInterface /** * {@inheritDoc} */ - public function accepts(Request $request, \ReflectionParameter $parameter) + public function supports(Request $request, \ReflectionParameter $parameter) { - return array_key_exists($parameter->name, $request->attributes->all()); + return $request->attributes->has($parameter->name); } /** @@ -34,8 +34,6 @@ public function accepts(Request $request, \ReflectionParameter $parameter) */ public function resolve(Request $request, \ReflectionParameter $parameter) { - $attributes = $request->attributes->all(); - - return $attributes[$parameter->name]; + return $request->attributes->get($parameter->name); } } diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php index a58256568d536..92ef9a0920a43 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php @@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\Request; /** - * An ArgumentResolverInterface implementation resolves the arguments of + * An ArgumentResolverInterface implementation resolves the arguments of * controllers. * * @author Wouter J @@ -22,7 +22,7 @@ interface ArgumentResolverInterface { /** - * Checks if the current parameter can be resolved by this argument + * Checks if the current parameter can be resolved by this argument * resolver. * * @param Request $request @@ -30,14 +30,14 @@ interface ArgumentResolverInterface * * @return Boolean */ - public function accepts(Request $request, \ReflectionParameter $parameter); + 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 index 5c4e394ebb295..dd1cd4bd2a186 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php @@ -31,7 +31,7 @@ class ArgumentResolverManager * * @param ArgumentResolverInterface $resolver */ - public function addResolver(ArgumentResolverInterface $resolver) + public function add(ArgumentResolverInterface $resolver) { $this->resolvers[] = $resolver; } @@ -48,6 +48,10 @@ public function addResolver(ArgumentResolverInterface $resolver) */ 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) { @@ -62,7 +66,7 @@ public function getArguments(Request $request, $controller) foreach ($parameters as $parameter) { foreach ($this->resolvers as $argumentResolver) { - if ($argumentResolver->accepts($request, $parameter)) { + if ($argumentResolver->supports($request, $parameter)) { $arguments[] = $argumentResolver->resolve($request, $parameter); continue 2; } diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 03561fb3f1c5c..5e4f2d0c9404c 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -86,57 +86,6 @@ public function getController(Request $request) return $callable; } - /** - * {@inheritdoc} - * - * @api - * - * @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead - */ - 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()); - } - - /** - * @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead - */ - 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/RegisterArgumentResolversPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php index e80a1593684bb..0e2f7baa69878 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php @@ -25,12 +25,12 @@ class RegisterArgumentResolversPass implements CompilerPassInterface /** * @var string */ - protected $managerService; + private $managerService; /** * @var string */ - protected $resolverTag; + private $resolverTag; public function __construct($managerService = 'argument_resolver.manager', $resolverTag = 'kernel.argument_resolver') { @@ -50,7 +50,7 @@ public function process(ContainerBuilder $container) $definition = $container->findDefinition($this->managerService); foreach ($container->findTaggedServiceIds($this->resolverTag) as $id => $resolvers) { - $definition->addMethodCall('addResolver', array(new Reference($id))); + $definition->addMethodCall('add', array(new Reference($id))); } } } diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index e465da9f28684..12b81149acc0e 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -304,8 +304,8 @@ protected function getArgumentResolver() if (null === $this->argumentResolver) { // to keep BC $this->argumentResolver = new ArgumentResolverManager(); - $this->argumentResolver->addResolver(new ArgumentResolver\RequestArgumentResolver()); - $this->argumentResolver->addResolver(new ArgumentResolver\RequestAttributesArgumentResolver()); + $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 index fb1514edcfaa9..a18794b573aad 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php @@ -25,15 +25,15 @@ public function setUp() $this->manager = new ArgumentResolverManager(); $this->resolver1 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface'); $this->resolver2 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface'); - $this->manager->addResolver($this->resolver1); - $this->manager->addResolver($this->resolver2); + $this->manager->add($this->resolver1); + $this->manager->add($this->resolver2); $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); } public function testGetArgumentsFirstResolverAccepts() { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); + $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); $this->resolver1->expects($this->any()) ->method('resolve') ->will($this->returnValue('resolved_value')); From 966ffe620f47261a1900b45eebc19a649012ab22 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Thu, 19 Feb 2015 20:01:23 +0100 Subject: [PATCH 3/5] Make fabbot happy --- .../Controller/ArgumentResolver/RequestArgumentResolver.php | 4 ++-- .../ArgumentResolver/RequestAttributesArgumentResolver.php | 4 ++-- .../HttpKernel/Controller/ArgumentResolverInterface.php | 2 +- .../DependencyInjection/RegisterArgumentResolversPass.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php index 105f835654620..ba4815a1d8af8 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php @@ -22,7 +22,7 @@ class RequestArgumentResolver implements ArgumentResolverInterface { /** - * {@inheritDoc} + * {@inheritdoc} */ public function supports(Request $request, \ReflectionParameter $parameter) { @@ -32,7 +32,7 @@ public function supports(Request $request, \ReflectionParameter $parameter) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function resolve(Request $request, \ReflectionParameter $parameter) { diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php index 67269e0a4a893..9f5c84f81a15a 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php @@ -22,7 +22,7 @@ class RequestAttributesArgumentResolver implements ArgumentResolverInterface { /** - * {@inheritDoc} + * {@inheritdoc} */ public function supports(Request $request, \ReflectionParameter $parameter) { @@ -30,7 +30,7 @@ public function supports(Request $request, \ReflectionParameter $parameter) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function resolve(Request $request, \ReflectionParameter $parameter) { diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php index 92ef9a0920a43..766c9f3666256 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverInterface.php @@ -28,7 +28,7 @@ interface ArgumentResolverInterface * @param Request $request * @param \ReflectionParameter $parameter * - * @return Boolean + * @return bool */ public function supports(Request $request, \ReflectionParameter $parameter); diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php index 0e2f7baa69878..b4f72a012ff2b 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php @@ -39,8 +39,8 @@ public function __construct($managerService = 'argument_resolver.manager', $reso } /** - * {@inheritDoc} - */ + * {@inheritdoc} + */ public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->managerService) && !$container->hasAlias($this->managerService)) { From 416a33edff373c52020f7de583b45e1a34cf7fd2 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 6 Apr 2015 18:08:11 +0200 Subject: [PATCH 4/5] Cleanup tests --- .../Controller/ControllerResolverTest.php | 4 +- .../ArgumentResolverManagerTest.php | 94 +++++++++++-------- .../Controller/ControllerResolverTest.php | 87 ++--------------- 3 files changed, 63 insertions(+), 122 deletions(-) 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/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php index a18794b573aad..0ad048c551e78 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php @@ -22,40 +22,34 @@ class ArgumentResolverManagerTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->manager = new ArgumentResolverManager(); $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 testGetArgumentsFirstResolverAccepts() + public function testGetArgumentsWithoutControllerParameters() { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); - $this->resolver1->expects($this->any()) - ->method('resolve') - ->will($this->returnValue('resolved_value')); + $this->assertArguments(array(), function () { }); + } - $controller = $this->getControllerWithOneArgument(); + public function testGetArgumentsFirstResolverAccepts() + { + $this->promiseResolverToMatch($this->resolver1, 'resolved_value'); - $arguments = $this->manager->getArguments($this->request, $controller); - $this->assertEquals(array('resolved_value'), $arguments); + $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter()); } public function testGetArgumentsSecondResolverAccepts() { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); - $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(true)); - $this->resolver2->expects($this->any()) - ->method('resolve') - ->will($this->returnValue('resolved_value')); - - $controller = $this->getControllerWithOneArgument(); + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToMatch($this->resolver2, 'resolved_value'); - $arguments = $this->manager->getArguments($this->request, $controller); - $this->assertEquals(array('resolved_value'), $arguments); + $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter()); } /** @@ -63,55 +57,75 @@ public function testGetArgumentsSecondResolverAccepts() */ public function testGetArgumentsFailsIfNoResolverAccepts() { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); - $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToNotMatch($this->resolver2); - $controller = $this->getControllerWithOneArgument(); - $this->manager->getArguments($this->request, $controller); + $this->manager->getArguments($this->request, $this->getControllerWithOneParameter()); } - public function testGetArgumentResolvingMultipleArguments() + public function testGetArgumentResolvingMultipleParameters() { $this->resolver1->expects($this->any()) - ->method('accepts') + ->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('accepts') + ->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')); - $controller = function ($a, $b, $c) { }; + $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); - $arguments = $this->manager->getArguments($this->request, $controller); - $this->assertEquals(array('1st resolved by 2', '1st resolved by 1', '2nd resolved by 1'), $arguments); + $this->assertArguments(array('resolved by 1'), function ($a = 'default') { }); } - public function testControllerWithOneOptionalArgumentWhichDoesNotMatch() + public function testControllerWithOneParameterWithNullDefault() { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false)); - $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToNotMatch($this->resolver2); + + $this->assertArguments(array(null), function ($a = null) { }); + } - $arguments = $this->manager->getArguments($this->request, function ($a = 'default') { }); - $this->assertEquals(array('default'), $arguments); + private function assertArguments(array $expected, $controller) + { + $this->assertEquals($expected, $this->manager->getArguments($this->request, $controller)); } - public function testControllerWithOneOptionalArgumentWhichDoMatch() + private function promiseResolverToMatch($resolver, $return) { - $this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true)); - $this->resolver1->expects($this->any())->method('resolve')->will($this->returnValue('resolved by 1')); - $this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false)); + $resolver->expects($this->any())->method('supports')->will($this->returnValue(true)); + $resolver->expects($this->any())->method('resolve')->will($this->returnValue($return)); + } - $arguments = $this->manager->getArguments($this->request, function ($a = 'default') { }); - $this->assertEquals(array('resolved by 1'), $arguments); + private function promiseResolverToNotMatch($resolver) + { + $resolver->expects($this->any())->method('supports')->will($this->returnValue(false)); } - protected function getControllerWithOneArgument() + 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() { } } From 1a34c3390950cf6661fd32c631164ff99330b13d Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 8 May 2015 16:01:16 +0200 Subject: [PATCH 5/5] Fix dep version --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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",