Skip to content

Commit e09a72e

Browse files
Merge branch '7.2' into 7.3
* 7.2: use Table::addPrimaryKeyConstraint() with Doctrine DBAL 4.3+ [Serializer] Fix ObjectNormalizer default context with named serializers [Serializer] Fix code skipped by premature return [TypeInfo] Fix `isSatisfiedBy` not traversing type tree Update JsDelivrEsmResolver::IMPORT_REGEX to support dynamic imports
2 parents 0d0bc59 + d8b75b2 commit e09a72e

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

DependencyInjection/SerializerPass.php

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Serializer\Debug\TraceableNormalizer;
2222
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
2323
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
24+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
2425
use Symfony\Component\Serializer\SerializerInterface;
2526

2627
/**
@@ -56,17 +57,27 @@ public function process(ContainerBuilder $container): void
5657
throw new RuntimeException('You must tag at least one service as "serializer.encoder" to use the "serializer" service.');
5758
}
5859

60+
$defaultContext = [];
5961
if ($container->hasParameter('serializer.default_context')) {
6062
$defaultContext = $container->getParameter('serializer.default_context');
61-
$this->bindDefaultContext($container, array_merge($normalizers, $encoders), $defaultContext);
6263
$container->getParameterBag()->remove('serializer.default_context');
6364
$container->getDefinition('serializer')->setArgument('$defaultContext', $defaultContext);
6465
}
6566

67+
/** @var ?string $circularReferenceHandler */
68+
$circularReferenceHandler = $container->hasParameter('.serializer.circular_reference_handler')
69+
? $container->getParameter('.serializer.circular_reference_handler') : null;
70+
71+
/** @var ?string $maxDepthHandler */
72+
$maxDepthHandler = $container->hasParameter('.serializer.max_depth_handler')
73+
? $container->getParameter('.serializer.max_depth_handler') : null;
74+
75+
$this->bindDefaultContext($container, array_merge($normalizers, $encoders), $defaultContext, $circularReferenceHandler, $maxDepthHandler);
76+
6677
$this->configureSerializer($container, 'serializer', $normalizers, $encoders, 'default');
6778

6879
if ($namedSerializers) {
69-
$this->configureNamedSerializers($container);
80+
$this->configureNamedSerializers($container, $circularReferenceHandler, $maxDepthHandler);
7081
}
7182
}
7283

@@ -100,11 +111,22 @@ private function createNamedSerializerTags(ContainerBuilder $container, string $
100111
}
101112
}
102113

103-
private function bindDefaultContext(ContainerBuilder $container, array $services, array $defaultContext): void
114+
private function bindDefaultContext(ContainerBuilder $container, array $services, array $defaultContext, ?string $circularReferenceHandler, ?string $maxDepthHandler): void
104115
{
105116
foreach ($services as $id) {
106117
$definition = $container->getDefinition((string) $id);
107-
$definition->setBindings(['array $defaultContext' => new BoundArgument($defaultContext, false)] + $definition->getBindings());
118+
119+
$context = $defaultContext;
120+
if (is_a($definition->getClass(), ObjectNormalizer::class, true)) {
121+
if (null !== $circularReferenceHandler) {
122+
$context += ['circular_reference_handler' => new Reference($circularReferenceHandler)];
123+
}
124+
if (null !== $maxDepthHandler) {
125+
$context += ['max_depth_handler' => new Reference($maxDepthHandler)];
126+
}
127+
}
128+
129+
$definition->setBindings(['array $defaultContext' => new BoundArgument($context, false)] + $definition->getBindings());
108130
}
109131
}
110132

@@ -127,7 +149,7 @@ private function configureSerializer(ContainerBuilder $container, string $id, ar
127149
$serializerDefinition->replaceArgument(1, $encoders);
128150
}
129151

130-
private function configureNamedSerializers(ContainerBuilder $container): void
152+
private function configureNamedSerializers(ContainerBuilder $container, ?string $circularReferenceHandler, ?string $maxDepthHandler): void
131153
{
132154
$defaultSerializerNameConverter = $container->hasParameter('.serializer.name_converter')
133155
? $container->getParameter('.serializer.name_converter') : null;
@@ -151,7 +173,7 @@ private function configureNamedSerializers(ContainerBuilder $container): void
151173
$normalizers = $this->buildChildDefinitions($container, $serializerName, $normalizers, $config);
152174
$encoders = $this->buildChildDefinitions($container, $serializerName, $encoders, $config);
153175

154-
$this->bindDefaultContext($container, array_merge($normalizers, $encoders), $config['default_context']);
176+
$this->bindDefaultContext($container, array_merge($normalizers, $encoders), $config['default_context'], $circularReferenceHandler, $maxDepthHandler);
155177

156178
$container->registerChild($serializerId, 'serializer')->setArgument('$defaultContext', $config['default_context']);
157179
$container->registerAliasForArgument($serializerId, SerializerInterface::class, $serializerName.'.serializer');
@@ -188,7 +210,9 @@ private function buildChildDefinitions(ContainerBuilder $container, string $seri
188210
foreach ($services as &$id) {
189211
$childId = $id.'.'.$serializerName;
190212

191-
$definition = $container->registerChild($childId, (string) $id);
213+
$definition = $container->registerChild($childId, (string) $id)
214+
->setClass($container->getDefinition((string) $id)->getClass())
215+
;
192216

193217
if (null !== $nameConverterIndex = $this->findNameConverterIndex($container, (string) $id)) {
194218
$definition->replaceArgument($nameConverterIndex, new Reference($config['name_converter']));

Tests/DependencyInjection/SerializerPassTest.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\Serializer\DependencyInjection\SerializerPass;
2222
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
2323
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
24+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
2425
use Symfony\Component\Serializer\SerializerInterface;
2526

2627
/**
@@ -101,6 +102,32 @@ public function testBindSerializerDefaultContext()
101102
$this->assertEquals($context, $container->getDefinition('serializer')->getArgument('$defaultContext'));
102103
}
103104

105+
/**
106+
* @testWith [{}, {}]
107+
* [{"serializer.default_context": {"enable_max_depth": true}}, {"enable_max_depth": true}]
108+
* [{".serializer.circular_reference_handler": "foo"}, {"circular_reference_handler": "foo"}]
109+
* [{".serializer.max_depth_handler": "bar"}, {"max_depth_handler": "bar"}]
110+
* [{"serializer.default_context": {"enable_max_depth": true}, ".serializer.circular_reference_handler": "foo", ".serializer.max_depth_handler": "bar"}, {"enable_max_depth": true, "circular_reference_handler": "foo", "max_depth_handler": "bar"}]
111+
*/
112+
public function testBindObjectNormalizerDefaultContext(array $parameters, array $context)
113+
{
114+
$container = new ContainerBuilder();
115+
$container->setParameter('kernel.debug', false);
116+
$container->register('serializer')->setArguments([null, null, []]);
117+
$container->getParameterBag()->add($parameters);
118+
$definition = $container->register('serializer.normalizer.object')
119+
->setClass(ObjectNormalizer::class)
120+
->addTag('serializer.normalizer')
121+
->addTag('serializer.encoder')
122+
;
123+
124+
$serializerPass = new SerializerPass();
125+
$serializerPass->process($container);
126+
127+
$bindings = $definition->getBindings();
128+
$this->assertEquals($bindings['array $defaultContext'], new BoundArgument($context, false));
129+
}
130+
104131
public function testNormalizersAndEncodersAreDecoratedAndOrderedWhenCollectingData()
105132
{
106133
$container = new ContainerBuilder();
@@ -567,7 +594,9 @@ public function testBindSerializerDefaultContextToNamedSerializers()
567594
$serializerPass = new SerializerPass();
568595
$serializerPass->process($container);
569596

570-
$this->assertSame([], $definition->getBindings());
597+
$bindings = $definition->getBindings();
598+
$this->assertArrayHasKey('array $defaultContext', $bindings);
599+
$this->assertEquals($bindings['array $defaultContext'], new BoundArgument([], false));
571600

572601
$bindings = $container->getDefinition('n1.api')->getBindings();
573602
$this->assertArrayHasKey('array $defaultContext', $bindings);
@@ -576,6 +605,37 @@ public function testBindSerializerDefaultContextToNamedSerializers()
576605
$this->assertEquals($defaultContext, $container->getDefinition('serializer.api')->getArgument('$defaultContext'));
577606
}
578607

608+
/**
609+
* @testWith [{}, {}, {}]
610+
* [{"enable_max_depth": true}, {}, {"enable_max_depth": true}]
611+
* [{}, {".serializer.circular_reference_handler": "foo"}, {"circular_reference_handler": "foo"}]
612+
* [{}, {".serializer.max_depth_handler": "bar"}, {"max_depth_handler": "bar"}]
613+
* [{"enable_max_depth": true}, {".serializer.circular_reference_handler": "foo", ".serializer.max_depth_handler": "bar"}, {"enable_max_depth": true, "circular_reference_handler": "foo", "max_depth_handler": "bar"}]
614+
*/
615+
public function testBindNamedSerializerObjectNormalizerDefaultContext(array $defaultContext, array $parameters, array $context)
616+
{
617+
$container = new ContainerBuilder();
618+
$container->setParameter('kernel.debug', false);
619+
$container->setParameter('.serializer.named_serializers', [
620+
'api' => ['default_context' => $defaultContext],
621+
]);
622+
623+
$container->register('serializer')->setArguments([null, null, []]);
624+
$container->getParameterBag()->add($parameters);
625+
$container->register('serializer.normalizer.object')
626+
->setClass(ObjectNormalizer::class)
627+
->addTag('serializer.normalizer', ['serializer' => '*'])
628+
->addTag('serializer.encoder', ['serializer' => '*'])
629+
;
630+
631+
$serializerPass = new SerializerPass();
632+
$serializerPass->process($container);
633+
634+
$bindings = $container->getDefinition('serializer.normalizer.object.api')->getBindings();
635+
$this->assertArrayHasKey('array $defaultContext', $bindings);
636+
$this->assertEquals($bindings['array $defaultContext'], new BoundArgument($context, false));
637+
}
638+
579639
public function testNamedSerializersAreRegistered()
580640
{
581641
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)