2015-08-17 17:00:26 -07:00
< ? 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 );
}
/**
* @ 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 ());
}
public function testConstructorDenormalizeWithOptionalDefaultArgument ()
{
2015-10-08 11:40:12 -07:00
if ( PHP_VERSION_ID <= 50316 ) {
$this -> markTestSkipped ( 'See https://bugs.php.net/62715' );
}
2015-08-17 17:00:26 -07:00
$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 ()));
}
}
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' );
}
}