Skip to content

Commit

Permalink
bug #15426 [Serializer] Add support for variadic arguments in the Get…
Browse files Browse the repository at this point in the history
…SetNormalizer (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
  • Loading branch information
fabpot committed Aug 9, 2015
2 parents 0f56497 + 704760b commit 620a3d4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
Expand Up @@ -136,11 +136,19 @@ public function denormalize($data, $class, $format = null, array $context = arra
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(
Expand Down
@@ -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;
}
}
Expand Up @@ -117,6 +117,28 @@ public function testConstructorDenormalizeWithMissingOptionalArgument()
$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();
Expand Down

0 comments on commit 620a3d4

Please sign in to comment.