From 9c48756a19a930ce4dc13eb47a50b89de9e3b921 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Thu, 1 Sep 2016 09:08:10 +0200 Subject: [PATCH] Fixed the nullable support for php 7.1 and below --- .../Controller/ControllerResolver.php | 22 +++++++++++++- .../Controller/ControllerResolverTest.php | 29 +++++++++++++++++++ .../Controller/NullableController.php | 19 ++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 1d7c49607d..c76b57bb6a 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -27,6 +27,15 @@ class ControllerResolver implements ControllerResolverInterface { private $logger; + /** + * If the ...$arg functionality is available. + * + * Requires at least PHP 5.6.0 or HHVM 3.9.1 + * + * @var bool + */ + private $supportsVariadic; + /** * Constructor. * @@ -35,6 +44,8 @@ class ControllerResolver implements ControllerResolverInterface public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; + + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); } /** @@ -99,13 +110,20 @@ class ControllerResolver implements ControllerResolverInterface return $this->doGetArguments($request, $controller, $r->getParameters()); } + /** + * @param Request $request + * @param callable $controller + * @param \ReflectionParameter[] $parameters + * + * @return array The arguments to use when calling the action + */ 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)) { - if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) { + if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { $arguments = array_merge($arguments, array_values($attributes[$param->name])); } else { $arguments[] = $attributes[$param->name]; @@ -114,6 +132,8 @@ class ControllerResolver implements ControllerResolverInterface $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); + } elseif ($param->allowsNull()) { + $arguments[] = null; } else { if (is_array($controller)) { $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 101782e490..9aa7e20a9a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; @@ -222,6 +223,34 @@ class ControllerResolverTest extends \PHPUnit_Framework_TestCase $mock->getController($request); } + /** + * @requires PHP 7.1 + */ + public function testGetNullableArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('bar', new \stdClass()); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + + /** + * @requires PHP 7.1 + */ + public function testGetNullableArgumentsWithDefaults() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array(null, null, 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + protected function createControllerResolver(LoggerInterface $logger = null) { return new ControllerResolver($logger); diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php new file mode 100644 index 0000000000..9db4df7b4c --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; + +class NullableController +{ + public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory) + { + } +}