bug #15426 [Serializer] Add support for variadic arguments in the GetSetNormalizer (stof)

This PR was merged into the 2.3 branch.

Discussion
----------

[Serializer] Add support for variadic arguments in the GetSetNormalizer

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

There were 2 broken cases:

- when the value was passed, the array was passed as argument, becoming the first value of the variadic array. The array needs to be spread into multiple arguments when calling the method
- when the value was missing, the code would throw a ReflectionException, similar to the issue reported in #13690, because a variadic argument is optional but does not have a default value

Commits
-------

704760b Add support for variadic arguments in the GetSetNormalizer
This commit is contained in:
Fabien Potencier 2015-08-09 10:58:38 +02:00
commit 620a3d4c69
3 changed files with 59 additions and 2 deletions

View File

@ -136,11 +136,19 @@ class GetSetMethodNormalizer extends SerializerAwareNormalizer implements Normal
foreach ($constructorParameters as $constructorParameter) {
$paramName = lcfirst($this->formatAttribute($constructorParameter->name));
if (isset($normalizedData[$paramName])) {
if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) {
if (isset($normalizedData[$paramName])) {
if (!is_array($normalizedData[$paramName])) {
throw new RuntimeException(sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name));
}
$params = array_merge($params, $normalizedData[$paramName]);
}
} elseif (isset($normalizedData[$paramName])) {
$params[] = $normalizedData[$paramName];
// don't run set for a parameter passed to the constructor
unset($normalizedData[$paramName]);
} elseif ($constructorParameter->isOptional()) {
} elseif ($constructorParameter->isDefaultValueAvailable()) {
$params[] = $constructorParameter->getDefaultValue();
} else {
throw new RuntimeException(

View File

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Serializer\Tests\Fixtures;
class VariadicConstructorArgsDummy
{
private $foo;
public function __construct(...$foo)
{
$this->foo = $foo;
}
public function getFoo()
{
return $this->foo;
}
}

View File

@ -117,6 +117,28 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array(1, 2, 3), $obj->getBaz());
}
/**
* @requires PHP 5.6
*/
public function testConstructorDenormalizeWithVariadicArgument()
{
$obj = $this->normalizer->denormalize(
array('foo' => array(1, 2, 3)),
'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
$this->assertEquals(array(1, 2, 3), $obj->getFoo());
}
/**
* @requires PHP 5.6
*/
public function testConstructorDenormalizeWithMissingVariadicArgument()
{
$obj = $this->normalizer->denormalize(
array(),
'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
$this->assertEquals(array(), $obj->getFoo());
}
public function testConstructorWithObjectDenormalize()
{
$data = new \stdClass();