From ba0c3b7b4b6f8d65c7de3137059473fde105674d Mon Sep 17 00:00:00 2001 From: Noemi Salaun Date: Sat, 13 Nov 2021 11:06:38 +0100 Subject: [PATCH 1/2] [Serializer] Allow default group in serialization context Fix #32622 --- .../Extractor/SerializerExtractor.php | 10 +++++++++- .../Tests/Extractor/SerializerExtractorTest.php | 11 +++++++++++ .../Tests/Fixtures/DefaultGroupDummy.php | 17 +++++++++++++++++ src/Symfony/Component/Serializer/CHANGELOG.md | 1 + .../Normalizer/AbstractNormalizer.php | 9 ++++++++- .../Tests/Normalizer/AbstractNormalizerTest.php | 6 ++++++ 6 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/DefaultGroupDummy.php diff --git a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php index 08ff10d04ac8f..7e22f4cb6c1f4 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php @@ -12,6 +12,7 @@ namespace Symfony\Component\PropertyInfo\Extractor; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; +use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; /** @@ -48,11 +49,18 @@ public function getProperties(string $class, array $context = []): ?array foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { $ignored = method_exists($serializerAttributeMetadata, 'isIgnored') && $serializerAttributeMetadata->isIgnored(); - if (!$ignored && (null === $context['serializer_groups'] || array_intersect($context['serializer_groups'], $serializerAttributeMetadata->getGroups()))) { + if (!$ignored && (null === $context['serializer_groups'] || array_intersect($context['serializer_groups'], $this->getAttributeGroups($serializerAttributeMetadata)))) { $properties[] = $serializerAttributeMetadata->getName(); } } return $properties; } + + private function getAttributeGroups(AttributeMetadataInterface $serializerAttributeMetadata): array + { + $groups = empty($serializerAttributeMetadata->getGroups()) ? ['_default'] : $serializerAttributeMetadata->getGroups(); + + return array_merge($groups, ['*']); + } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php index 66d8c06b3e6ff..37c48a807b606 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor; use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultGroupDummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\IgnorePropertyDummy; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; @@ -52,4 +53,14 @@ public function testGetPropertiesWithAnyGroup() { $this->assertSame(['analyses', 'feet'], $this->extractor->getProperties(AdderRemoverDummy::class, ['serializer_groups' => null])); } + + public function testGetPropertiesWithAllGroup() + { + $this->assertSame(['somethingWithoutGroup', 'somethingWithGroup'], $this->extractor->getProperties(DefaultGroupDummy::class, ['serializer_groups' => ['*']])); + } + + public function testGetPropertiesWithDefaultGroup() + { + $this->assertSame(['somethingWithoutGroup'], $this->extractor->getProperties(DefaultGroupDummy::class, ['serializer_groups' => ['_default']])); + } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DefaultGroupDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DefaultGroupDummy.php new file mode 100644 index 0000000000000..f1168672fd698 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DefaultGroupDummy.php @@ -0,0 +1,17 @@ +getGroups(), ['*']), $groups)) && + ([] === $groups || array_intersect($this->getAttributeGroups($attributeMetadata), $groups)) && $this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context) ) { $allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata; @@ -257,6 +257,13 @@ protected function getGroups(array $context): array return is_scalar($groups) ? (array) $groups : $groups; } + protected function getAttributeGroups(AttributeMetadataInterface $attributeMetadata): array + { + $groups = empty($attributeMetadata->getGroups()) ? ['_default'] : $attributeMetadata->getGroups(); + + return array_merge($groups, ['*']); + } + /** * Is this attribute allowed? * diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php index ee305403837c2..8a28d0a2f80c8 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php @@ -87,6 +87,9 @@ public function testGetAllowedAttributesAsString() $result = $this->normalizer->getAllowedAttributes('c', [AbstractNormalizer::GROUPS => ['*']], true); $this->assertEquals(['a1', 'a2', 'a3', 'a4'], $result); + + $result = $this->normalizer->getAllowedAttributes('c', [AbstractNormalizer::GROUPS => ['_default']], true); + $this->assertEquals(['a1'], $result); } public function testGetAllowedAttributesAsObjects() @@ -122,6 +125,9 @@ public function testGetAllowedAttributesAsObjects() $result = $this->normalizer->getAllowedAttributes('c', [AbstractNormalizer::GROUPS => ['*']], false); $this->assertEquals([$a1, $a2, $a3, $a4], $result); + + $result = $this->normalizer->getAllowedAttributes('c', [AbstractNormalizer::GROUPS => ['_default']], false); + $this->assertEquals([$a1], $result); } public function testObjectWithStaticConstructor() From 4efbc42678fc6a3e4356b691be9086c8078c9f00 Mon Sep 17 00:00:00 2001 From: Noemi Salaun Date: Mon, 23 May 2022 10:04:49 +0200 Subject: [PATCH 2/2] Extract _default in a public constant as suggested by chadyred https://github.com/symfony/symfony/pull/44035#pullrequestreview-978318221 --- .../PropertyInfo/Extractor/SerializerExtractor.php | 3 ++- .../Serializer/Normalizer/AbstractNormalizer.php | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php index 7e22f4cb6c1f4..672a73df887c7 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php @@ -14,6 +14,7 @@ use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; /** * Lists available properties using Symfony Serializer Component metadata. @@ -59,7 +60,7 @@ public function getProperties(string $class, array $context = []): ?array private function getAttributeGroups(AttributeMetadataInterface $serializerAttributeMetadata): array { - $groups = empty($serializerAttributeMetadata->getGroups()) ? ['_default'] : $serializerAttributeMetadata->getGroups(); + $groups = empty($serializerAttributeMetadata->getGroups()) ? [AbstractNormalizer::DEFAULT_GROUP_FOR_ATTRIBUTE_WITHOUT_GROUPS] : $serializerAttributeMetadata->getGroups(); return array_merge($groups, ['*']); } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 16b2c5680854f..6ccbfa5751b32 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -112,6 +112,12 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn */ public const IGNORED_ATTRIBUTES = 'ignored_attributes'; + /** + * The default group can be use on the serialization context to explicitly + * tell the serializer to allow properties without defined groups. + */ + public const DEFAULT_GROUP_FOR_ATTRIBUTE_WITHOUT_GROUPS = '_default'; + /** * @internal */ @@ -259,7 +265,7 @@ protected function getGroups(array $context): array protected function getAttributeGroups(AttributeMetadataInterface $attributeMetadata): array { - $groups = empty($attributeMetadata->getGroups()) ? ['_default'] : $attributeMetadata->getGroups(); + $groups = empty($attributeMetadata->getGroups()) ? [self::DEFAULT_GROUP_FOR_ATTRIBUTE_WITHOUT_GROUPS] : $attributeMetadata->getGroups(); return array_merge($groups, ['*']); }