Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / serializer / Tests / Normalizer / PropertyNormalizerTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Serializer\Tests\Normalizer;
13
14 use Doctrine\Common\Annotations\AnnotationReader;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
17 use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
18 use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
19 use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
20 use Symfony\Component\Serializer\Serializer;
21 use Symfony\Component\Serializer\SerializerInterface;
22 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
23 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyChild;
24 use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
25 use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
26 use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
27
28 class PropertyNormalizerTest extends TestCase
29 {
30     /**
31      * @var PropertyNormalizer
32      */
33     private $normalizer;
34     /**
35      * @var SerializerInterface
36      */
37     private $serializer;
38
39     protected function setUp()
40     {
41         $this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
42         $this->normalizer = new PropertyNormalizer();
43         $this->normalizer->setSerializer($this->serializer);
44     }
45
46     public function testNormalize()
47     {
48         $obj = new PropertyDummy();
49         $obj->foo = 'foo';
50         $obj->setBar('bar');
51         $obj->setCamelCase('camelcase');
52         $this->assertEquals(
53             array('foo' => 'foo', 'bar' => 'bar', 'camelCase' => 'camelcase'),
54             $this->normalizer->normalize($obj, 'any')
55         );
56     }
57
58     public function testDenormalize()
59     {
60         $obj = $this->normalizer->denormalize(
61             array('foo' => 'foo', 'bar' => 'bar'),
62             __NAMESPACE__.'\PropertyDummy',
63             'any'
64         );
65         $this->assertEquals('foo', $obj->foo);
66         $this->assertEquals('bar', $obj->getBar());
67     }
68
69     public function testNormalizeWithParentClass()
70     {
71         $group = new GroupDummyChild();
72         $group->setBaz('baz');
73         $group->setFoo('foo');
74         $group->setBar('bar');
75         $group->setKevin('Kevin');
76         $group->setCoopTilleuls('coop');
77         $this->assertEquals(
78             array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin',
79                   'coopTilleuls' => 'coop', 'fooBar' => null, 'symfony' => null, 'baz' => 'baz', ),
80             $this->normalizer->normalize($group, 'any')
81         );
82     }
83
84     public function testDenormalizeWithParentClass()
85     {
86         $obj = $this->normalizer->denormalize(
87             array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', 'baz' => 'baz'),
88             GroupDummyChild::class,
89             'any'
90         );
91         $this->assertEquals('foo', $obj->getFoo());
92         $this->assertEquals('bar', $obj->getBar());
93         $this->assertEquals('Kevin', $obj->getKevin());
94         $this->assertEquals('baz', $obj->getBaz());
95         $this->assertNull($obj->getSymfony());
96     }
97
98     public function testConstructorDenormalize()
99     {
100         $obj = $this->normalizer->denormalize(
101             array('foo' => 'foo', 'bar' => 'bar'),
102             __NAMESPACE__.'\PropertyConstructorDummy',
103             'any'
104         );
105         $this->assertEquals('foo', $obj->getFoo());
106         $this->assertEquals('bar', $obj->getBar());
107     }
108
109     public function testConstructorDenormalizeWithNullArgument()
110     {
111         $obj = $this->normalizer->denormalize(
112             array('foo' => null, 'bar' => 'bar'),
113             __NAMESPACE__.'\PropertyConstructorDummy', '
114             any'
115         );
116         $this->assertNull($obj->getFoo());
117         $this->assertEquals('bar', $obj->getBar());
118     }
119
120     /**
121      * @dataProvider provideCallbacks
122      */
123     public function testCallbacks($callbacks, $value, $result, $message)
124     {
125         $this->normalizer->setCallbacks($callbacks);
126
127         $obj = new PropertyConstructorDummy('', $value);
128
129         $this->assertEquals(
130             $result,
131             $this->normalizer->normalize($obj, 'any'),
132             $message
133         );
134     }
135
136     /**
137      * @expectedException \InvalidArgumentException
138      */
139     public function testUncallableCallbacks()
140     {
141         $this->normalizer->setCallbacks(array('bar' => null));
142
143         $obj = new PropertyConstructorDummy('baz', 'quux');
144
145         $this->normalizer->normalize($obj, 'any');
146     }
147
148     public function testIgnoredAttributes()
149     {
150         $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase'));
151
152         $obj = new PropertyDummy();
153         $obj->foo = 'foo';
154         $obj->setBar('bar');
155
156         $this->assertEquals(
157             array(),
158             $this->normalizer->normalize($obj, 'any')
159         );
160     }
161
162     public function testGroupsNormalize()
163     {
164         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
165         $this->normalizer = new PropertyNormalizer($classMetadataFactory);
166         $this->normalizer->setSerializer($this->serializer);
167
168         $obj = new GroupDummy();
169         $obj->setFoo('foo');
170         $obj->setBar('bar');
171         $obj->setFooBar('fooBar');
172         $obj->setSymfony('symfony');
173         $obj->setKevin('kevin');
174         $obj->setCoopTilleuls('coopTilleuls');
175
176         $this->assertEquals(array(
177             'bar' => 'bar',
178         ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c'))));
179
180         // The PropertyNormalizer is also able to hydrate properties from parent classes
181         $this->assertEquals(array(
182             'symfony' => 'symfony',
183             'foo' => 'foo',
184             'fooBar' => 'fooBar',
185             'bar' => 'bar',
186             'kevin' => 'kevin',
187             'coopTilleuls' => 'coopTilleuls',
188         ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c'))));
189     }
190
191     public function testGroupsDenormalize()
192     {
193         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
194         $this->normalizer = new PropertyNormalizer($classMetadataFactory);
195         $this->normalizer->setSerializer($this->serializer);
196
197         $obj = new GroupDummy();
198         $obj->setFoo('foo');
199
200         $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
201
202         $normalized = $this->normalizer->denormalize(
203             $toNormalize,
204             'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
205             null,
206             array(PropertyNormalizer::GROUPS => array('a'))
207         );
208         $this->assertEquals($obj, $normalized);
209
210         $obj->setBar('bar');
211
212         $normalized = $this->normalizer->denormalize(
213             $toNormalize,
214             'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
215             null,
216             array(PropertyNormalizer::GROUPS => array('a', 'b'))
217         );
218         $this->assertEquals($obj, $normalized);
219     }
220
221     public function testGroupsNormalizeWithNameConverter()
222     {
223         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
224         $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
225         $this->normalizer->setSerializer($this->serializer);
226
227         $obj = new GroupDummy();
228         $obj->setFooBar('@dunglas');
229         $obj->setSymfony('@coopTilleuls');
230         $obj->setCoopTilleuls('les-tilleuls.coop');
231
232         $this->assertEquals(
233             array(
234                 'bar' => null,
235                 'foo_bar' => '@dunglas',
236                 'symfony' => '@coopTilleuls',
237             ),
238             $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('name_converter')))
239         );
240     }
241
242     public function testGroupsDenormalizeWithNameConverter()
243     {
244         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
245         $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
246         $this->normalizer->setSerializer($this->serializer);
247
248         $obj = new GroupDummy();
249         $obj->setFooBar('@dunglas');
250         $obj->setSymfony('@coopTilleuls');
251
252         $this->assertEquals(
253             $obj,
254             $this->normalizer->denormalize(array(
255                 'bar' => null,
256                 'foo_bar' => '@dunglas',
257                 'symfony' => '@coopTilleuls',
258                 'coop_tilleuls' => 'les-tilleuls.coop',
259             ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(PropertyNormalizer::GROUPS => array('name_converter')))
260         );
261     }
262
263     public function provideCallbacks()
264     {
265         return array(
266             array(
267                 array(
268                     'bar' => function ($bar) {
269                         return 'baz';
270                     },
271                 ),
272                 'baz',
273                 array('foo' => '', 'bar' => 'baz'),
274                 'Change a string',
275             ),
276             array(
277                 array(
278                     'bar' => function ($bar) {
279                         return;
280                     },
281                 ),
282                 'baz',
283                 array('foo' => '', 'bar' => null),
284                 'Null an item',
285             ),
286             array(
287                 array(
288                     'bar' => function ($bar) {
289                         return $bar->format('d-m-Y H:i:s');
290                     },
291                 ),
292                 new \DateTime('2011-09-10 06:30:00'),
293                 array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
294                 'Format a date',
295             ),
296             array(
297                 array(
298                     'bar' => function ($bars) {
299                         $foos = '';
300                         foreach ($bars as $bar) {
301                             $foos .= $bar->getFoo();
302                         }
303
304                         return $foos;
305                     },
306                 ),
307                 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
308                 array('foo' => '', 'bar' => 'bazquux'),
309                 'Collect a property',
310             ),
311             array(
312                 array(
313                     'bar' => function ($bars) {
314                         return count($bars);
315                     },
316                 ),
317                 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
318                 array('foo' => '', 'bar' => 2),
319                 'Count a property',
320             ),
321         );
322     }
323
324     /**
325      * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
326      */
327     public function testUnableToNormalizeCircularReference()
328     {
329         $serializer = new Serializer(array($this->normalizer));
330         $this->normalizer->setSerializer($serializer);
331         $this->normalizer->setCircularReferenceLimit(2);
332
333         $obj = new PropertyCircularReferenceDummy();
334
335         $this->normalizer->normalize($obj);
336     }
337
338     public function testSiblingReference()
339     {
340         $serializer = new Serializer(array($this->normalizer));
341         $this->normalizer->setSerializer($serializer);
342
343         $siblingHolder = new PropertySiblingHolder();
344
345         $expected = array(
346             'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
347             'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
348             'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
349         );
350         $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
351     }
352
353     public function testCircularReferenceHandler()
354     {
355         $serializer = new Serializer(array($this->normalizer));
356         $this->normalizer->setSerializer($serializer);
357         $this->normalizer->setCircularReferenceHandler(function ($obj) {
358             return get_class($obj);
359         });
360
361         $obj = new PropertyCircularReferenceDummy();
362
363         $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy');
364         $this->assertEquals($expected, $this->normalizer->normalize($obj));
365     }
366
367     public function testDenormalizeNonExistingAttribute()
368     {
369         $this->assertEquals(
370             new PropertyDummy(),
371             $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
372         );
373     }
374
375     public function testDenormalizeShouldIgnoreStaticProperty()
376     {
377         $obj = $this->normalizer->denormalize(array('outOfScope' => true), __NAMESPACE__.'\PropertyDummy');
378
379         $this->assertEquals(new PropertyDummy(), $obj);
380         $this->assertEquals('out_of_scope', PropertyDummy::$outOfScope);
381     }
382
383     /**
384      * @expectedException \Symfony\Component\Serializer\Exception\LogicException
385      * @expectedExceptionMessage Cannot normalize attribute "bar" because the injected serializer is not a normalizer
386      */
387     public function testUnableToNormalizeObjectAttribute()
388     {
389         $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
390         $this->normalizer->setSerializer($serializer);
391
392         $obj = new PropertyDummy();
393         $object = new \stdClass();
394         $obj->setBar($object);
395
396         $this->normalizer->normalize($obj, 'any');
397     }
398
399     public function testNoTraversableSupport()
400     {
401         $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
402     }
403
404     public function testNoStaticPropertySupport()
405     {
406         $this->assertFalse($this->normalizer->supportsNormalization(new StaticPropertyDummy()));
407     }
408
409     public function testMaxDepth()
410     {
411         $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
412         $this->normalizer = new PropertyNormalizer($classMetadataFactory);
413         $serializer = new Serializer(array($this->normalizer));
414         $this->normalizer->setSerializer($serializer);
415
416         $level1 = new MaxDepthDummy();
417         $level1->foo = 'level1';
418
419         $level2 = new MaxDepthDummy();
420         $level2->foo = 'level2';
421         $level1->child = $level2;
422
423         $level3 = new MaxDepthDummy();
424         $level3->foo = 'level3';
425         $level2->child = $level3;
426
427         $result = $serializer->normalize($level1, null, array(PropertyNormalizer::ENABLE_MAX_DEPTH => true));
428
429         $expected = array(
430             'foo' => 'level1',
431             'child' => array(
432                     'foo' => 'level2',
433                     'child' => array(
434                             'child' => null,
435                             'bar' => null,
436                         ),
437                     'bar' => null,
438                 ),
439             'bar' => null,
440         );
441
442         $this->assertEquals($expected, $result);
443     }
444
445     public function testInheritedPropertiesSupport()
446     {
447         $this->assertTrue($this->normalizer->supportsNormalization(new PropertyChildDummy()));
448     }
449 }
450
451 class PropertyDummy
452 {
453     public static $outOfScope = 'out_of_scope';
454     public $foo;
455     private $bar;
456     protected $camelCase;
457
458     public function getBar()
459     {
460         return $this->bar;
461     }
462
463     public function setBar($bar)
464     {
465         $this->bar = $bar;
466     }
467
468     public function getCamelCase()
469     {
470         return $this->camelCase;
471     }
472
473     public function setCamelCase($camelCase)
474     {
475         $this->camelCase = $camelCase;
476     }
477 }
478
479 class PropertyConstructorDummy
480 {
481     protected $foo;
482     private $bar;
483
484     public function __construct($foo, $bar)
485     {
486         $this->foo = $foo;
487         $this->bar = $bar;
488     }
489
490     public function getFoo()
491     {
492         return $this->foo;
493     }
494
495     public function getBar()
496     {
497         return $this->bar;
498     }
499 }
500
501 class PropertyCamelizedDummy
502 {
503     private $kevinDunglas;
504     public $fooBar;
505     public $bar_foo;
506
507     public function __construct($kevinDunglas = null)
508     {
509         $this->kevinDunglas = $kevinDunglas;
510     }
511 }
512
513 class StaticPropertyDummy
514 {
515     private static $property = 'value';
516 }
517
518 class PropertyParentDummy
519 {
520     private $foo = 'bar';
521 }
522
523 class PropertyChildDummy extends PropertyParentDummy
524 {
525 }