bug #14415 [Serializer] Fix a bug when using groups together with a name converter (dunglas)

This PR was squashed before being merged into the 2.7 branch (closes #14415).

Discussion
----------

[Serializer] Fix a bug when using groups together with a name converter

| 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

* Fix the bug
* Increase test coverage

Commits
-------

454ef8c [Serializer] Fix a bug when using groups together with a name converter
This commit is contained in:
Fabien Potencier 2015-04-27 14:05:47 +02:00
commit 09cde7c52d
8 changed files with 178 additions and 14 deletions

View File

@ -58,7 +58,6 @@ class GetSetMethodNormalizer extends AbstractNormalizer
foreach ($reflectionMethods as $method) {
if ($this->isGetMethod($method)) {
$attributeName = lcfirst(substr($method->name, 0 === strpos($method->name, 'is') ? 2 : 3));
if (in_array($attributeName, $this->ignoredAttributes)) {
continue;
}
@ -104,14 +103,14 @@ class GetSetMethodNormalizer extends AbstractNormalizer
$object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes);
foreach ($normalizedData as $attribute => $value) {
if ($this->nameConverter) {
$attribute = $this->nameConverter->denormalize($attribute);
}
$allowed = $allowedAttributes === false || in_array($attribute, $allowedAttributes);
$ignored = in_array($attribute, $this->ignoredAttributes);
if ($allowed && !$ignored) {
if ($this->nameConverter) {
$attribute = $this->nameConverter->denormalize($attribute);
}
$setter = 'set'.ucfirst($attribute);
if (method_exists($object, $setter)) {

View File

@ -141,14 +141,14 @@ class ObjectNormalizer extends AbstractNormalizer
$object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes);
foreach ($normalizedData as $attribute => $value) {
if ($this->nameConverter) {
$attribute = $this->nameConverter->denormalize($attribute);
}
$allowed = $allowedAttributes === false || in_array($attribute, $allowedAttributes);
$ignored = in_array($attribute, $this->ignoredAttributes);
if ($allowed && !$ignored) {
if ($this->nameConverter) {
$attribute = $this->nameConverter->normalize($attribute);
}
try {
$this->propertyAccessor->setValue($object, $attribute, $value);
} catch (NoSuchPropertyException $exception) {

View File

@ -22,6 +22,9 @@ class GroupDummy extends GroupDummyParent implements GroupDummyInterface
* @Groups({"a"})
*/
private $foo;
/**
* @Groups({"b", "c", "name_converter"})
*/
protected $bar;
private $fooBar;
private $symfony;
@ -58,7 +61,7 @@ class GroupDummy extends GroupDummyParent implements GroupDummyInterface
}
/**
* @Groups({"a", "b"})
* @Groups({"a", "b", "name_converter"})
*/
public function isFooBar()
{

View File

@ -19,7 +19,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
interface GroupDummyInterface
{
/**
* @Groups({"a"})
* @Groups({"a", "name_converter"})
*/
public function getSymfony();
}

View File

@ -30,11 +30,13 @@ class TestClassMetadataFactory
$bar = new AttributeMetadata('bar');
$bar->addGroup('b');
$bar->addGroup('c');
$bar->addGroup('name_converter');
$expected->addAttributeMetadata($bar);
$fooBar = new AttributeMetadata('fooBar');
$fooBar->addGroup('a');
$fooBar->addGroup('b');
$fooBar->addGroup('name_converter');
$expected->addAttributeMetadata($fooBar);
$symfony = new AttributeMetadata('symfony');
@ -53,6 +55,7 @@ class TestClassMetadataFactory
if ($withInterface) {
$symfony->addGroup('a');
$symfony->addGroup('name_converter');
}
// load reflection class so that the comparison passes

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Serializer\Tests\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
@ -115,6 +116,16 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testNameConverterSupport()
{
$this->normalizer = new GetSetMethodNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
$obj = $this->normalizer->denormalize(
array('camel_case' => 'camelCase'),
__NAMESPACE__.'\GetSetDummy'
);
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testDenormalizeNull()
{
$this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
@ -262,6 +273,48 @@ class GetSetMethodNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($obj, $normalized);
}
public function testGroupsNormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$obj->setCoopTilleuls('les-tilleuls.coop');
$this->assertEquals(
array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
),
$this->normalizer->normalize($obj, null, array('groups' => array('name_converter')))
);
}
public function testGroupsDenormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$this->assertEquals(
$obj,
$this->normalizer->denormalize(array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
'coop_tilleuls' => 'les-tilleuls.coop',
), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array('groups' => array('name_converter')))
);
}
/**
* @dataProvider provideCallbacks
*/

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Serializer\Tests\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
@ -111,6 +112,16 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testNameConverterSupport()
{
$this->normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
$obj = $this->normalizer->denormalize(
array('camel_case' => 'camelCase'),
__NAMESPACE__.'\ObjectDummy'
);
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testDenormalizeNull()
{
$this->assertEquals(new ObjectDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\ObjectDummy'));
@ -206,6 +217,48 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($obj, $normalized);
}
public function testGroupsNormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$obj->setCoopTilleuls('les-tilleuls.coop');
$this->assertEquals(
array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
),
$this->normalizer->normalize($obj, null, array('groups' => array('name_converter')))
);
}
public function testGroupsDenormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$this->assertEquals(
$obj,
$this->normalizer->denormalize(array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
'coop_tilleuls' => 'les-tilleuls.coop',
), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array('groups' => array('name_converter')))
);
}
/**
* @dataProvider provideCallbacks
*/
@ -423,7 +476,7 @@ class ObjectDummy
public function otherMethod()
{
throw new \RuntimeException("Dummy::otherMethod() should not be called");
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
public function setObject($object)
@ -462,7 +515,7 @@ class ObjectConstructorDummy
public function otherMethod()
{
throw new \RuntimeException("Dummy::otherMethod() should not be called");
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
}
@ -495,6 +548,6 @@ class ObjectConstructorOptionalArgsDummy
public function otherMethod()
{
throw new \RuntimeException("Dummy::otherMethod() should not be called");
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
}

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Serializer\Tests\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
@ -129,6 +130,16 @@ class PropertyNormalizerTest extends \PHPUnit_Framework_TestCase
), __NAMESPACE__.'\PropertyCamelizedDummy'), $obj);
}
public function testNameConverterSupport()
{
$this->normalizer = new PropertyNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
$obj = $this->normalizer->denormalize(
array('camel_case' => 'camelCase'),
__NAMESPACE__.'\PropertyDummy'
);
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testConstructorDenormalize()
{
$obj = $this->normalizer->denormalize(
@ -239,6 +250,48 @@ class PropertyNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($obj, $normalized);
}
public function testGroupsNormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$obj->setCoopTilleuls('les-tilleuls.coop');
$this->assertEquals(
array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
),
$this->normalizer->normalize($obj, null, array('groups' => array('name_converter')))
);
}
public function testGroupsDenormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$this->assertEquals(
$obj,
$this->normalizer->denormalize(array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
'coop_tilleuls' => 'les-tilleuls.coop',
), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array('groups' => array('name_converter')))
);
}
public function provideCallbacks()
{
return array(