From 8ca4a3f34503c1056fd6b28d0554320563ceb32f Mon Sep 17 00:00:00 2001 From: Anto Date: Thu, 17 Oct 2019 20:41:04 +0200 Subject: [PATCH] [Serializer] Fix property name usage for denormalization --- .../MetadataAwareNameConverter.php | 37 +++++++++------ .../Normalizer/AbstractObjectNormalizer.php | 1 - .../Fixtures/OtherSerializedNameDummy.php | 45 +++++++++++++++++++ .../MetadataAwareNameConverterTest.php | 23 ++++++++++ .../Tests/Normalizer/ObjectNormalizerTest.php | 18 ++++++++ 5 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php diff --git a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php index e863e013e7..9cd20bdefe 100644 --- a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php +++ b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Serializer\NameConverter; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; /** * @author Fabien Bourigault @@ -25,11 +26,11 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface */ private $fallbackNameConverter; - private static $normalizeCache = []; + private $normalizeCache = []; - private static $denormalizeCache = []; + private $denormalizeCache = []; - private static $attributesMetadataCache = []; + private $attributesMetadataCache = []; public function __construct(ClassMetadataFactoryInterface $metadataFactory, NameConverterInterface $fallbackNameConverter = null) { @@ -46,11 +47,11 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface return $this->normalizeFallback($propertyName, $class, $format, $context); } - if (!isset(self::$normalizeCache[$class][$propertyName])) { - self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class); + if (!isset($this->normalizeCache[$class][$propertyName])) { + $this->normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class); } - return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); + return $this->normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); } /** @@ -62,11 +63,11 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface return $this->denormalizeFallback($propertyName, $class, $format, $context); } - if (!isset(self::$denormalizeCache[$class][$propertyName])) { - self::$denormalizeCache[$class][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class); + if (!isset($this->denormalizeCache[$class][$propertyName])) { + $this->denormalizeCache[$class][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context); } - return self::$denormalizeCache[$class][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context); + return $this->denormalizeCache[$class][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context); } private function getCacheValueForNormalization($propertyName, string $class) @@ -88,13 +89,13 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface return $this->fallbackNameConverter ? $this->fallbackNameConverter->normalize($propertyName, $class, $format, $context) : $propertyName; } - private function getCacheValueForDenormalization($propertyName, string $class) + private function getCacheValueForDenormalization($propertyName, string $class, $context) { - if (!isset(self::$attributesMetadataCache[$class])) { - self::$attributesMetadataCache[$class] = $this->getCacheValueForAttributesMetadata($class); + if (!isset($this->attributesMetadataCache[$class])) { + $this->attributesMetadataCache[$class] = $this->getCacheValueForAttributesMetadata($class, $context); } - return self::$attributesMetadataCache[$class][$propertyName] ?? null; + return $this->attributesMetadataCache[$class][$propertyName] ?? null; } private function denormalizeFallback($propertyName, string $class = null, string $format = null, array $context = []) @@ -102,7 +103,7 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface return $this->fallbackNameConverter ? $this->fallbackNameConverter->denormalize($propertyName, $class, $format, $context) : $propertyName; } - private function getCacheValueForAttributesMetadata(string $class): array + private function getCacheValueForAttributesMetadata(string $class, $context): array { if (!$this->metadataFactory->hasMetadataFor($class)) { return []; @@ -116,6 +117,14 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface continue; } + $groups = $metadata->getGroups(); + if (!$groups && ($context[AbstractNormalizer::GROUPS] ?? [])) { + continue; + } + if ($groups && !array_intersect($groups, $context[AbstractNormalizer::GROUPS] ?? [])) { + continue; + } + $cache[$metadata->getSerializedName()] = $name; } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index da45e30a7f..9b9b9fb4fa 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -236,7 +236,6 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * * @param object $object * @param string|null $format - * @param array $context * * @return string[] */ diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php new file mode 100644 index 0000000000..1ac543ca69 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php @@ -0,0 +1,45 @@ + + * + * 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; + +use Symfony\Component\Serializer\Annotation\Groups; +use Symfony\Component\Serializer\Annotation\SerializedName; + +/** + * @author Anthony GRASSIOT + */ +class OtherSerializedNameDummy +{ + /** + * @Groups({"a"}) + */ + private $buz; + + public function setBuz($buz) + { + $this->buz = $buz; + } + + public function getBuz() + { + return $this->buz; + } + + /** + * @Groups({"b"}) + * @SerializedName("buz") + */ + public function getBuzForExport() + { + return $this->buz.' Rocks'; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php b/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php index 7e2552ea8a..c1c906e6ce 100644 --- a/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php +++ b/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php @@ -18,6 +18,7 @@ use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; +use Symfony\Component\Serializer\Tests\Fixtures\OtherSerializedNameDummy; use Symfony\Component\Serializer\Tests\Fixtures\SerializedNameDummy; /** @@ -115,4 +116,26 @@ final class MetadataAwareNameConverterTest extends TestCase [0, 0], ]; } + + /** + * @dataProvider attributeAndContextProvider + */ + public function testDenormalizeWithGroups($expected, $propertyName, $context = []) + { + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); + + $nameConverter = new MetadataAwareNameConverter($classMetadataFactory); + + $this->assertEquals($expected, $nameConverter->denormalize($propertyName, OtherSerializedNameDummy::class, null, $context)); + } + + public function attributeAndContextProvider() + { + return [ + ['buz', 'buz', ['groups' => ['a']]], + ['buzForExport', 'buz', ['groups' => ['b']]], + ['buz', 'buz', ['groups' => ['c']]], + ['buz', 'buz', []], + ]; + } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 0b4c5f5e6d..aacce2dee9 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -32,6 +32,7 @@ use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy; use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy; use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy; +use Symfony\Component\Serializer\Tests\Fixtures\OtherSerializedNameDummy; use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder; use Symfony\Component\Serializer\Tests\Normalizer\Features\AttributesTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\CallbacksObject; @@ -481,6 +482,23 @@ class ObjectNormalizerTest extends TestCase ); } + public function testGroupsDenormalizeWithMetaDataNameConverter() + { + $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); + $this->normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory)); + $this->normalizer->setSerializer($this->serializer); + + $obj = new OtherSerializedNameDummy(); + $obj->setBuz('Aldrin'); + + $this->assertEquals( + $obj, + $this->normalizer->denormalize([ + 'buz' => 'Aldrin', + ], 'Symfony\Component\Serializer\Tests\Fixtures\OtherSerializedNameDummy', null, [ObjectNormalizer::GROUPS => ['a']]) + ); + } + // ignored attributes protected function getNormalizerForIgnoredAttributes(): ObjectNormalizer