This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php

624 lines
18 KiB
PHP
Raw Normal View History

<?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\Tests\Normalizer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
{
/**
* @var ObjectNormalizerTest
*/
private $normalizer;
/**
* @var SerializerInterface
*/
private $serializer;
protected function setUp()
{
$this->serializer = $this->getMock(__NAMESPACE__.'\ObjectSerializerNormalizer');
$this->normalizer = new ObjectNormalizer();
$this->normalizer->setSerializer($this->serializer);
}
public function testNormalize()
{
$obj = new ObjectDummy();
$object = new \stdClass();
$obj->setFoo('foo');
$obj->bar = 'bar';
$obj->setBaz(true);
$obj->setCamelCase('camelcase');
$obj->setObject($object);
$this->serializer
->expects($this->once())
->method('normalize')
->with($object, 'any')
->will($this->returnValue('string_object'))
;
$this->assertEquals(
array(
'foo' => 'foo',
'bar' => 'bar',
'baz' => true,
'fooBar' => 'foobar',
'camelCase' => 'camelcase',
'object' => 'string_object',
),
$this->normalizer->normalize($obj, 'any')
);
}
public function testDenormalize()
{
$obj = $this->normalizer->denormalize(
array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
__NAMESPACE__.'\ObjectDummy',
'any'
);
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->bar);
$this->assertTrue($obj->isBaz());
}
public function testDenormalizeWithObject()
{
$data = new \stdClass();
$data->foo = 'foo';
$data->bar = 'bar';
$data->fooBar = 'foobar';
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->bar);
}
2015-03-13 17:49:40 +00:00
/**
* @group legacy
*/
public function testLegacyDenormalizeOnCamelCaseFormat()
{
$this->normalizer->setCamelizedAttributes(array('camel_case'));
$obj = $this->normalizer->denormalize(
array('camel_case' => 'camelCase'),
__NAMESPACE__.'\ObjectDummy'
);
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testNameConverterSupport()
{
$this->normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
$obj = $this->normalizer->denormalize(
array('camel_case' => 'camelCase'),
__NAMESPACE__.'\ObjectDummy'
);
$this->assertEquals('camelCase', $obj->getCamelCase());
}
public function testDenormalizeNull()
{
$this->assertEquals(new ObjectDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\ObjectDummy'));
}
public function testConstructorDenormalize()
{
$obj = $this->normalizer->denormalize(
array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
__NAMESPACE__.'\ObjectConstructorDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->bar);
$this->assertTrue($obj->isBaz());
}
public function testConstructorDenormalizeWithNullArgument()
{
$obj = $this->normalizer->denormalize(
array('foo' => 'foo', 'bar' => null, 'baz' => true),
__NAMESPACE__.'\ObjectConstructorDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertNull($obj->bar);
$this->assertTrue($obj->isBaz());
}
public function testConstructorDenormalizeWithMissingOptionalArgument()
{
$obj = $this->normalizer->denormalize(
array('foo' => 'test', 'baz' => array(1, 2, 3)),
__NAMESPACE__.'\ObjectConstructorOptionalArgsDummy', 'any');
$this->assertEquals('test', $obj->getFoo());
$this->assertEquals(array(), $obj->bar);
$this->assertEquals(array(1, 2, 3), $obj->getBaz());
}
/**
* @see https://bugs.php.net/62715
*
* @requires PHP 5.3.17
*/
public function testConstructorDenormalizeWithOptionalDefaultArgument()
{
$obj = $this->normalizer->denormalize(
array('bar' => 'test'),
__NAMESPACE__.'\ObjectConstructorArgsWithDefaultValueDummy', 'any');
$this->assertEquals(array(), $obj->getFoo());
$this->assertEquals('test', $obj->getBar());
}
public function testConstructorWithObjectDenormalize()
{
$data = new \stdClass();
$data->foo = 'foo';
$data->bar = 'bar';
$data->baz = true;
$data->fooBar = 'foobar';
$obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\ObjectConstructorDummy', 'any');
$this->assertEquals('foo', $obj->getFoo());
$this->assertEquals('bar', $obj->bar);
}
public function testGroupsNormalize()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory);
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFoo('foo');
$obj->setBar('bar');
$obj->setFooBar('fooBar');
$obj->setSymfony('symfony');
$obj->setKevin('kevin');
$obj->setCoopTilleuls('coopTilleuls');
$this->assertEquals(array(
'bar' => 'bar',
), $this->normalizer->normalize($obj, null, array('groups' => array('c'))));
$this->assertEquals(array(
'symfony' => 'symfony',
'foo' => 'foo',
'fooBar' => 'fooBar',
'bar' => 'bar',
'kevin' => 'kevin',
'coopTilleuls' => 'coopTilleuls',
), $this->normalizer->normalize($obj, null, array('groups' => array('a', 'c'))));
}
public function testGroupsDenormalize()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory);
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFoo('foo');
$toNormalize = array('foo' => 'foo', 'bar' => 'bar');
$normalized = $this->normalizer->denormalize(
$toNormalize,
'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
null,
array('groups' => array('a'))
);
$this->assertEquals($obj, $normalized);
$obj->setBar('bar');
$normalized = $this->normalizer->denormalize(
$toNormalize,
'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
null,
array('groups' => array('a', 'b'))
);
$this->assertEquals($obj, $normalized);
}
public function testGroupsNormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$obj->setCoopTilleuls('les-tilleuls.coop');
$this->assertEquals(
array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
),
$this->normalizer->normalize($obj, null, array('groups' => array('name_converter')))
);
}
public function testGroupsDenormalizeWithNameConverter()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
$this->normalizer->setSerializer($this->serializer);
$obj = new GroupDummy();
$obj->setFooBar('@dunglas');
$obj->setSymfony('@coopTilleuls');
$this->assertEquals(
$obj,
$this->normalizer->denormalize(array(
'bar' => null,
'foo_bar' => '@dunglas',
'symfony' => '@coopTilleuls',
'coop_tilleuls' => 'les-tilleuls.coop',
), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array('groups' => array('name_converter')))
);
}
/**
* @dataProvider provideCallbacks
*/
public function testCallbacks($callbacks, $value, $result, $message)
{
$this->normalizer->setCallbacks($callbacks);
$obj = new ObjectConstructorDummy('', $value, true);
$this->assertEquals(
$result,
$this->normalizer->normalize($obj, 'any'),
$message
);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testUncallableCallbacks()
{
$this->normalizer->setCallbacks(array('bar' => null));
$obj = new ObjectConstructorDummy('baz', 'quux', true);
$this->normalizer->normalize($obj, 'any');
}
public function testIgnoredAttributes()
{
$this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'baz', 'camelCase', 'object'));
$obj = new ObjectDummy();
$obj->setFoo('foo');
$obj->bar = 'bar';
$obj->setBaz(true);
$this->assertEquals(
array('fooBar' => 'foobar'),
$this->normalizer->normalize($obj, 'any')
);
}
public function provideCallbacks()
{
return array(
array(
array(
'bar' => function ($bar) {
return 'baz';
},
),
'baz',
array('foo' => '', 'bar' => 'baz', 'baz' => true),
'Change a string',
),
array(
array(
'bar' => function ($bar) {
return;
},
),
'baz',
array('foo' => '', 'bar' => null, 'baz' => true),
'Null an item',
),
array(
array(
'bar' => function ($bar) {
return $bar->format('d-m-Y H:i:s');
},
),
new \DateTime('2011-09-10 06:30:00'),
array('foo' => '', 'bar' => '10-09-2011 06:30:00', 'baz' => true),
'Format a date',
),
array(
array(
'bar' => function ($bars) {
$foos = '';
foreach ($bars as $bar) {
$foos .= $bar->getFoo();
}
return $foos;
},
),
array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
array('foo' => '', 'bar' => 'bazquux', 'baz' => true),
'Collect a property',
),
array(
array(
'bar' => function ($bars) {
return count($bars);
},
),
array(new ObjectConstructorDummy('baz', '', false), new ObjectConstructorDummy('quux', '', false)),
array('foo' => '', 'bar' => 2, 'baz' => true),
'Count a property',
),
);
}
/**
* @expectedException \Symfony\Component\Serializer\Exception\LogicException
* @expectedExceptionMessage Cannot normalize attribute "object" because injected serializer is not a normalizer
*/
public function testUnableToNormalizeObjectAttribute()
{
$serializer = $this->getMock('Symfony\Component\Serializer\SerializerInterface');
$this->normalizer->setSerializer($serializer);
$obj = new ObjectDummy();
$object = new \stdClass();
$obj->setObject($object);
$this->normalizer->normalize($obj, 'any');
}
/**
* @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
*/
public function testUnableToNormalizeCircularReference()
{
$serializer = new Serializer(array($this->normalizer));
$this->normalizer->setSerializer($serializer);
$this->normalizer->setCircularReferenceLimit(2);
$obj = new CircularReferenceDummy();
$this->normalizer->normalize($obj);
}
public function testSiblingReference()
{
$serializer = new Serializer(array($this->normalizer));
$this->normalizer->setSerializer($serializer);
$siblingHolder = new SiblingHolder();
$expected = array(
'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
);
$this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
}
public function testCircularReferenceHandler()
{
$serializer = new Serializer(array($this->normalizer));
$this->normalizer->setSerializer($serializer);
$this->normalizer->setCircularReferenceHandler(function ($obj) {
return get_class($obj);
});
$obj = new CircularReferenceDummy();
$expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy');
$this->assertEquals($expected, $this->normalizer->normalize($obj));
}
public function testDenormalizeNonExistingAttribute()
{
$this->assertEquals(
new ObjectDummy(),
$this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\ObjectDummy')
);
}
public function testNoTraversableSupport()
{
$this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
}
public function testNormalizeStatic()
{
$this->assertEquals(array('foo' => 'K'), $this->normalizer->normalize(new ObjectWithStaticPropertiesAndMethods()));
}
}
class ObjectDummy
{
protected $foo;
public $bar;
private $baz;
protected $camelCase;
protected $object;
public function getFoo()
{
return $this->foo;
}
public function setFoo($foo)
{
$this->foo = $foo;
}
public function isBaz()
{
return $this->baz;
}
public function setBaz($baz)
{
$this->baz = $baz;
}
public function getFooBar()
{
return $this->foo.$this->bar;
}
public function getCamelCase()
{
return $this->camelCase;
}
public function setCamelCase($camelCase)
{
$this->camelCase = $camelCase;
}
public function otherMethod()
{
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
public function setObject($object)
{
$this->object = $object;
}
public function getObject()
{
return $this->object;
}
}
class ObjectConstructorDummy
{
protected $foo;
public $bar;
private $baz;
public function __construct($foo, $bar, $baz)
{
$this->foo = $foo;
$this->bar = $bar;
$this->baz = $baz;
}
public function getFoo()
{
return $this->foo;
}
public function isBaz()
{
return $this->baz;
}
public function otherMethod()
{
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
}
abstract class ObjectSerializerNormalizer implements SerializerInterface, NormalizerInterface
{
}
class ObjectConstructorOptionalArgsDummy
{
protected $foo;
public $bar;
private $baz;
public function __construct($foo, $bar = array(), $baz = array())
{
$this->foo = $foo;
$this->bar = $bar;
$this->baz = $baz;
}
public function getFoo()
{
return $this->foo;
}
public function getBaz()
{
return $this->baz;
}
public function otherMethod()
{
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
}
class ObjectConstructorArgsWithDefaultValueDummy
{
protected $foo;
protected $bar;
public function __construct($foo = array(), $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}
public function getFoo()
{
return $this->foo;
}
public function getBar()
{
return $this->bar;
}
public function otherMethod()
{
throw new \RuntimeException('Dummy::otherMethod() should not be called');
}
}
class ObjectWithStaticPropertiesAndMethods
{
public $foo = 'K';
public static $bar = 'A';
public static function getBaz()
{
return 'L';
}
}