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)
{
return $argument->hasDefaultValue() || $argument->isNullable();
return $argument->hasDefaultValue() || ($argument->isNullable() && !$argument->isVariadic());
}
/**

View File

@ -40,7 +40,7 @@ class ArgumentMetadata
$this->isVariadic = $isVariadic;
$this->hasDefaultValue = $hasDefaultValue;
$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
*/

View File

@ -58,7 +58,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
}
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;
@ -88,23 +88,6 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
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.
*
@ -127,7 +110,16 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
private function getType(\ReflectionParameter $parameter)
{
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()) {

View File

@ -121,7 +121,7 @@ class ArgumentMetadataFactoryTest extends \PHPUnit_Framework_TestCase
new ArgumentMetadata('foo', 'string', false, false, null, true),
new ArgumentMetadata('bar', \stdClass::class, false, false, null, 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);
}