4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Serializer\Tests\Normalizer;
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\MaxDepthDummy;
24 use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
25 use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
27 class PropertyNormalizerTest extends TestCase
30 * @var PropertyNormalizer
34 * @var SerializerInterface
38 protected function setUp()
40 $this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
41 $this->normalizer = new PropertyNormalizer();
42 $this->normalizer->setSerializer($this->serializer);
45 public function testNormalize()
47 $obj = new PropertyDummy();
50 $obj->setCamelCase('camelcase');
52 array('foo' => 'foo', 'bar' => 'bar', 'camelCase' => 'camelcase'),
53 $this->normalizer->normalize($obj, 'any')
57 public function testDenormalize()
59 $obj = $this->normalizer->denormalize(
60 array('foo' => 'foo', 'bar' => 'bar'),
61 __NAMESPACE__.'\PropertyDummy',
64 $this->assertEquals('foo', $obj->foo);
65 $this->assertEquals('bar', $obj->getBar());
68 public function testConstructorDenormalize()
70 $obj = $this->normalizer->denormalize(
71 array('foo' => 'foo', 'bar' => 'bar'),
72 __NAMESPACE__.'\PropertyConstructorDummy',
75 $this->assertEquals('foo', $obj->getFoo());
76 $this->assertEquals('bar', $obj->getBar());
79 public function testConstructorDenormalizeWithNullArgument()
81 $obj = $this->normalizer->denormalize(
82 array('foo' => null, 'bar' => 'bar'),
83 __NAMESPACE__.'\PropertyConstructorDummy', '
86 $this->assertNull($obj->getFoo());
87 $this->assertEquals('bar', $obj->getBar());
91 * @dataProvider provideCallbacks
93 public function testCallbacks($callbacks, $value, $result, $message)
95 $this->normalizer->setCallbacks($callbacks);
97 $obj = new PropertyConstructorDummy('', $value);
101 $this->normalizer->normalize($obj, 'any'),
107 * @expectedException \InvalidArgumentException
109 public function testUncallableCallbacks()
111 $this->normalizer->setCallbacks(array('bar' => null));
113 $obj = new PropertyConstructorDummy('baz', 'quux');
115 $this->normalizer->normalize($obj, 'any');
118 public function testIgnoredAttributes()
120 $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase'));
122 $obj = new PropertyDummy();
128 $this->normalizer->normalize($obj, 'any')
132 public function testGroupsNormalize()
134 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
135 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
136 $this->normalizer->setSerializer($this->serializer);
138 $obj = new GroupDummy();
141 $obj->setFooBar('fooBar');
142 $obj->setSymfony('symfony');
143 $obj->setKevin('kevin');
144 $obj->setCoopTilleuls('coopTilleuls');
146 $this->assertEquals(array(
148 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c'))));
150 // The PropertyNormalizer is not able to hydrate properties from parent classes
151 $this->assertEquals(array(
152 'symfony' => 'symfony',
154 'fooBar' => 'fooBar',
156 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c'))));
159 public function testGroupsDenormalize()
161 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
162 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
163 $this->normalizer->setSerializer($this->serializer);
165 $obj = new GroupDummy();
168 $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
170 $normalized = $this->normalizer->denormalize(
172 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
174 array(PropertyNormalizer::GROUPS => array('a'))
176 $this->assertEquals($obj, $normalized);
180 $normalized = $this->normalizer->denormalize(
182 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
184 array(PropertyNormalizer::GROUPS => array('a', 'b'))
186 $this->assertEquals($obj, $normalized);
189 public function testGroupsNormalizeWithNameConverter()
191 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
192 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
193 $this->normalizer->setSerializer($this->serializer);
195 $obj = new GroupDummy();
196 $obj->setFooBar('@dunglas');
197 $obj->setSymfony('@coopTilleuls');
198 $obj->setCoopTilleuls('les-tilleuls.coop');
203 'foo_bar' => '@dunglas',
204 'symfony' => '@coopTilleuls',
206 $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('name_converter')))
210 public function testGroupsDenormalizeWithNameConverter()
212 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
213 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
214 $this->normalizer->setSerializer($this->serializer);
216 $obj = new GroupDummy();
217 $obj->setFooBar('@dunglas');
218 $obj->setSymfony('@coopTilleuls');
222 $this->normalizer->denormalize(array(
224 'foo_bar' => '@dunglas',
225 'symfony' => '@coopTilleuls',
226 'coop_tilleuls' => 'les-tilleuls.coop',
227 ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(PropertyNormalizer::GROUPS => array('name_converter')))
231 public function provideCallbacks()
236 'bar' => function ($bar) {
241 array('foo' => '', 'bar' => 'baz'),
246 'bar' => function ($bar) {
251 array('foo' => '', 'bar' => null),
256 'bar' => function ($bar) {
257 return $bar->format('d-m-Y H:i:s');
260 new \DateTime('2011-09-10 06:30:00'),
261 array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
266 'bar' => function ($bars) {
268 foreach ($bars as $bar) {
269 $foos .= $bar->getFoo();
275 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
276 array('foo' => '', 'bar' => 'bazquux'),
277 'Collect a property',
281 'bar' => function ($bars) {
285 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
286 array('foo' => '', 'bar' => 2),
293 * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
295 public function testUnableToNormalizeCircularReference()
297 $serializer = new Serializer(array($this->normalizer));
298 $this->normalizer->setSerializer($serializer);
299 $this->normalizer->setCircularReferenceLimit(2);
301 $obj = new PropertyCircularReferenceDummy();
303 $this->normalizer->normalize($obj);
306 public function testSiblingReference()
308 $serializer = new Serializer(array($this->normalizer));
309 $this->normalizer->setSerializer($serializer);
311 $siblingHolder = new PropertySiblingHolder();
314 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
315 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
316 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
318 $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
321 public function testCircularReferenceHandler()
323 $serializer = new Serializer(array($this->normalizer));
324 $this->normalizer->setSerializer($serializer);
325 $this->normalizer->setCircularReferenceHandler(function ($obj) {
326 return get_class($obj);
329 $obj = new PropertyCircularReferenceDummy();
331 $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy');
332 $this->assertEquals($expected, $this->normalizer->normalize($obj));
335 public function testDenormalizeNonExistingAttribute()
339 $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
343 public function testDenormalizeShouldIgnoreStaticProperty()
345 $obj = $this->normalizer->denormalize(array('outOfScope' => true), __NAMESPACE__.'\PropertyDummy');
347 $this->assertEquals(new PropertyDummy(), $obj);
348 $this->assertEquals('out_of_scope', PropertyDummy::$outOfScope);
352 * @expectedException \Symfony\Component\Serializer\Exception\LogicException
353 * @expectedExceptionMessage Cannot normalize attribute "bar" because the injected serializer is not a normalizer
355 public function testUnableToNormalizeObjectAttribute()
357 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
358 $this->normalizer->setSerializer($serializer);
360 $obj = new PropertyDummy();
361 $object = new \stdClass();
362 $obj->setBar($object);
364 $this->normalizer->normalize($obj, 'any');
367 public function testNoTraversableSupport()
369 $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
372 public function testNoStaticPropertySupport()
374 $this->assertFalse($this->normalizer->supportsNormalization(new StaticPropertyDummy()));
377 public function testMaxDepth()
379 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
380 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
381 $serializer = new Serializer(array($this->normalizer));
382 $this->normalizer->setSerializer($serializer);
384 $level1 = new MaxDepthDummy();
385 $level1->foo = 'level1';
387 $level2 = new MaxDepthDummy();
388 $level2->foo = 'level2';
389 $level1->child = $level2;
391 $level3 = new MaxDepthDummy();
392 $level3->foo = 'level3';
393 $level2->child = $level3;
395 $result = $serializer->normalize($level1, null, array(PropertyNormalizer::ENABLE_MAX_DEPTH => true));
410 $this->assertEquals($expected, $result);
416 public static $outOfScope = 'out_of_scope';
419 protected $camelCase;
421 public function getBar()
426 public function setBar($bar)
431 public function getCamelCase()
433 return $this->camelCase;
436 public function setCamelCase($camelCase)
438 $this->camelCase = $camelCase;
442 class PropertyConstructorDummy
447 public function __construct($foo, $bar)
453 public function getFoo()
458 public function getBar()
464 class PropertyCamelizedDummy
466 private $kevinDunglas;
470 public function __construct($kevinDunglas = null)
472 $this->kevinDunglas = $kevinDunglas;
476 class StaticPropertyDummy
478 private static $property = 'value';