bug #20152 [HttpKernel] Fix nullable types handling (nicolas-grekas)

This PR was merged into the 3.1 branch.

Discussion
----------

[HttpKernel] Fix nullable types handling

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #19784
| License       | MIT
| Doc PR        | -

Commits
-------

0884518 [HttpKernel] Fix nullable types handling
This commit is contained in:
Fabien Potencier 2016-10-04 14:38:20 -07:00
commit 6f8e5b081a
4 changed files with 15 additions and 23 deletions

View File

@ -27,7 +27,7 @@ final class DefaultValueResolver implements ArgumentValueResolverInterface
*/ */
public function supports(Request $request, ArgumentMetadata $argument) public function supports(Request $request, ArgumentMetadata $argument)
{ {
return $argument->hasDefaultValue() || $argument->isNullable(); return $argument->hasDefaultValue() || ($argument->isNullable() && !$argument->isVariadic());
} }
/** /**

View File

@ -40,7 +40,7 @@ class ArgumentMetadata
$this->isVariadic = $isVariadic; $this->isVariadic = $isVariadic;
$this->hasDefaultValue = $hasDefaultValue; $this->hasDefaultValue = $hasDefaultValue;
$this->defaultValue = $defaultValue; $this->defaultValue = $defaultValue;
$this->isNullable = (bool) $isNullable; $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
} }
/** /**
@ -88,7 +88,7 @@ class ArgumentMetadata
} }
/** /**
* Returns whether the argument is nullable in PHP 7.1 or higher. * Returns whether the argument accepts null values.
* *
* @return bool * @return bool
*/ */

View File

@ -58,7 +58,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
} }
foreach ($reflection->getParameters() as $param) { foreach ($reflection->getParameters() as $param) {
$arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $this->isNullable($param)); $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull());
} }
return $arguments; return $arguments;
@ -88,23 +88,6 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
return $parameter->isDefaultValueAvailable(); return $parameter->isDefaultValueAvailable();
} }
/**
* Returns if the argument is allowed to be null but is still mandatory.
*
* @param \ReflectionParameter $parameter
*
* @return bool
*/
private function isNullable(\ReflectionParameter $parameter)
{
if ($this->supportsParameterType) {
return null !== ($type = $parameter->getType()) && $type->allowsNull();
}
// fallback for supported php 5.x versions
return $this->hasDefaultValue($parameter) && null === $this->getDefaultValue($parameter);
}
/** /**
* Returns a default value if available. * Returns a default value if available.
* *
@ -127,7 +110,16 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
private function getType(\ReflectionParameter $parameter) private function getType(\ReflectionParameter $parameter)
{ {
if ($this->supportsParameterType) { if ($this->supportsParameterType) {
return $parameter->hasType() ? (string) $parameter->getType() : null; if (!$type = $parameter->getType()) {
return;
}
$typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString();
if ('array' === $typeName && !$type->isBuiltin()) {
// Special case for HHVM with variadics
return;
}
return $typeName;
} }
if ($parameter->isArray()) { if ($parameter->isArray()) {

View File

@ -121,7 +121,7 @@ class ArgumentMetadataFactoryTest extends \PHPUnit_Framework_TestCase
new ArgumentMetadata('foo', 'string', false, false, null, true), new ArgumentMetadata('foo', 'string', false, false, null, true),
new ArgumentMetadata('bar', \stdClass::class, false, false, null, true), new ArgumentMetadata('bar', \stdClass::class, false, false, null, true),
new ArgumentMetadata('baz', 'string', false, true, 'value', true), new ArgumentMetadata('baz', 'string', false, true, 'value', true),
new ArgumentMetadata('mandatory', null, false, false, null), new ArgumentMetadata('mandatory', null, false, false, null, true),
), $arguments); ), $arguments);
} }