Skip to content

[Serializer] Migrate ArrayDenormalizer to DenormalizerAwareInterface #39577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions UPGRADE-5.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ Security
--------

* Deprecated voters that do not return a valid decision when calling the `vote` method.

Serializer
----------

* Deprecated `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead.
6 changes: 6 additions & 0 deletions UPGRADE-6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ Security
* Removed the `AbstractRememberMeServices::$providerKey` property in favor of `AbstractRememberMeServices::$firewallName`
* `AccessDecisionManager` now throw an exception when a voter does not return a valid decision.

Serializer
----------

* Removed `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead.
* `ArrayDenormalizer` does not implement `SerializerAwareInterface` anymore.

TwigBundle
----------

Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/Serializer/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

5.3.0
-----

* deprecated `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead.

5.2.0
-----

Expand Down
35 changes: 18 additions & 17 deletions src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\Serializer\Exception\BadMethodCallException;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerInterface;

Expand All @@ -24,24 +25,19 @@
*
* @final
*/
class ArrayDenormalizer implements ContextAwareDenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
class ArrayDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface, SerializerAwareInterface, CacheableSupportsMethodInterface
{
/**
* @var SerializerInterface|DenormalizerInterface
*/
private $serializer;
use DenormalizerAwareTrait;

/**
* {@inheritdoc}
*
* @throws NotNormalizableValueException
*
* @return array
*/
public function denormalize($data, string $type, string $format = null, array $context = [])
public function denormalize($data, string $type, string $format = null, array $context = []): array
{
if (null === $this->serializer) {
throw new BadMethodCallException('Please set a serializer before calling denormalize()!');
if (null === $this->denormalizer) {
throw new BadMethodCallException('Please set a denormalizer before calling denormalize()!');
}
if (!\is_array($data)) {
throw new InvalidArgumentException('Data expected to be an array, '.get_debug_type($data).' given.');
Expand All @@ -50,7 +46,6 @@ public function denormalize($data, string $type, string $format = null, array $c
throw new InvalidArgumentException('Unsupported class: '.$type);
}

$serializer = $this->serializer;
$type = substr($type, 0, -2);

$builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null;
Expand All @@ -59,7 +54,7 @@ public function denormalize($data, string $type, string $format = null, array $c
throw new NotNormalizableValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, get_debug_type($key)));
}

$data[$key] = $serializer->denormalize($value, $type, $format, $context);
$data[$key] = $this->denormalizer->denormalize($value, $type, $format, $context);
}

return $data;
Expand All @@ -70,31 +65,37 @@ public function denormalize($data, string $type, string $format = null, array $c
*/
public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool
{
if (null === $this->serializer) {
throw new BadMethodCallException(sprintf('The serializer needs to be set to allow "%s()" to be used.', __METHOD__));
if (null === $this->denormalizer) {
throw new BadMethodCallException(sprintf('The nested denormalizer needs to be set to allow "%s()" to be used.', __METHOD__));
}

return '[]' === substr($type, -2)
&& $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context);
&& $this->denormalizer->supportsDenormalization($data, substr($type, 0, -2), $format, $context);
}

/**
* {@inheritdoc}
*
* @deprecated call setDenormalizer() instead
*/
public function setSerializer(SerializerInterface $serializer)
{
if (!$serializer instanceof DenormalizerInterface) {
throw new InvalidArgumentException('Expected a serializer that also implements DenormalizerInterface.');
}

$this->serializer = $serializer;
if (Serializer::class !== debug_backtrace()[1]['class'] ?? null) {
trigger_deprecation('symfony/serializer', '5.3', 'Calling "%s" is deprecated. Please call setDenormalizer() instead.');
}

$this->setDenormalizer($serializer);
}

/**
* {@inheritdoc}
*/
public function hasCacheableSupportsMethod(): bool
{
return $this->serializer instanceof CacheableSupportsMethodInterface && $this->serializer->hasCacheableSupportsMethod();
return $this->denormalizer instanceof CacheableSupportsMethodInterface && $this->denormalizer->hasCacheableSupportsMethod();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,30 @@

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
use Symfony\Component\Serializer\Serializer;

class ArrayDenormalizerTest extends TestCase
{
use ExpectDeprecationTrait;

/**
* @var ArrayDenormalizer
*/
private $denormalizer;

/**
* @var SerializerInterface|MockObject
* @var ContextAwareDenormalizerInterface|MockObject
*/
private $serializer;

protected function setUp(): void
{
$this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\Serializer')->getMock();
$this->serializer = $this->getMockBuilder(ContextAwareDenormalizerInterface::class)->getMock();
$this->denormalizer = new ArrayDenormalizer();
$this->denormalizer->setSerializer($this->serializer);
$this->denormalizer->setDenormalizer($this->serializer);
}

public function testDenormalize()
Expand Down Expand Up @@ -65,11 +69,51 @@ public function testDenormalize()
);
}

/**
* @group legacy
*/
public function testDenormalizeLegacy()
{
$serializer = $this->getMockBuilder(Serializer::class)->getMock();

$serializer->expects($this->exactly(2))
->method('denormalize')
->withConsecutive(
[['foo' => 'one', 'bar' => 'two']],
[['foo' => 'three', 'bar' => 'four']]
)
->willReturnOnConsecutiveCalls(
new ArrayDummy('one', 'two'),
new ArrayDummy('three', 'four')
);

$denormalizer = new ArrayDenormalizer();

$this->expectDeprecation('Since symfony/serializer 5.3: Calling "%s" is deprecated. Please call setDenormalizer() instead.');
$denormalizer->setSerializer($serializer);

$result = $denormalizer->denormalize(
[
['foo' => 'one', 'bar' => 'two'],
['foo' => 'three', 'bar' => 'four'],
],
__NAMESPACE__.'\ArrayDummy[]'
);

$this->assertEquals(
[
new ArrayDummy('one', 'two'),
new ArrayDummy('three', 'four'),
],
$result
);
}

public function testSupportsValidArray()
{
$this->serializer->expects($this->once())
->method('supportsDenormalization')
->with($this->anything(), ArrayDummy::class, $this->anything())
->with($this->anything(), ArrayDummy::class, 'json', ['con' => 'text'])
->willReturn(true);

$this->assertTrue(
Expand All @@ -78,7 +122,9 @@ public function testSupportsValidArray()
['foo' => 'one', 'bar' => 'two'],
['foo' => 'three', 'bar' => 'four'],
],
__NAMESPACE__.'\ArrayDummy[]'
__NAMESPACE__.'\ArrayDummy[]',
'json',
['con' => 'text']
)
);
}
Expand Down