diff --git a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php index 620032f5b161b..1d935dc88a2e7 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php @@ -13,6 +13,7 @@ use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; +use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; /** * Lists available properties using Symfony Serializer Component metadata. @@ -38,15 +39,34 @@ public function getProperties(string $class, array $context = []): ?array return null; } + $enableDefaultGroups = $context[AbstractNormalizer::ENABLE_DEFAULT_GROUPS] ?? false; + $groups = $context['serializer_groups'] ?? []; - $groupsHasBeenDefined = [] !== $groups; - $groups = array_merge($groups, ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]); + $defaultGroups = ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]; + + $groupsHasBeenDefined = $enableDefaultGroups + ? [] !== $groups + : null !== ($context['serializer_groups'] ?? null); + + $customGroupsHasBeenDefined = (bool) array_diff($groups, $defaultGroups); + + if ($enableDefaultGroups && !$customGroupsHasBeenDefined) { + $groups = array_merge($groups, $defaultGroups); + } $properties = []; $serializerClassMetadata = $this->classMetadataFactory->getMetadataFor($class); foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { - if (!$serializerAttributeMetadata->isIgnored() && (!$groupsHasBeenDefined || array_intersect(array_merge($serializerAttributeMetadata->getGroups(), ['*']), $groups))) { + if ($serializerAttributeMetadata->isIgnored()) { + continue; + } + + if (!($attributeGroups = $serializerAttributeMetadata->getGroups()) && $enableDefaultGroups && !$customGroupsHasBeenDefined) { + $attributeGroups = $defaultGroups; + } + + if (!$groupsHasBeenDefined || array_intersect(array_merge($attributeGroups, ['*']), $groups)) { $properties[] = $serializerAttributeMetadata->getName(); } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php index 48d3ec957d167..79bb2af82f424 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php @@ -15,6 +15,7 @@ use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor; use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\GroupPropertyDummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\IgnorePropertyDummy; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AttributeLoader; @@ -43,12 +44,91 @@ public function testGetProperties() public function testGetPropertiesWithIgnoredProperties() { $this->assertSame(['visibleProperty'], $this->extractor->getProperties(IgnorePropertyDummy::class, ['serializer_groups' => ['a']])); - $this->assertSame(['visibleProperty'], $this->extractor->getProperties(IgnorePropertyDummy::class, ['serializer_groups' => ['Default']])); - $this->assertSame(['visibleProperty'], $this->extractor->getProperties(IgnorePropertyDummy::class, ['serializer_groups' => ['IgnorePropertyDummy']])); } public function testGetPropertiesWithAnyGroup() { $this->assertSame(['analyses', 'feet'], $this->extractor->getProperties(AdderRemoverDummy::class, ['serializer_groups' => null])); } + + public function testGetPropertiesWithDefaultGroups() + { + $this->assertSame( + ['noGroup', 'customGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => null]), + ); + + $this->assertSame( + [], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => []]), + ); + + $this->assertSame( + ['noGroup', 'customGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => ['*']]), + ); + + $this->assertSame( + ['customGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => ['custom']]), + ); + + $this->assertSame( + ['defaultGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => ['Default']]), + ); + + $this->assertSame( + ['classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, ['serializer_groups' => ['GroupPropertyDummy']]), + ); + + $this->assertSame( + ['noGroup', 'customGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => null, + ]), + ); + + $this->assertSame( + ['noGroup', 'customGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => [], + ]), + ); + + $this->assertSame( + ['noGroup', 'customGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => ['*'], + ]), + ); + + $this->assertSame( + ['customGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => ['custom'], + ]), + ); + + $this->assertSame( + ['noGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => ['Default'], + ]), + ); + + $this->assertSame( + ['noGroup', 'defaultGroup', 'classGroup'], + $this->extractor->getProperties(GroupPropertyDummy::class, [ + 'enable_default_groups' => true, + 'serializer_groups' => ['GroupPropertyDummy'], + ]), + ); + } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/GroupPropertyDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/GroupPropertyDummy.php new file mode 100644 index 0000000000000..aef6c6cf035e1 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/GroupPropertyDummy.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +use Symfony\Component\Serializer\Attribute\Groups; + +class GroupPropertyDummy +{ + public bool $noGroup = true; + + #[Groups('custom')] + public bool $customGroup = true; + + #[Groups('Default')] + public bool $defaultGroup = true; + + #[Groups('GroupPropertyDummy')] + public bool $classGroup = true; +} diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/IgnorePropertyDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/IgnorePropertyDummy.php index 0cc4606241f20..9216ff801b27d 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/IgnorePropertyDummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/IgnorePropertyDummy.php @@ -19,7 +19,7 @@ */ class IgnorePropertyDummy { - #[Groups(['a', 'Default', 'IgnorePropertyDummy'])] + #[Groups(['a'])] public $visibleProperty; #[Groups(['a']), Ignore] diff --git a/src/Symfony/Component/Serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php b/src/Symfony/Component/Serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php index a27f00c5ba80c..ae0da61e6f01d 100644 --- a/src/Symfony/Component/Serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php +++ b/src/Symfony/Component/Serializer/Context/Normalizer/AbstractObjectNormalizerContextBuilder.php @@ -128,4 +128,13 @@ public function withPreserveEmptyObjects(?bool $preserveEmptyObjects): static { return $this->with(AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS, $preserveEmptyObjects); } + + /** + * Configures whether 'Default' and 'ClassNames' groups are added when no + * custom group is specified. + */ + public function withEnableDefaultGroups(?bool $enableDefaultGroups): static + { + return $this->with(AbstractObjectNormalizer::ENABLE_DEFAULT_GROUPS, $enableDefaultGroups); + } } diff --git a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php index 327d92dc1b1c3..611d10f9fbd77 100644 --- a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php +++ b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php @@ -47,11 +47,13 @@ public function normalize(string $propertyName, ?string $class = null, ?string $ return $this->normalizeFallback($propertyName, $class, $format, $context); } - if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) { - self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class); + $cacheKey = $this->getCacheKey($class, $context); + + if (!\array_key_exists($cacheKey, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$cacheKey])) { + self::$normalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class, $context); } - return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); + return self::$normalizeCache[$cacheKey][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); } public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string @@ -61,6 +63,7 @@ public function denormalize(string $propertyName, ?string $class = null, ?string } $cacheKey = $this->getCacheKey($class, $context); + if (!\array_key_exists($cacheKey, self::$denormalizeCache) || !\array_key_exists($propertyName, self::$denormalizeCache[$cacheKey])) { self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context); } @@ -68,22 +71,15 @@ public function denormalize(string $propertyName, ?string $class = null, ?string return self::$denormalizeCache[$cacheKey][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context); } - private function getCacheValueForNormalization(string $propertyName, string $class): ?string + private function getCacheValueForNormalization(string $propertyName, string $class, array $context): ?string { - if (!$this->metadataFactory->hasMetadataFor($class)) { - return null; - } - - $attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata(); - if (!\array_key_exists($propertyName, $attributesMetadata)) { - return null; - } + $cacheKey = $this->getCacheKey($class, $context); - if (null !== $attributesMetadata[$propertyName]->getSerializedName() && null !== $attributesMetadata[$propertyName]->getSerializedPath()) { - throw new LogicException(sprintf('Found SerializedName and SerializedPath attributes on property "%s" of class "%s".', $propertyName, $class)); + if (!\array_key_exists($cacheKey, self::$attributesMetadataCache)) { + self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context); } - return $attributesMetadata[$propertyName]->getSerializedName() ?? null; + return array_flip(self::$attributesMetadataCache[$cacheKey])[$propertyName] ?? null; } private function normalizeFallback(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string @@ -117,6 +113,18 @@ private function getCacheValueForAttributesMetadata(string $class, array $contex $classMetadata = $this->metadataFactory->getMetadataFor($class); + $enableDefaultGroups = $context[AbstractNormalizer::ENABLE_DEFAULT_GROUPS] ?? false; + + $groups = (array) ($context[AbstractNormalizer::GROUPS] ?? []); + $defaultGroups = ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]; + + $groupsHasBeenDefined = [] !== $groups; + $customGroupsHasBeenDefined = (bool) array_diff($groups, $defaultGroups); + + if ($enableDefaultGroups && !$customGroupsHasBeenDefined) { + $groups = array_merge($groups, $defaultGroups); + } + $cache = []; foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) { if (null === $metadata->getSerializedName()) { @@ -129,15 +137,11 @@ private function getCacheValueForAttributesMetadata(string $class, array $contex $metadataGroups = $metadata->getGroups(); - $contextGroups = (array) ($context[AbstractNormalizer::GROUPS] ?? []); - $contextGroupsHasBeenDefined = [] !== $contextGroups; - $contextGroups = array_merge($contextGroups, ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]); - - if ($contextGroupsHasBeenDefined && !$metadataGroups) { + if ($metadataGroups && !array_intersect(array_merge($metadataGroups, ['*']), $groups)) { continue; } - if ($metadataGroups && !array_intersect(array_merge($metadataGroups, ['*']), $contextGroups)) { + if (!$metadataGroups && $groupsHasBeenDefined && !\in_array('*', $groups)) { continue; } @@ -153,6 +157,6 @@ private function getCacheKey(string $class, array $context): string return $class.'-'.$context['cache_key']; } - return $class.hash('xxh128', serialize($context[AbstractNormalizer::GROUPS] ?? [])); + return $class.hash('xxh128', serialize($context[AbstractNormalizer::GROUPS] ?? []).serialize($context[AbstractNormalizer::ENABLE_DEFAULT_GROUPS] ?? false)); } } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 6f065984ca6e5..485a1138b2456 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -128,6 +128,11 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn */ public const FILTER_BOOL = 'filter_bool'; + /** + * Add 'Default' and 'ClassNames' groups when no custom group is specified. + */ + public const ENABLE_DEFAULT_GROUPS = 'enable_default_groups'; + /** * @internal */ @@ -226,9 +231,17 @@ protected function getAllowedAttributes(string|object $classOrObject, array $con $classMetadata = $this->classMetadataFactory->getMetadataFor($classOrObject); $class = $classMetadata->getName(); + $enableDefaultGroups = $context[self::ENABLE_DEFAULT_GROUPS] ?? $this->defaultContext[self::ENABLE_DEFAULT_GROUPS] ?? false; + $groups = $this->getGroups($context); + $defaultGroups = ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]; + $groupsHasBeenDefined = [] !== $groups; - $groups = array_merge($groups, ['Default', (false !== $nsSep = strrpos($class, '\\')) ? substr($class, $nsSep + 1) : $class]); + $customGroupsHasBeenDefined = (bool) array_diff($groups, $defaultGroups); + + if ($enableDefaultGroups && !$customGroupsHasBeenDefined) { + $groups = array_merge($groups, $defaultGroups); + } $allowedAttributes = []; $ignoreUsed = false; @@ -238,12 +251,16 @@ protected function getAllowedAttributes(string|object $classOrObject, array $con $ignoreUsed = true; } - // If you update this check, update accordingly the one in Symfony\Component\PropertyInfo\Extractor\SerializerExtractor::getProperties() - if ( - !$ignore - && (!$groupsHasBeenDefined || array_intersect(array_merge($attributeMetadata->getGroups(), ['*']), $groups)) - && $this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context) - ) { + // If you update these checks, update accordingly the one in Symfony\Component\PropertyInfo\Extractor\SerializerExtractor::getProperties() + if ($ignore || !$this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context)) { + continue; + } + + if (!($attributeGroups = $attributeMetadata->getGroups()) && $enableDefaultGroups && !$customGroupsHasBeenDefined) { + $attributeGroups = $defaultGroups; + } + + if (!$groupsHasBeenDefined || array_intersect(array_merge($attributeGroups, ['*']), $groups)) { $allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata; } } diff --git a/src/Symfony/Component/Serializer/Tests/Context/Normalizer/AbstractObjectNormalizerContextBuilderTest.php b/src/Symfony/Component/Serializer/Tests/Context/Normalizer/AbstractObjectNormalizerContextBuilderTest.php index 410f2972b0258..91cc76f7d0b87 100644 --- a/src/Symfony/Component/Serializer/Tests/Context/Normalizer/AbstractObjectNormalizerContextBuilderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Context/Normalizer/AbstractObjectNormalizerContextBuilderTest.php @@ -45,6 +45,7 @@ public function testWithers(array $values) ->withExcludeFromCacheKeys($values[AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY]) ->withDeepObjectToPopulate($values[AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE]) ->withPreserveEmptyObjects($values[AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS]) + ->withEnableDefaultGroups($values[AbstractObjectNormalizer::ENABLE_DEFAULT_GROUPS]) ->toArray(); $this->assertSame($values, $context); @@ -65,6 +66,7 @@ public static function withersDataProvider(): iterable AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY => ['key'], AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true, AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => false, + AbstractObjectNormalizer::ENABLE_DEFAULT_GROUPS => false, ]]; yield 'With null values' => [[ @@ -77,6 +79,7 @@ public static function withersDataProvider(): iterable AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY => null, AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => null, AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => null, + AbstractObjectNormalizer::ENABLE_DEFAULT_GROUPS => null, ]]; } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php index 86fc6ead1fdb1..dd6b51428f45e 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/OtherSerializedNameDummy.php @@ -19,6 +19,18 @@ */ class OtherSerializedNameDummy { + #[Groups(['Default']), SerializedName('renamedDefaultGroup')] + private $defaultGroup; + + #[Groups(['OtherSerializedNameDummy']), SerializedName('renamedClassGroup')] + public $classGroup; + + #[SerializedName('renamedNoGroup')] + public $noGroup; + + #[Groups(['custom']), SerializedName('renamedCustomGroup')] + public $customGroup; + #[Groups(['a'])] private $buz; diff --git a/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php b/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php index c6ccd2601c98e..0f2818d8e98b4 100644 --- a/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php +++ b/src/Symfony/Component/Serializer/Tests/NameConverter/MetadataAwareNameConverterTest.php @@ -116,6 +116,7 @@ public static function fallbackAttributeProvider(): array } /** + * @group wip * @dataProvider attributeAndContextProvider */ public function testNormalizeWithGroups(string $propertyName, string $expected, array $context = []) @@ -128,6 +129,7 @@ public function testNormalizeWithGroups(string $propertyName, string $expected, } /** + * @group wip * @dataProvider attributeAndContextProvider */ public function testDenormalizeWithGroups(string $expected, string $propertyName, array $context = []) @@ -142,13 +144,62 @@ public function testDenormalizeWithGroups(string $expected, string $propertyName public static function attributeAndContextProvider(): array { return [ - ['buz', 'buz', ['groups' => ['a']]], ['buzForExport', 'buz', ['groups' => ['b']]], ['buz', 'buz', ['groups' => 'a']], ['buzForExport', 'buz', ['groups' => 'b']], ['buz', 'buz', ['groups' => ['c']]], ['buz', 'buz', []], ['buzForExport', 'buz', ['groups' => ['*']]], + + ['defaultGroup', 'defaultGroup', ['groups' => []]], + ['classGroup', 'classGroup', ['groups' => []]], + ['noGroup', 'renamedNoGroup', ['groups' => []]], + ['customGroup', 'customGroup', ['groups' => []]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => ['*']]], + ['classGroup', 'renamedClassGroup', ['groups' => ['*']]], + ['noGroup', 'renamedNoGroup', ['groups' => ['*']]], + ['customGroup', 'renamedCustomGroup', ['groups' => ['*']]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => ['Default']]], + ['classGroup', 'classGroup', ['groups' => ['Default']]], + ['noGroup', 'noGroup', ['groups' => ['Default']]], + ['customGroup', 'customGroup', ['groups' => ['Default']]], + + ['defaultGroup', 'defaultGroup', ['groups' => ['OtherSerializedNameDummy']]], + ['classGroup', 'renamedClassGroup', ['groups' => ['OtherSerializedNameDummy']]], + ['noGroup', 'noGroup', ['groups' => ['OtherSerializedNameDummy']]], + ['customGroup', 'customGroup', ['groups' => ['OtherSerializedNameDummy']]], + + ['defaultGroup', 'defaultGroup', ['groups' => ['custom']]], + ['classGroup', 'classGroup', ['groups' => ['custom']]], + ['noGroup', 'noGroup', ['groups' => ['custom']]], + ['customGroup', 'renamedCustomGroup', ['groups' => ['custom']]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => [], 'enable_default_groups' => true]], + ['classGroup', 'renamedClassGroup', ['groups' => [], 'enable_default_groups' => true]], + ['noGroup', 'renamedNoGroup', ['groups' => [], 'enable_default_groups' => true]], + ['customGroup', 'customGroup', ['groups' => [], 'enable_default_groups' => true]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => ['*'], 'enable_default_groups' => true]], + ['classGroup', 'renamedClassGroup', ['groups' => ['*'], 'enable_default_groups' => true]], + ['noGroup', 'renamedNoGroup', ['groups' => ['*'], 'enable_default_groups' => true]], + ['customGroup', 'renamedCustomGroup', ['groups' => ['*'], 'enable_default_groups' => true]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => ['Default'], 'enable_default_groups' => true]], + ['classGroup', 'renamedClassGroup', ['groups' => ['Default'], 'enable_default_groups' => true]], + ['noGroup', 'noGroup', ['groups' => ['Default'], 'enable_default_groups' => true]], + ['customGroup', 'customGroup', ['groups' => ['Default'], 'enable_default_groups' => true]], + + ['defaultGroup', 'renamedDefaultGroup', ['groups' => ['OtherSerializedNameDummy'], 'enable_default_groups' => true]], + ['classGroup', 'renamedClassGroup', ['groups' => ['OtherSerializedNameDummy'], 'enable_default_groups' => true]], + ['noGroup', 'noGroup', ['groups' => ['OtherSerializedNameDummy'], 'enable_default_groups' => true]], + ['customGroup', 'customGroup', ['groups' => ['OtherSerializedNameDummy'], 'enable_default_groups' => true]], + + ['defaultGroup', 'defaultGroup', ['groups' => ['custom'], 'enable_default_groups' => true]], + ['classGroup', 'classGroup', ['groups' => ['custom'], 'enable_default_groups' => true]], + ['noGroup', 'noGroup', ['groups' => ['custom'], 'enable_default_groups' => true]], + ['customGroup', 'renamedCustomGroup', ['groups' => ['custom'], 'enable_default_groups' => true]], ]; } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/GroupsTestTrait.php b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/GroupsTestTrait.php index ba4d7632385c2..5ccabf9d164c9 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/GroupsTestTrait.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/GroupsTestTrait.php @@ -41,8 +41,6 @@ public function testGroupsNormalize() $this->assertEquals([ 'bar' => 'bar', - 'default' => 'default', - 'className' => 'className', ], $normalizer->normalize($obj, null, ['groups' => ['c']])); $this->assertEquals([ @@ -52,14 +50,9 @@ public function testGroupsNormalize() 'bar' => 'bar', 'kevin' => 'kevin', 'coopTilleuls' => 'coopTilleuls', - 'default' => 'default', - 'className' => 'className', ], $normalizer->normalize($obj, null, ['groups' => ['a', 'c']])); - $this->assertEquals([ - 'default' => 'default', - 'className' => 'className', - ], $normalizer->normalize($obj, null, ['groups' => ['unknown']])); + $this->assertEquals([], $normalizer->normalize($obj, null, ['groups' => ['unknown']])); $this->assertEquals([ 'quux' => 'quux', @@ -79,15 +72,11 @@ public function testGroupsDenormalize() $normalizer = $this->getDenormalizerForGroups(); $obj = new GroupDummy(); - $obj->setDefault('default'); - $obj->setClassName('className'); $data = [ 'foo' => 'foo', 'bar' => 'bar', 'quux' => 'quux', - 'default' => 'default', - 'className' => 'className', ]; $denormalized = $normalizer->denormalize( @@ -124,18 +113,87 @@ public function testGroupsDenormalize() $this->assertEquals($obj, $denormalized); } - public function testNormalizeNoPropertyInGroup() + public function testNormalizeWithDefaultGroups() { $normalizer = $this->getNormalizerForGroups(); - $obj = new GroupDummy(); - $obj->setFoo('foo'); - $obj->setDefault('default'); - $obj->setClassName('className'); + $assertNormalizedProperties = function (array $expectedProperties, array $normalized): void { + $actualProperties = array_keys($normalized); - $this->assertEquals([ - 'default' => 'default', - 'className' => 'className', - ], $normalizer->normalize($obj, null, ['groups' => ['notExist']])); + sort($expectedProperties); + sort($actualProperties); + + $this->assertSame($expectedProperties, $actualProperties); + }; + + $assertNormalizedProperties( + ['foo', 'fooBar', 'symfony', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: ['groups' => ['a']]), + ); + + $assertNormalizedProperties( + ['bar', 'foo', 'fooBar', 'symfony', 'quux', 'default', 'className', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy()), + ); + + $assertNormalizedProperties( + ['bar', 'foo', 'fooBar', 'symfony', 'quux', 'default', 'className', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: ['groups' => []]), + ); + + $assertNormalizedProperties( + ['foo', 'bar', 'quux', 'fooBar', 'symfony', 'default', 'className', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: ['groups' => ['*']]), + ); + + $assertNormalizedProperties( + ['default'], + $normalizer->normalize(new GroupDummy(), context: ['groups' => ['Default']]), + ); + + $assertNormalizedProperties( + ['className'], + $normalizer->normalize(new GroupDummy(), context: ['groups' => ['GroupDummy']]), + ); + + $assertNormalizedProperties( + ['foo', 'fooBar', 'symfony', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: [ + 'enable_default_groups' => true, + 'groups' => ['a'], + ]), + ); + + $assertNormalizedProperties( + ['bar', 'foo', 'fooBar', 'symfony', 'quux', 'default', 'className', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: [ + 'enable_default_groups' => true, + 'groups' => [], + ]), + ); + + $assertNormalizedProperties( + ['foo', 'bar', 'quux', 'fooBar', 'symfony', 'default', 'className', 'kevin', 'coopTilleuls'], + $normalizer->normalize(new GroupDummy(), context: [ + 'enable_default_groups' => true, + 'groups' => ['*'], + ]), + ); + + $assertNormalizedProperties( + ['default', 'className'], + $normalizer->normalize(new GroupDummy(), context: [ + 'enable_default_groups' => true, + 'groups' => ['Default'], + ]), + ); + + $assertNormalizedProperties( + ['default', 'className'], + $normalizer->normalize(new GroupDummy(), context: [ + 'enable_default_groups' => true, + 'groups' => ['GroupDummy'], + ]), + ); } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index f846a0d972c8d..2c30a57bc2001 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -302,8 +302,6 @@ public function testGroupsNormalizeWithNameConverter() 'bar' => null, 'foo_bar' => '@dunglas', 'symfony' => '@coopTilleuls', - 'default' => null, - 'class_name' => null, ], $this->normalizer->normalize($obj, null, [GetSetMethodNormalizer::GROUPS => ['name_converter']]) ); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 50866a1b235c0..ed6a9d3bed24f 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -507,8 +507,6 @@ public function testGroupsNormalizeWithNameConverter() 'bar' => null, 'foo_bar' => '@dunglas', 'symfony' => '@coopTilleuls', - 'default' => null, - 'class_name' => null, ], $this->normalizer->normalize($obj, null, [ObjectNormalizer::GROUPS => ['name_converter']]) ); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php index b93a7bb9fd1cd..5e2a15659a3dc 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php @@ -321,8 +321,6 @@ public function testGroupsNormalizeWithNameConverter() 'bar' => null, 'foo_bar' => '@dunglas', 'symfony' => '@coopTilleuls', - 'default' => null, - 'class_name' => null, ], $this->normalizer->normalize($obj, null, [PropertyNormalizer::GROUPS => ['name_converter']]) );