Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cbbda0b

Browse files
committed
extract normalizer tests for the context options into traits to reuse them for all normalizers
1 parent c68ef46 commit cbbda0b

25 files changed

+1320
-899
lines changed

src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,89 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
3232
use ObjectToPopulateTrait;
3333
use SerializerAwareTrait;
3434

35-
const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
36-
const OBJECT_TO_POPULATE = 'object_to_populate';
37-
const GROUPS = 'groups';
38-
const ATTRIBUTES = 'attributes';
39-
const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
40-
const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments';
41-
const CALLBACKS = 'callbacks';
42-
const CIRCULAR_REFERENCE_HANDLER = 'circular_reference_handler';
43-
const IGNORED_ATTRIBUTES = 'ignored_attributes';
35+
/* constants to configure the context */
36+
37+
/**
38+
* How many loops of circular reference to allow while normalizing.
39+
*
40+
* The default value of 1 means that when we encounter the same object a
41+
* second time, we consider that a circular reference.
42+
*
43+
* You can raise this value for special cases, e.g. in combination with the
44+
* max depth setting of the object normalizer.
45+
*/
46+
public const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit';
47+
48+
/**
49+
* Instead of creating a new instance of an object, update the specified object.
50+
*
51+
* If you have a nested structure, child objects will be overwritten with
52+
* new instances unless you set DEEP_OBJECT_TO_POPULATE to true.
53+
*/
54+
public const OBJECT_TO_POPULATE = 'object_to_populate';
55+
56+
/**
57+
* Only (de)normalize attributes that are in the specified groups.
58+
*/
59+
public const GROUPS = 'groups';
60+
61+
/**
62+
* Limit (de)normalize to the specified names.
63+
*
64+
* For nested structures, this list needs to reflect the object tree.
65+
*/
66+
public const ATTRIBUTES = 'attributes';
67+
68+
/**
69+
* If ATTRIBUTES are specified, and the source has fields that are not part of that list,
70+
* either ignore those attributes (true) or throw an ExtraAttributesException (false).
71+
*/
72+
public const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes';
73+
74+
/**
75+
* Hashmap of default values for constructor arguments.
76+
*
77+
* The names need to match the parameter names in the constructor arguments.
78+
*/
79+
public const DEFAULT_CONSTRUCTOR_ARGUMENTS = 'default_constructor_arguments';
80+
81+
/**
82+
* Hashmap of field name => callable to normalize this field.
83+
*
84+
* The callable is called if the field is encountered with the arguments:
85+
*
86+
* - mixed $attributeValue value of this field
87+
* - object $object the whole object being normalized
88+
* - string $attributeName name of the attribute being normalized
89+
* - string $format the requested format
90+
* - array $context the serialization context
91+
*/
92+
public const CALLBACKS = 'callbacks';
93+
94+
/**
95+
* Handler to call when a circular reference has been detected.
96+
*
97+
* If you specify no handler, a CircularReferenceException is thrown.
98+
*
99+
* The method will be called with ($object, $format, $context) and its
100+
* return value is returned as the result of the normalize call.
101+
*/
102+
public const CIRCULAR_REFERENCE_HANDLER = 'circular_reference_handler';
103+
104+
/**
105+
* Skip the specified attributes when normalizing an object tree.
106+
*
107+
* This list is applied to each element of nested structures.
108+
*
109+
* Note: The behaviour for nested structures is different from ATTRIBUTES
110+
* for historical reason. Aligning the behaviour would be a BC break.
111+
*/
112+
public const IGNORED_ATTRIBUTES = 'ignored_attributes';
44113

45114
/**
46115
* @internal
47116
*/
48-
const CIRCULAR_REFERENCE_LIMIT_COUNTERS = 'circular_reference_limit_counters';
117+
protected const CIRCULAR_REFERENCE_LIMIT_COUNTERS = 'circular_reference_limit_counters';
49118

50119
protected $defaultContext = [
51120
self::ALLOW_EXTRA_ATTRIBUTES => true,

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,60 @@
3333
*/
3434
abstract class AbstractObjectNormalizer extends AbstractNormalizer
3535
{
36-
const ENABLE_MAX_DEPTH = 'enable_max_depth';
37-
const DEPTH_KEY_PATTERN = 'depth_%s::%s';
38-
const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
39-
const SKIP_NULL_VALUES = 'skip_null_values';
40-
const MAX_DEPTH_HANDLER = 'max_depth_handler';
41-
const EXCLUDE_FROM_CACHE_KEY = 'exclude_from_cache_key';
42-
const DEEP_OBJECT_TO_POPULATE = 'deep_object_to_populate';
36+
/**
37+
* Set to true to respect the max depth metadata on fields.
38+
*/
39+
public const ENABLE_MAX_DEPTH = 'enable_max_depth';
40+
41+
/**
42+
* How to track the current depth in the context.
43+
*/
44+
private const DEPTH_KEY_PATTERN = 'depth_%s::%s';
45+
46+
/**
47+
* While denormalizing, we can verify that types match.
48+
*
49+
* You can disable this by setting this flag to true.
50+
*/
51+
public const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
52+
53+
/**
54+
* Flag to control whether fields with the value `null` should be output
55+
* when normalizing or omitted.
56+
*/
57+
public const SKIP_NULL_VALUES = 'skip_null_values';
58+
59+
/**
60+
* Callback to allow to set a value for an attribute when the max depth has
61+
* been reached.
62+
*
63+
* If no callback is given, the attribute is skipped. If a callable is
64+
* given, its return value is used (even if null).
65+
*
66+
* The arguments are:
67+
*
68+
* - mixed $attributeValue value of this field
69+
* - object $object the whole object being normalized
70+
* - string $attributeName name of the attribute being normalized
71+
* - string $format the requested format
72+
* - array $context the serialization context
73+
*/
74+
public const MAX_DEPTH_HANDLER = 'max_depth_handler';
75+
76+
/**
77+
* Specify which context key are not relevant to determine which attributes
78+
* of an object to (de)normalize.
79+
*/
80+
public const EXCLUDE_FROM_CACHE_KEY = 'exclude_from_cache_key';
81+
82+
/**
83+
* Flag to tell the denormalizer to also populate existing objects on
84+
* attributes of the main object.
85+
*
86+
* Setting this to true is only useful if you also specify the root object
87+
* in OBJECT_TO_POPULATE.
88+
*/
89+
public const DEEP_OBJECT_TO_POPULATE = 'deep_object_to_populate';
4390

4491
private $propertyTypeExtractor;
4592
private $typesCache = [];

src/Symfony/Component/Serializer/Tests/Fixtures/DeepObjectPopulateChildDummy.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,20 @@ class DeepObjectPopulateChildDummy
1919
public $foo;
2020

2121
public $bar;
22+
23+
// needed to have GetSetNormalizer consider this class as supported
24+
public function getFoo()
25+
{
26+
return $this->foo;
27+
}
28+
29+
public function setFoo($foo)
30+
{
31+
$this->foo = $foo;
32+
}
33+
34+
public function setBar($bar)
35+
{
36+
$this->bar = $bar;
37+
}
2238
}

src/Symfony/Component/Serializer/Tests/Fixtures/MaxDepthDummy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ public function getChild()
4242
{
4343
return $this->child;
4444
}
45+
46+
public function getFoo()
47+
{
48+
return $this->foo;
49+
}
4550
}

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractNormalizerTest.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
1111
use Symfony\Component\Serializer\Tests\Fixtures\AbstractNormalizerDummy;
1212
use Symfony\Component\Serializer\Tests\Fixtures\NullableConstructorArgumentDummy;
13-
use Symfony\Component\Serializer\Tests\Fixtures\ProxyDummy;
1413
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorDummy;
1514
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorNormalizer;
1615

@@ -99,18 +98,6 @@ public function testGetAllowedAttributesAsObjects()
9998
$this->assertEquals([$a3, $a4], $result);
10099
}
101100

102-
public function testObjectToPopulateWithProxy()
103-
{
104-
$proxyDummy = new ProxyDummy();
105-
106-
$context = [AbstractNormalizer::OBJECT_TO_POPULATE => $proxyDummy];
107-
108-
$normalizer = new ObjectNormalizer();
109-
$normalizer->denormalize(['foo' => 'bar'], 'Symfony\Component\Serializer\Tests\Fixtures\ToBeProxyfiedDummy', null, $context);
110-
111-
$this->assertSame('bar', $proxyDummy->getFoo());
112-
}
113-
114101
public function testObjectWithStaticConstructor()
115102
{
116103
$normalizer = new StaticConstructorNormalizer();

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
2424
use Symfony\Component\Serializer\SerializerAwareInterface;
2525
use Symfony\Component\Serializer\SerializerInterface;
26-
use Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateChildDummy;
27-
use Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateParentDummy;
2826

2927
class AbstractObjectNormalizerTest extends TestCase
3028
{
@@ -163,58 +161,6 @@ public function testExtraAttributesException()
163161
'allow_extra_attributes' => false,
164162
]);
165163
}
166-
167-
public function testSkipNullValues()
168-
{
169-
$dummy = new Dummy();
170-
$dummy->bar = 'present';
171-
172-
$normalizer = new ObjectNormalizer();
173-
$result = $normalizer->normalize($dummy, null, [AbstractObjectNormalizer::SKIP_NULL_VALUES => true]);
174-
$this->assertSame(['bar' => 'present'], $result);
175-
}
176-
177-
public function testDeepObjectToPopulate()
178-
{
179-
$child = new DeepObjectPopulateChildDummy();
180-
$child->bar = 'bar-old';
181-
$child->foo = 'foo-old';
182-
183-
$parent = new DeepObjectPopulateParentDummy();
184-
$parent->setChild($child);
185-
186-
$context = [
187-
AbstractObjectNormalizer::OBJECT_TO_POPULATE => $parent,
188-
AbstractObjectNormalizer::DEEP_OBJECT_TO_POPULATE => true,
189-
];
190-
191-
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
192-
$normalizer = new ObjectNormalizer($classMetadataFactory, null, null, new PhpDocExtractor());
193-
194-
$newChild = new DeepObjectPopulateChildDummy();
195-
$newChild->bar = 'bar-new';
196-
$newChild->foo = 'foo-old';
197-
198-
$serializer = $this->getMockBuilder(__NAMESPACE__.'\ObjectSerializerDenormalizer')->getMock();
199-
$serializer
200-
->method('supportsDenormalization')
201-
->with($this->arrayHasKey('bar'),
202-
$this->equalTo(DeepObjectPopulateChildDummy::class),
203-
$this->isNull(),
204-
$this->contains($child))
205-
->willReturn(true);
206-
$serializer->method('denormalize')->willReturn($newChild);
207-
208-
$normalizer->setSerializer($serializer);
209-
$normalizer->denormalize([
210-
'child' => [
211-
'bar' => 'bar-new',
212-
],
213-
], 'Symfony\Component\Serializer\Tests\Fixtures\DeepObjectPopulateParentDummy', null, $context);
214-
215-
$this->assertSame('bar-new', $parent->getChild()->bar);
216-
$this->assertSame('foo-old', $parent->getChild()->foo);
217-
}
218164
}
219165

220166
class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer

0 commit comments

Comments
 (0)