From d10ffa496c4d7f9b6dbca07277d461824bb6faaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 20 Apr 2015 09:28:27 +0200 Subject: [PATCH 1/2] [Serializer] Fix a bug when using groups together with a name converter --- .../Normalizer/GetSetMethodNormalizer.php | 9 ++-- .../Normalizer/ObjectNormalizer.php | 8 +-- .../Serializer/Tests/Fixtures/GroupDummy.php | 5 +- .../Tests/Fixtures/GroupDummyInterface.php | 2 +- .../Mapping/TestClassMetadataFactory.php | 3 ++ .../Normalizer/GetSetMethodNormalizerTest.php | 53 +++++++++++++++++++ .../Tests/Normalizer/ObjectNormalizerTest.php | 53 +++++++++++++++++++ .../Normalizer/PropertyNormalizerTest.php | 53 +++++++++++++++++++ 8 files changed, 175 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 6ccfb984b55b2..b246ab091867b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -58,7 +58,6 @@ public function normalize($object, $format = null, array $context = array()) 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 @@ public function denormalize($data, $class, $format = null, array $context = arra $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)) { diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index 92628cb5318e6..86af5c677f446 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -141,14 +141,14 @@ public function denormalize($data, $class, $format = null, array $context = arra $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) { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummy.php index 0a623d8912399..37bfa7eb3f075 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummy.php @@ -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 @@ public function setFooBar($fooBar) } /** - * @Groups({"a", "b"}) + * @Groups({"a", "b", "name_converter"}) */ public function isFooBar() { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyInterface.php b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyInterface.php index 6ff54b0450fd7..a60629e6dd509 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyInterface.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyInterface.php @@ -19,7 +19,7 @@ interface GroupDummyInterface { /** - * @Groups({"a"}) + * @Groups({"a", "name_converter"}) */ public function getSymfony(); } diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/TestClassMetadataFactory.php b/src/Symfony/Component/Serializer/Tests/Mapping/TestClassMetadataFactory.php index 07b38c024b943..f435d36f744d2 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/TestClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/TestClassMetadataFactory.php @@ -30,11 +30,13 @@ public static function createClassMetadata($withParent = false, $withInterface = $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 @@ public static function createClassMetadata($withParent = false, $withInterface = if ($withInterface) { $symfony->addGroup('a'); + $symfony->addGroup('name_converter'); } // load reflection class so that the comparison passes diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index 9da90047b875d..65adfe4c2a7c6 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -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 @@ public function testLegacyDenormalizeOnCamelCaseFormat() $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 @@ public function testGroupsDenormalize() $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 */ diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 3efa05dfc592a..d08526a351703 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -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 @@ public function testLegacyDenormalizeOnCamelCaseFormat() $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 @@ public function testGroupsDenormalize() $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 */ diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php index 3ce91f3eee83c..655241073f376 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php @@ -14,6 +14,7 @@ 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 @@ public function testLegacyCamelizedAttributesDenormalize() ), __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 @@ public function testGroupsDenormalize() $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( From cf27a1d9f715ff1b80678fa9e1b194da85488692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 20 Apr 2015 13:22:03 +0200 Subject: [PATCH 2/2] [Serializer] Fix CS of ObjectNormalizerTest --- .../Serializer/Tests/Normalizer/ObjectNormalizerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index d08526a351703..433c985266845 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -476,7 +476,7 @@ public function setCamelCase($camelCase) 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) @@ -515,7 +515,7 @@ public function isBaz() public function otherMethod() { - throw new \RuntimeException("Dummy::otherMethod() should not be called"); + throw new \RuntimeException('Dummy::otherMethod() should not be called'); } } @@ -548,6 +548,6 @@ public function getBaz() public function otherMethod() { - throw new \RuntimeException("Dummy::otherMethod() should not be called"); + throw new \RuntimeException('Dummy::otherMethod() should not be called'); } }