From 0506d0be88fdaf9d6dd67d828008605c86aa0230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B0=D0=B2=D1=80=D0=B8=D0=BD=D0=B5=D0=BD=D0=BA?= =?UTF-8?q?=D0=BE=20=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC?= Date: Sat, 10 Aug 2019 18:37:03 +0300 Subject: [PATCH] [Serializer] added the ability to pass \ArrayObject to context.callbacks This allows adding more flexible callback reactions since \ArrayObject can return a callback dynamically --- .../Normalizer/AbstractNormalizer.php | 6 +++--- .../Normalizer/AbstractObjectNormalizer.php | 4 ++-- .../Normalizer/Features/CallbacksTestTrait.php | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 5f165b56ac77..9724e05b9772 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -169,8 +169,8 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory $this->defaultContext = array_merge($this->defaultContext, $defaultContext); if (isset($this->defaultContext[self::CALLBACKS])) { - if (!\is_array($this->defaultContext[self::CALLBACKS])) { - throw new InvalidArgumentException(sprintf('The "%s" default context option must be an array of callables.', self::CALLBACKS)); + if (!\is_array($this->defaultContext[self::CALLBACKS]) && !$this->defaultContext[self::CALLBACKS] instanceof \ArrayObject) { + throw new InvalidArgumentException(sprintf('The "%s" default context option must be an array or an \ArrayObject of callables.', self::CALLBACKS)); } foreach ($this->defaultContext[self::CALLBACKS] as $attribute => $callback) { @@ -230,7 +230,7 @@ public function setCircularReferenceHandler(callable $circularReferenceHandler) * * @throws InvalidArgumentException if a non-callable callback is set */ - public function setCallbacks(array $callbacks) + public function setCallbacks($callbacks) { @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the "callbacks" key of the context instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 9871a7630e35..7fdef4be7921 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -144,8 +144,8 @@ public function normalize($object, $format = null, array $context = []) } if (isset($context[self::CALLBACKS])) { - if (!\is_array($context[self::CALLBACKS])) { - throw new InvalidArgumentException(sprintf('The "%s" context option must be an array of callables.', self::CALLBACKS)); + if (!\is_array($context[self::CALLBACKS]) && !$context[self::CALLBACKS] instanceof \ArrayObject) { + throw new InvalidArgumentException(sprintf('The "%s" context option must be an array or an \ArrayObject of callables.', self::CALLBACKS)); } foreach ($context[self::CALLBACKS] as $attribute => $callback) { diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php index ccb54d9c6fd2..953c0647357d 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/Features/CallbacksTestTrait.php @@ -103,6 +103,23 @@ public function provideCallbacks() [new CallbacksObject(), new CallbacksObject()], ['bar' => 2], ], + 'Callbacks as ArrayObject' => [ + new class() extends \ArrayObject { + public function offsetExists($index) + { + return true; + } + + public function offsetGet($index) + { + return function () use ($index) { + return $index; + }; + } + }, + 'baz', + ['bar' => 'bar'], + ], ]; }