2011-01-18 19:17:24 +00:00
< ? php
2012-04-02 04:52:14 +01:00
/*
* 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 .
*/
2011-01-18 19:17:24 +00:00
namespace Symfony\Component\Serializer ;
2012-07-14 09:46:16 +01:00
use Symfony\Component\Serializer\Encoder\ChainDecoder ;
use Symfony\Component\Serializer\Encoder\ChainEncoder ;
2011-01-18 19:17:24 +00:00
use Symfony\Component\Serializer\Encoder\EncoderInterface ;
2011-05-08 16:49:19 +01:00
use Symfony\Component\Serializer\Encoder\DecoderInterface ;
2016-01-26 12:57:16 +00:00
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface ;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface ;
2011-11-08 20:04:30 +00:00
use Symfony\Component\Serializer\Normalizer\NormalizerInterface ;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface ;
2011-05-29 09:55:08 +01:00
use Symfony\Component\Serializer\Exception\LogicException ;
use Symfony\Component\Serializer\Exception\UnexpectedValueException ;
2011-01-18 19:17:24 +00:00
/**
2014-10-02 18:46:25 +01:00
* Serializer serializes and deserializes data .
2011-01-18 19:17:24 +00:00
*
2014-10-02 18:46:25 +01:00
* objects are turned into arrays by normalizers .
* arrays are turned into various output formats by encoders .
2011-01-18 19:17:24 +00:00
*
* $serializer -> serialize ( $obj , 'xml' )
* $serializer -> decode ( $data , 'xml' )
2011-05-29 09:55:54 +01:00
* $serializer -> denormalize ( $data , 'Class' , 'xml' )
2011-01-18 19:17:24 +00:00
*
* @ author Jordi Boggiano < j . boggiano @ seld . be >
2011-05-29 09:55:54 +01:00
* @ author Johannes M . Schmitt < schmittjoh @ gmail . com >
* @ author Lukas Kahwe Smith < smith @ pooteeweet . org >
2015-01-23 09:46:35 +00:00
* @ author Kévin Dunglas < dunglas @ gmail . com >
2011-01-18 19:17:24 +00:00
*/
2011-11-08 20:04:30 +00:00
class Serializer implements SerializerInterface , NormalizerInterface , DenormalizerInterface , EncoderInterface , DecoderInterface
2011-01-18 19:17:24 +00:00
{
2014-10-02 18:46:25 +01:00
/**
* @ var Encoder\ChainEncoder
*/
2012-07-14 09:46:16 +01:00
protected $encoder ;
2016-01-18 21:15:26 +00:00
2014-10-02 18:46:25 +01:00
/**
* @ var Encoder\ChainDecoder
*/
2012-07-14 09:46:16 +01:00
protected $decoder ;
2016-01-18 21:15:26 +00:00
2014-10-02 18:46:25 +01:00
/**
* @ var array
*/
2014-10-22 19:27:13 +01:00
protected $normalizers = array ();
2016-01-18 21:15:26 +00:00
2014-10-02 18:46:25 +01:00
/**
* @ var array
2016-04-18 20:23:24 +01:00
*
* @ deprecated since 3.1 will be removed in 4.0
2014-10-02 18:46:25 +01:00
*/
2014-10-22 19:27:13 +01:00
protected $normalizerCache = array ();
2016-01-18 21:15:26 +00:00
2014-10-02 18:46:25 +01:00
/**
* @ var array
2016-04-18 20:23:24 +01:00
*
* @ deprecated since 3.1 will be removed in 4.0
2014-10-02 18:46:25 +01:00
*/
2011-05-06 18:36:56 +01:00
protected $denormalizerCache = array ();
2011-01-18 19:17:24 +00:00
2012-07-17 18:53:41 +01:00
public function __construct ( array $normalizers = array (), array $encoders = array ())
2011-05-29 09:55:54 +01:00
{
foreach ( $normalizers as $normalizer ) {
if ( $normalizer instanceof SerializerAwareInterface ) {
$normalizer -> setSerializer ( $this );
}
2016-01-26 12:57:16 +00:00
if ( $normalizer instanceof DenormalizerAwareInterface ) {
$normalizer -> setDenormalizer ( $this );
}
if ( $normalizer instanceof NormalizerAwareInterface ) {
$normalizer -> setNormalizer ( $this );
}
2011-05-29 09:55:54 +01:00
}
$this -> normalizers = $normalizers ;
2012-07-14 09:46:16 +01:00
$decoders = array ();
$realEncoders = array ();
2011-05-29 09:55:54 +01:00
foreach ( $encoders as $encoder ) {
if ( $encoder instanceof SerializerAwareInterface ) {
$encoder -> setSerializer ( $this );
}
2012-07-14 09:46:16 +01:00
if ( $encoder instanceof DecoderInterface ) {
$decoders [] = $encoder ;
}
if ( $encoder instanceof EncoderInterface ) {
$realEncoders [] = $encoder ;
}
2011-05-29 09:55:54 +01:00
}
2012-07-14 09:46:16 +01:00
$this -> encoder = new ChainEncoder ( $realEncoders );
$this -> decoder = new ChainDecoder ( $decoders );
2011-05-29 09:55:54 +01:00
}
2011-01-18 19:17:24 +00:00
/**
* { @ inheritdoc }
*/
2012-08-06 14:52:32 +01:00
final public function serialize ( $data , $format , array $context = array ())
2011-01-18 19:17:24 +00:00
{
2011-12-14 17:10:48 +00:00
if ( ! $this -> supportsEncoding ( $format )) {
2013-04-10 11:24:37 +01:00
throw new UnexpectedValueException ( sprintf ( 'Serialization for the format %s is not supported' , $format ));
2011-05-08 17:16:53 +01:00
}
2011-06-09 13:18:47 +01:00
2012-07-14 10:05:55 +01:00
if ( $this -> encoder -> needsNormalization ( $format )) {
2013-01-18 13:08:59 +00:00
$data = $this -> normalize ( $data , $format , $context );
2011-05-08 17:16:53 +01:00
}
2011-06-08 11:12:55 +01:00
2013-01-18 13:08:59 +00:00
return $this -> encode ( $data , $format , $context );
2011-05-06 12:01:19 +01:00
}
/**
2011-05-29 09:57:30 +01:00
* { @ inheritdoc }
2011-05-06 12:01:19 +01:00
*/
2012-08-06 14:52:32 +01:00
final public function deserialize ( $data , $type , $format , array $context = array ())
2011-06-09 12:55:54 +01:00
{
2011-12-14 17:10:48 +00:00
if ( ! $this -> supportsDecoding ( $format )) {
2013-04-10 11:24:37 +01:00
throw new UnexpectedValueException ( sprintf ( 'Deserialization for the format %s is not supported' , $format ));
2011-06-09 13:18:47 +01:00
}
2013-01-18 13:08:59 +00:00
$data = $this -> decode ( $data , $format , $context );
2011-06-09 12:55:54 +01:00
2013-01-18 13:08:59 +00:00
return $this -> denormalize ( $data , $type , $format , $context );
2011-01-18 19:17:24 +00:00
}
/**
* { @ inheritdoc }
*/
2013-01-18 13:08:59 +00:00
public function normalize ( $data , $format = null , array $context = array ())
2011-01-18 19:17:24 +00:00
{
2015-01-23 09:46:35 +00:00
// If a normalizer supports the given data, use it
2016-07-16 17:39:49 +01:00
if ( $normalizer = $this -> getNormalizer ( $data , $format , $context )) {
2015-01-23 09:46:35 +00:00
return $normalizer -> normalize ( $data , $format , $context );
}
2011-05-09 12:59:54 +01:00
if ( null === $data || is_scalar ( $data )) {
2011-05-06 12:01:19 +01:00
return $data ;
}
2016-01-06 21:10:50 +00:00
if ( is_array ( $data ) || $data instanceof \Traversable ) {
2011-05-06 18:04:39 +01:00
$normalized = array ();
foreach ( $data as $key => $val ) {
2013-01-18 13:08:59 +00:00
$normalized [ $key ] = $this -> normalize ( $val , $format , $context );
2011-05-06 18:04:39 +01:00
}
2011-06-08 11:12:55 +01:00
2011-05-06 18:04:39 +01:00
return $normalized ;
}
2016-01-06 21:10:50 +00:00
2011-01-18 19:17:24 +00:00
if ( is_object ( $data )) {
2016-01-06 21:10:50 +00:00
if ( ! $this -> normalizers ) {
throw new LogicException ( 'You must register at least one normalizer to be able to normalize objects.' );
2011-05-06 18:36:56 +01:00
}
2011-06-08 11:12:55 +01:00
2016-01-06 21:10:50 +00:00
throw new UnexpectedValueException ( sprintf ( 'Could not normalize object of type %s, no supporting normalizer found.' , get_class ( $data )));
2011-05-06 18:36:56 +01:00
}
2016-01-06 21:10:50 +00:00
2013-04-10 11:24:37 +01:00
throw new UnexpectedValueException ( sprintf ( 'An unexpected value could not be normalized: %s' , var_export ( $data , true )));
2011-01-18 19:17:24 +00:00
}
2011-05-06 12:01:19 +01:00
/**
2011-05-29 09:57:30 +01:00
* { @ inheritdoc }
2011-05-06 12:01:19 +01:00
*/
2013-01-18 13:08:59 +00:00
public function denormalize ( $data , $type , $format = null , array $context = array ())
2011-05-06 12:01:19 +01:00
{
2013-01-18 13:08:59 +00:00
return $this -> denormalizeObject ( $data , $type , $format , $context );
2011-05-06 12:01:19 +01:00
}
2011-11-08 20:54:41 +00:00
/**
* { @ inheritdoc }
*/
2016-07-16 17:39:49 +01:00
public function supportsNormalization ( $data , $format = null /*, array $context = array()*/ )
2011-11-08 20:54:41 +00:00
{
2016-07-16 17:39:49 +01:00
if ( func_num_args () > 2 ) {
$context = func_get_arg ( 2 );
} else {
if ( __CLASS__ !== get_class ( $this )) {
$r = new \ReflectionMethod ( $this , __FUNCTION__ );
if ( __CLASS__ !== $r -> getDeclaringClass () -> getName ()) {
2017-02-28 14:54:44 +00:00
@ trigger_error ( sprintf ( 'Method %s() will have a third `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
2016-07-16 17:39:49 +01:00
}
}
$context = array ();
}
return null !== $this -> getNormalizer ( $data , $format , $context );
2011-11-08 20:54:41 +00:00
}
/**
* { @ inheritdoc }
*/
2016-07-16 17:39:49 +01:00
public function supportsDenormalization ( $data , $type , $format = null /*, array $context = array()*/ )
2011-11-08 20:54:41 +00:00
{
2016-07-16 17:39:49 +01:00
if ( func_num_args () > 3 ) {
$context = func_get_arg ( 3 );
} else {
if ( __CLASS__ !== get_class ( $this )) {
$r = new \ReflectionMethod ( $this , __FUNCTION__ );
if ( __CLASS__ !== $r -> getDeclaringClass () -> getName ()) {
2017-02-28 14:54:44 +00:00
@ trigger_error ( sprintf ( 'Method %s() will have a fourth `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
2016-07-16 17:39:49 +01:00
}
}
$context = array ();
}
return null !== $this -> getDenormalizer ( $data , $type , $format , $context );
2011-11-08 20:54:41 +00:00
}
/**
2014-03-14 23:57:23 +00:00
* Returns a matching normalizer .
*
2017-11-05 15:47:03 +00:00
* @ param mixed $data Data to get the serializer for
* @ param string $format Format name , present to give the option to normalizers to act differently based on formats
* @ param array $context Options available to the normalizer
2014-03-14 23:57:23 +00:00
*
* @ return NormalizerInterface | null
2011-11-08 20:54:41 +00:00
*/
2016-07-16 17:39:49 +01:00
private function getNormalizer ( $data , $format , array $context )
2011-11-08 20:54:41 +00:00
{
foreach ( $this -> normalizers as $normalizer ) {
2016-07-16 17:39:49 +01:00
if ( $normalizer instanceof NormalizerInterface && $normalizer -> supportsNormalization ( $data , $format , $context )) {
2011-11-08 20:54:41 +00:00
return $normalizer ;
}
}
}
/**
2014-03-14 23:57:23 +00:00
* Returns a matching denormalizer .
*
2017-11-05 15:47:03 +00:00
* @ param mixed $data Data to restore
* @ param string $class The expected class to instantiate
* @ param string $format Format name , present to give the option to normalizers to act differently based on formats
* @ param array $context Options available to the denormalizer
2014-03-14 23:57:23 +00:00
*
* @ return DenormalizerInterface | null
2011-11-08 20:54:41 +00:00
*/
2016-07-16 17:39:49 +01:00
private function getDenormalizer ( $data , $class , $format , array $context )
2011-11-08 20:54:41 +00:00
{
foreach ( $this -> normalizers as $normalizer ) {
2016-07-16 17:39:49 +01:00
if ( $normalizer instanceof DenormalizerInterface && $normalizer -> supportsDenormalization ( $data , $class , $format , $context )) {
2011-11-08 20:54:41 +00:00
return $normalizer ;
}
}
}
2011-01-18 19:17:24 +00:00
/**
* { @ inheritdoc }
*/
2013-01-18 13:08:59 +00:00
final public function encode ( $data , $format , array $context = array ())
2011-01-18 19:17:24 +00:00
{
2013-01-18 13:08:59 +00:00
return $this -> encoder -> encode ( $data , $format , $context );
2011-01-18 19:17:24 +00:00
}
/**
* { @ inheritdoc }
*/
2013-01-18 13:08:59 +00:00
final public function decode ( $data , $format , array $context = array ())
2011-01-18 19:17:24 +00:00
{
2013-01-18 13:08:59 +00:00
return $this -> decoder -> decode ( $data , $format , $context );
2011-01-18 19:17:24 +00:00
}
2011-05-10 08:24:19 +01:00
/**
2014-10-02 18:46:25 +01:00
* Denormalizes data back into an object of the given class .
2011-05-29 09:16:42 +01:00
*
2017-10-28 19:51:46 +01:00
* @ param mixed $data Data to restore
* @ param string $class The expected class to instantiate
* @ param string $format Format name , present to give the option to normalizers to act differently based on formats
2014-10-02 18:46:25 +01:00
* @ param array $context The context data for this particular denormalization
2012-11-16 16:06:12 +00:00
*
2011-05-29 09:16:42 +01:00
* @ return object
2012-12-16 12:02:54 +00:00
*
* @ throws LogicException
* @ throws UnexpectedValueException
2011-05-10 08:24:19 +01:00
*/
2014-03-14 23:57:23 +00:00
private function denormalizeObject ( $data , $class , $format , array $context = array ())
2011-05-10 08:24:19 +01:00
{
if ( ! $this -> normalizers ) {
2011-05-29 09:55:08 +01:00
throw new LogicException ( 'You must register at least one normalizer to be able to denormalize objects.' );
2011-05-10 08:24:19 +01:00
}
2011-12-11 19:53:57 +00:00
2016-07-16 17:39:49 +01:00
if ( $normalizer = $this -> getDenormalizer ( $data , $class , $format , $context )) {
2014-03-14 23:57:23 +00:00
return $normalizer -> denormalize ( $data , $class , $format , $context );
2011-05-10 08:24:19 +01:00
}
2011-12-11 19:53:57 +00:00
2013-04-10 11:24:37 +01:00
throw new UnexpectedValueException ( sprintf ( 'Could not denormalize object of type %s, no supporting normalizer found.' , $class ));
2011-11-02 03:01:10 +00:00
}
2011-06-09 13:18:47 +01:00
/**
* { @ inheritdoc }
*/
2016-07-16 17:39:49 +01:00
public function supportsEncoding ( $format /*, array $context = array()*/ )
2011-06-09 13:18:47 +01:00
{
2016-07-16 17:39:49 +01:00
if ( func_num_args () > 1 ) {
$context = func_get_arg ( 1 );
} else {
if ( __CLASS__ !== get_class ( $this )) {
$r = new \ReflectionMethod ( $this , __FUNCTION__ );
if ( __CLASS__ !== $r -> getDeclaringClass () -> getName ()) {
2017-02-28 14:54:44 +00:00
@ trigger_error ( sprintf ( 'Method %s() will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
2016-07-16 17:39:49 +01:00
}
}
$context = array ();
}
return $this -> encoder -> supportsEncoding ( $format , $context );
2011-06-09 13:18:47 +01:00
}
/**
* { @ inheritdoc }
*/
2016-07-16 17:39:49 +01:00
public function supportsDecoding ( $format /*, array $context = array()*/ )
2011-06-09 13:18:47 +01:00
{
2016-07-16 17:39:49 +01:00
if ( func_num_args () > 1 ) {
$context = func_get_arg ( 1 );
} else {
if ( __CLASS__ !== get_class ( $this )) {
$r = new \ReflectionMethod ( $this , __FUNCTION__ );
if ( __CLASS__ !== $r -> getDeclaringClass () -> getName ()) {
2017-02-28 14:54:44 +00:00
@ trigger_error ( sprintf ( 'Method %s() will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
2016-07-16 17:39:49 +01:00
}
}
$context = array ();
}
return $this -> decoder -> supportsDecoding ( $format , $context );
2011-01-18 19:17:24 +00:00
}
}