From 99f829ec2b59e4dafca3040a9150c48c42f01cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Mon, 23 Apr 2018 16:51:34 +0200 Subject: [PATCH] [Serializer] Allow to access to the format and context in circular ref handler --- src/Symfony/Component/Serializer/CHANGELOG.md | 5 +++++ .../Serializer/Normalizer/AbstractNormalizer.php | 13 ++++++++++--- .../Normalizer/AbstractObjectNormalizer.php | 10 +++++----- .../Tests/Normalizer/ObjectNormalizerTest.php | 9 +++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 983bb9f5a0..6cd80fdb0b 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.2.0 +----- + +* `AbstractNormalizer::handleCircularReference` is now final, and receives two optional extra arguments: the format and the context + 4.1.0 ----- diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index fe8b05ef86..f8344cca52 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -190,16 +190,23 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn * If a circular reference handler is set, it will be called. Otherwise, a * {@class CircularReferenceException} will be thrown. * - * @param object $object + * @final since Symfony 4.2 + * + * @param object $object + * @param string|null $format + * @param array $context * * @return mixed * * @throws CircularReferenceException */ - protected function handleCircularReference($object) + protected function handleCircularReference($object/*, string $format = null, array $context = array()*/) { + $format = \func_num_args() > 1 ? func_get_arg(1) : null; + $context = \func_num_args() > 2 ? func_get_arg(2) : array(); + if ($this->circularReferenceHandler) { - return \call_user_func($this->circularReferenceHandler, $object); + return \call_user_func($this->circularReferenceHandler, $object, $format, $context); } throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', \get_class($object), $this->circularReferenceLimit)); diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 7f8d341846..f901712350 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -79,13 +79,13 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer } if ($this->isCircularReference($object, $context)) { - return $this->handleCircularReference($object); + return $this->handleCircularReference($object, $format, $context); } $data = array(); $stack = array(); $attributes = $this->getAttributes($object, $format, $context); - $class = get_class($object); + $class = \get_class($object); $attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null; foreach ($attributes as $attribute) { @@ -154,7 +154,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer */ protected function getAttributes($object, $format = null, array $context) { - $class = get_class($object); + $class = \get_class($object); $key = $class.'-'.$context['cache_key']; if (isset($this->attributesCache[$key])) { @@ -248,7 +248,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer $attribute = $this->nameConverter->denormalize($attribute); } - if ((false !== $allowedAttributes && !in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) { + if ((false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) { if (isset($context[self::ALLOW_EXTRA_ATTRIBUTES]) && !$context[self::ALLOW_EXTRA_ATTRIBUTES]) { $extraAttributes[] = $attribute; } @@ -345,7 +345,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer return (float) $data; } - if (call_user_func('is_'.$builtinType, $data)) { + if (\call_user_func('is_'.$builtinType, $data)) { return $data; } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 62338af339..7619392543 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -544,6 +544,15 @@ class ObjectNormalizerTest extends TestCase $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy'); $this->assertEquals($expected, $this->normalizer->normalize($obj)); + + $this->normalizer->setCircularReferenceHandler(function ($obj, string $format, array $context) { + $this->assertInstanceOf(CircularReferenceDummy::class, $obj); + $this->assertSame('test', $format); + $this->arrayHasKey('foo', $context); + + return \get_class($obj); + }); + $this->assertEquals($expected, $this->normalizer->normalize($obj, 'test', array('foo' => 'bar'))); } public function testDenormalizeNonExistingAttribute()