Skip to content

Commit

Permalink
feature #21716 [Serializer] Add Support for object_to_populate in C…
Browse files Browse the repository at this point in the history
…ustomNormalizer (chrisguitarguy)

This PR was squashed before being merged into the 3.4 branch (closes #21716).

Discussion
----------

[Serializer] Add Support for `object_to_populate` in CustomNormalizer

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21715
| License       | MIT
| Doc PR        | n/a

This pulls a trait out of `AbstractNormalizer` with a method to extract the object to populate and adds some tests for it. Then uses that trait in both `AbstractNormalizer` and `CustomNormalizer` so both can support the `object_to_populate` key.

Commits
-------

ec9242d [Serializer] Add Support for  in CustomNormalizer
  • Loading branch information
fabpot committed Sep 27, 2017
2 parents f56f28b + ec9242d commit 94aef22
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 9 deletions.
Expand Up @@ -27,6 +27,8 @@
*/
abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
use ObjectToPopulateTrait;

const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
const OBJECT_TO_POPULATE = 'object_to_populate';
const GROUPS = 'groups';
Expand Down Expand Up @@ -317,12 +319,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref
$format = null;
}

if (
isset($context[static::OBJECT_TO_POPULATE]) &&
is_object($context[static::OBJECT_TO_POPULATE]) &&
$context[static::OBJECT_TO_POPULATE] instanceof $class
) {
$object = $context[static::OBJECT_TO_POPULATE];
if (null !== $object = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) {
unset($context[static::OBJECT_TO_POPULATE]);

return $object;
Expand Down
Expand Up @@ -19,10 +19,11 @@
*/
class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface
{
private $cache = array();

use ObjectToPopulateTrait;
use SerializerAwareTrait;

private $cache = array();

/**
* {@inheritdoc}
*/
Expand All @@ -36,7 +37,7 @@ public function normalize($object, $format = null, array $context = array())
*/
public function denormalize($data, $class, $format = null, array $context = array())
{
$object = new $class();
$object = $this->extractObjectToPopulate($class, $context) ?: new $class();
$object->denormalize($this->serializer, $data, $format, $context);

return $object;
Expand Down
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Normalizer;

trait ObjectToPopulateTrait
{
/**
* Extract the `object_to_populate` field from the context if it exists
* and is an instance of the provided $class.
*
* @param string $class The class the object should be
* @param $context The denormalization context
* @param string $key They in which to look for the object to populate.
* Keeps backwards compatibility with `AbstractNormalizer`.
*
* @return object|null an object if things check out, null otherwise
*/
protected function extractObjectToPopulate($class, array $context, $key = null)
{
$key = $key ?: 'object_to_populate';

if (
isset($context[$key]) &&
is_object($context[$key]) &&
$context[$key] instanceof $class
) {
return $context[$key];
}

return null;
}
}
Expand Up @@ -56,6 +56,18 @@ public function testDeserialize()
$this->assertNull($obj->xmlFoo);
}

public function testDenormalizeWithObjectToPopulateUsesProvidedObject()
{
$expected = new ScalarDummy();
$obj = $this->normalizer->denormalize('foo', ScalarDummy::class, 'json', array(
'object_to_populate' => $expected,
));

$this->assertSame($expected, $obj);
$this->assertEquals('foo', $obj->foo);
$this->assertNull($obj->xmlFoo);
}

public function testSupportsNormalization()
{
$this->assertTrue($this->normalizer->supportsNormalization(new ScalarDummy()));
Expand Down
@@ -0,0 +1,47 @@
<?php

namespace Symfony\Component\Serializer\Tests\Normalizer;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
use Symfony\Component\Serializer\Tests\Fixtures\ProxyDummy;

class ObjectToPopulateTraitTest extends TestCase
{
use ObjectToPopulateTrait;

public function testExtractObjectToPopulateReturnsNullWhenKeyIsMissing()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array());

$this->assertNull($object);
}

public function testExtractObjectToPopulateReturnsNullWhenNonObjectIsProvided()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => 'not an object',
));

$this->assertNull($object);
}

public function testExtractObjectToPopulateReturnsNullWhenTheClassIsNotAnInstanceOfTheProvidedClass()
{
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => new \stdClass(),
));

$this->assertNull($object);
}

public function testExtractObjectToPopulateReturnsObjectWhenEverythingChecksOut()
{
$expected = new ProxyDummy();
$object = $this->extractObjectToPopulate(ProxyDummy::class, array(
'object_to_populate' => $expected,
));

$this->assertSame($expected, $object);
}
}

0 comments on commit 94aef22

Please sign in to comment.