bug #30977 [serializer] prevent mixup in normalizer of the object to populate (dbu)

This PR was merged into the 3.4 branch.

Discussion
----------

[serializer] prevent mixup in normalizer of the object to populate

EUFOSSA

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

OBJECT_TO_POPULATE is meant to specify the top level object. The implementation left the option in the context and it would be used whenever we have the first element that matches the class. #30607 (to master) introduces the feature to also keep the instances of attributes to deeply populate an existing object tree. In both cases, we do not want the mix up to happen with what the current OBJECT_TO_POPULATE is.

Commits
-------

fdb668e051 prevent mixup of the object to populate
This commit is contained in:
Fabien Potencier 2019-04-08 08:05:24 +02:00
commit b30f57e14b
2 changed files with 29 additions and 0 deletions

View File

@ -330,6 +330,8 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
return $object;
}
// clean up even if no match
unset($context[static::OBJECT_TO_POPULATE]);
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
if ($constructor) {

View File

@ -315,6 +315,30 @@ class ObjectNormalizerTest extends TestCase
);
}
public function testObjectToPopulateNoMatch()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory, null, null, new PhpDocExtractor());
new Serializer([$this->normalizer]);
$objectToPopulate = new ObjectInner();
$objectToPopulate->foo = 'foo';
$outer = $this->normalizer->denormalize([
'foo' => 'foo',
'inner' => [
'bar' => 'bar',
],
], ObjectOuter::class, null, [ObjectNormalizer::OBJECT_TO_POPULATE => $objectToPopulate]);
$this->assertInstanceOf(ObjectOuter::class, $outer);
$inner = $outer->getInner();
$this->assertInstanceOf(ObjectInner::class, $inner);
$this->assertNotSame($objectToPopulate, $inner);
$this->assertSame('bar', $inner->bar);
$this->assertNull($inner->foo);
}
/**
* @dataProvider provideCallbacks
*/
@ -936,6 +960,9 @@ class ObjectOuter
{
public $foo;
public $bar;
/**
* @var ObjectInner
*/
private $inner;
private $date;