From 57fe0178c463f6a4c1c54bf99b0cbdcfd0e8bc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 23 Apr 2018 17:22:12 +0200 Subject: [PATCH] [Serializer] Allow to access extra infos in name converters --- src/Symfony/Component/Serializer/CHANGELOG.md | 1 + .../AdvancedNameConverterInterface.php | 30 +++++++++++++++++++ .../Normalizer/AbstractNormalizer.php | 2 +- .../Normalizer/AbstractObjectNormalizer.php | 10 +++---- .../Tests/Normalizer/ObjectNormalizerTest.php | 19 ++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Component/Serializer/NameConverter/AdvancedNameConverterInterface.php diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index b6bea64685..f5969a2d7d 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * added support for XML comment encoding (encoding `['#comment' => ' foo ']` results ``) * added optional `int[] $encoderIgnoredNodeTypes` argument to `XmlEncoder::__construct` to configure node types to be ignored during encoding. +* added `AdvancedNameConverterInterface` to access the class, the format and the context in a name converter 4.1.0 ----- diff --git a/src/Symfony/Component/Serializer/NameConverter/AdvancedNameConverterInterface.php b/src/Symfony/Component/Serializer/NameConverter/AdvancedNameConverterInterface.php new file mode 100644 index 0000000000..d0f94fdfc1 --- /dev/null +++ b/src/Symfony/Component/Serializer/NameConverter/AdvancedNameConverterInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\NameConverter; + +/** + * Gives access to the class, the format and the context in the property name converters. + * + * @author Kévin Dunglas + */ +interface AdvancedNameConverterInterface extends NameConverterInterface +{ + /** + * {@inheritdoc} + */ + public function normalize($propertyName, string $class = null, string $format = null, array $context = array()); + + /** + * {@inheritdoc} + */ + public function denormalize($propertyName, string $class = null, string $format = null, array $context = array()); +} diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index bc6f68b7e8..326a83fda6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -348,7 +348,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn $params = array(); foreach ($constructorParameters as $constructorParameter) { $paramName = $constructorParameter->name; - $key = $this->nameConverter ? $this->nameConverter->normalize($paramName) : $paramName; + $key = $this->nameConverter ? $this->nameConverter->normalize($paramName, $class, $format, $context) : $paramName; $allowed = false === $allowedAttributes || \in_array($paramName, $allowedAttributes); $ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context); diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 524cb656c0..aaf047a323 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -108,7 +108,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer $stack[$attribute] = $attributeValue; } - $data = $this->updateData($data, $attribute, $attributeValue); + $data = $this->updateData($data, $attribute, $attributeValue, $class, $format, $context); } foreach ($stack as $attribute => $attributeValue) { @@ -116,7 +116,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer', $attribute)); } - $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $this->createChildContext($context, $attribute))); + $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $this->createChildContext($context, $attribute)), $class, $format, $context); } return $data; @@ -246,7 +246,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer foreach ($normalizedData as $attribute => $value) { if ($this->nameConverter) { - $attribute = $this->nameConverter->denormalize($attribute); + $attribute = $this->nameConverter->denormalize($attribute, $class, $format, $context); } if ((false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) { @@ -400,10 +400,10 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer * * @param mixed $attributeValue */ - private function updateData(array $data, string $attribute, $attributeValue): array + private function updateData(array $data, string $attribute, $attributeValue, string $class, ?string $format, array $context): array { if ($this->nameConverter) { - $attribute = $this->nameConverter->normalize($attribute); + $attribute = $this->nameConverter->normalize($attribute, $class, $format, $context); } $data[$attribute] = $attributeValue; diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 218b85d933..11030c00d5 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -18,6 +18,7 @@ use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\PropertyInfoExtractor; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; +use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; @@ -861,6 +862,24 @@ class ObjectNormalizerTest extends TestCase ), ))); } + + public function testAdvancedNameConverter() + { + $nameConverter = new class() implements AdvancedNameConverterInterface { + public function normalize($propertyName, string $class = null, string $format = null, array $context = array()) + { + return sprintf('%s-%s-%s-%s', $propertyName, $class, $format, $context['foo']); + } + + public function denormalize($propertyName, string $class = null, string $format = null, array $context = array()) + { + return sprintf('%s-%s-%s-%s', $propertyName, $class, $format, $context['foo']); + } + }; + + $normalizer = new ObjectNormalizer(null, $nameConverter); + $this->assertArrayHasKey('foo-Symfony\Component\Serializer\Tests\Normalizer\ObjectDummy-json-bar', $normalizer->normalize(new ObjectDummy(), 'json', array('foo' => 'bar'))); + } } class ObjectDummy