2015-08-18 00:00:26 +00: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 ;
use Symfony\Component\Serializer\Encoder\ChainDecoder ;
use Symfony\Component\Serializer\Encoder\ChainEncoder ;
use Symfony\Component\Serializer\Encoder\DecoderInterface ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Serializer\Encoder\EncoderInterface ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Serializer\Exception\LogicException ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Serializer\Exception\NotEncodableValueException ;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException ;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface ;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface ;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface ;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface ;
2015-08-18 00:00:26 +00:00
/**
* Serializer serializes and deserializes data .
*
* objects are turned into arrays by normalizers .
* arrays are turned into various output formats by encoders .
*
2018-11-23 12:29:20 +00:00
* $serializer -> serialize ( $obj , 'xml' )
* $serializer -> decode ( $data , 'xml' )
* $serializer -> denormalize ( $data , 'Class' , 'xml' )
2015-08-18 00:00:26 +00:00
*
* @ author Jordi Boggiano < j . boggiano @ seld . be >
* @ author Johannes M . Schmitt < schmittjoh @ gmail . com >
* @ author Lukas Kahwe Smith < smith @ pooteeweet . org >
* @ author Kévin Dunglas < dunglas @ gmail . com >
*/
class Serializer implements SerializerInterface , NormalizerInterface , DenormalizerInterface , EncoderInterface , DecoderInterface
{
/**
* @ var Encoder\ChainEncoder
*/
protected $encoder ;
2016-04-20 16:56:34 +00:00
2015-08-18 00:00:26 +00:00
/**
* @ var Encoder\ChainDecoder
*/
protected $decoder ;
2016-04-20 16:56:34 +00:00
2015-08-18 00:00:26 +00:00
/**
* @ var array
*/
protected $normalizers = array ();
2016-04-20 16:56:34 +00:00
2015-08-18 00:00:26 +00:00
/**
* @ var array
2018-11-23 12:29:20 +00:00
*
* @ deprecated since 3.1 will be removed in 4.0
2015-08-18 00:00:26 +00:00
*/
protected $normalizerCache = array ();
2016-04-20 16:56:34 +00:00
2015-08-18 00:00:26 +00:00
/**
* @ var array
2018-11-23 12:29:20 +00:00
*
* @ deprecated since 3.1 will be removed in 4.0
2015-08-18 00:00:26 +00:00
*/
protected $denormalizerCache = array ();
public function __construct ( array $normalizers = array (), array $encoders = array ())
{
foreach ( $normalizers as $normalizer ) {
if ( $normalizer instanceof SerializerAwareInterface ) {
$normalizer -> setSerializer ( $this );
}
2018-11-23 12:29:20 +00:00
if ( $normalizer instanceof DenormalizerAwareInterface ) {
$normalizer -> setDenormalizer ( $this );
}
if ( $normalizer instanceof NormalizerAwareInterface ) {
$normalizer -> setNormalizer ( $this );
}
2015-08-18 00:00:26 +00:00
}
$this -> normalizers = $normalizers ;
$decoders = array ();
$realEncoders = array ();
foreach ( $encoders as $encoder ) {
if ( $encoder instanceof SerializerAwareInterface ) {
$encoder -> setSerializer ( $this );
}
if ( $encoder instanceof DecoderInterface ) {
$decoders [] = $encoder ;
}
if ( $encoder instanceof EncoderInterface ) {
$realEncoders [] = $encoder ;
}
}
$this -> encoder = new ChainEncoder ( $realEncoders );
$this -> decoder = new ChainDecoder ( $decoders );
}
/**
* { @ inheritdoc }
*/
final public function serialize ( $data , $format , array $context = array ())
{
2018-11-23 12:29:20 +00:00
if ( ! $this -> supportsEncoding ( $format , $context )) {
throw new NotEncodableValueException ( sprintf ( 'Serialization for the format %s is not supported' , $format ));
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
if ( $this -> encoder -> needsNormalization ( $format , $context )) {
2015-08-18 00:00:26 +00:00
$data = $this -> normalize ( $data , $format , $context );
}
return $this -> encode ( $data , $format , $context );
}
/**
* { @ inheritdoc }
*/
final public function deserialize ( $data , $type , $format , array $context = array ())
{
2018-11-23 12:29:20 +00:00
if ( ! $this -> supportsDecoding ( $format , $context )) {
throw new NotEncodableValueException ( sprintf ( 'Deserialization for the format %s is not supported' , $format ));
2015-08-18 00:00:26 +00:00
}
$data = $this -> decode ( $data , $format , $context );
return $this -> denormalize ( $data , $type , $format , $context );
}
/**
* { @ inheritdoc }
*/
public function normalize ( $data , $format = null , array $context = array ())
{
// If a normalizer supports the given data, use it
2018-11-23 12:29:20 +00:00
if ( $normalizer = $this -> getNormalizer ( $data , $format , $context )) {
2015-08-18 00:00:26 +00:00
return $normalizer -> normalize ( $data , $format , $context );
}
if ( null === $data || is_scalar ( $data )) {
return $data ;
}
2016-04-20 16:56:34 +00:00
2018-11-23 12:29:20 +00:00
if ( \is_array ( $data ) || $data instanceof \Traversable ) {
2015-08-18 00:00:26 +00:00
$normalized = array ();
foreach ( $data as $key => $val ) {
$normalized [ $key ] = $this -> normalize ( $val , $format , $context );
}
return $normalized ;
}
2016-04-20 16:56:34 +00:00
2018-11-23 12:29:20 +00:00
if ( \is_object ( $data )) {
2016-04-20 16:56:34 +00:00
if ( ! $this -> normalizers ) {
throw new LogicException ( 'You must register at least one normalizer to be able to normalize objects.' );
2015-08-18 00:00:26 +00:00
}
2018-11-23 12:29:20 +00:00
throw new NotNormalizableValueException ( sprintf ( 'Could not normalize object of type %s, no supporting normalizer found.' , \get_class ( $data )));
2015-08-18 00:00:26 +00:00
}
2016-04-20 16:56:34 +00:00
2018-11-23 12:29:20 +00:00
throw new NotNormalizableValueException ( sprintf ( 'An unexpected value could not be normalized: %s' , var_export ( $data , true )));
2015-08-18 00:00:26 +00:00
}
/**
* { @ inheritdoc }
2018-11-23 12:29:20 +00:00
*
* @ throws NotNormalizableValueException
2015-08-18 00:00:26 +00:00
*/
public function denormalize ( $data , $type , $format = null , array $context = array ())
{
2018-11-23 12:29:20 +00:00
if ( ! $this -> normalizers ) {
throw new LogicException ( 'You must register at least one normalizer to be able to denormalize objects.' );
}
if ( $normalizer = $this -> getDenormalizer ( $data , $type , $format , $context )) {
return $normalizer -> denormalize ( $data , $type , $format , $context );
}
throw new NotNormalizableValueException ( sprintf ( 'Could not denormalize object of type %s, no supporting normalizer found.' , $type ));
2015-08-18 00:00:26 +00:00
}
/**
* { @ inheritdoc }
*/
2018-11-23 12:29:20 +00:00
public function supportsNormalization ( $data , $format = null /*, array $context = array()*/ )
2015-08-18 00:00:26 +00:00
{
2018-11-23 12:29:20 +00: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 ()) {
@ trigger_error ( sprintf ( 'The "%s()" method will have a third `$context = array()` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
}
}
$context = array ();
}
return null !== $this -> getNormalizer ( $data , $format , $context );
2015-08-18 00:00:26 +00:00
}
/**
* { @ inheritdoc }
*/
2018-11-23 12:29:20 +00:00
public function supportsDenormalization ( $data , $type , $format = null /*, array $context = array()*/ )
2015-08-18 00:00:26 +00:00
{
2018-11-23 12:29:20 +00: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 ()) {
@ trigger_error ( sprintf ( 'The "%s()" method will have a fourth `$context = array()` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
}
}
$context = array ();
}
return null !== $this -> getDenormalizer ( $data , $type , $format , $context );
2015-08-18 00:00:26 +00:00
}
/**
* Returns a matching normalizer .
*
2018-11-23 12:29:20 +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
2015-08-18 00:00:26 +00:00
*
* @ return NormalizerInterface | null
*/
2018-11-23 12:29:20 +00:00
private function getNormalizer ( $data , $format , array $context )
2015-08-18 00:00:26 +00:00
{
foreach ( $this -> normalizers as $normalizer ) {
2018-11-23 12:29:20 +00:00
if ( $normalizer instanceof NormalizerInterface && $normalizer -> supportsNormalization ( $data , $format , $context )) {
2015-08-18 00:00:26 +00:00
return $normalizer ;
}
}
}
/**
* Returns a matching denormalizer .
*
2018-11-23 12:29:20 +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
2015-08-18 00:00:26 +00:00
*
* @ return DenormalizerInterface | null
*/
2018-11-23 12:29:20 +00:00
private function getDenormalizer ( $data , $class , $format , array $context )
2015-08-18 00:00:26 +00:00
{
foreach ( $this -> normalizers as $normalizer ) {
2018-11-23 12:29:20 +00:00
if ( $normalizer instanceof DenormalizerInterface && $normalizer -> supportsDenormalization ( $data , $class , $format , $context )) {
2015-08-18 00:00:26 +00:00
return $normalizer ;
}
}
}
/**
* { @ inheritdoc }
*/
final public function encode ( $data , $format , array $context = array ())
{
return $this -> encoder -> encode ( $data , $format , $context );
}
/**
* { @ inheritdoc }
*/
final public function decode ( $data , $format , array $context = array ())
{
return $this -> decoder -> decode ( $data , $format , $context );
}
/**
2018-11-23 12:29:20 +00:00
* { @ inheritdoc }
2015-08-18 00:00:26 +00:00
*/
2018-11-23 12:29:20 +00:00
public function supportsEncoding ( $format /*, array $context = array()*/ )
2015-08-18 00:00:26 +00:00
{
2018-11-23 12:29:20 +00: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 ()) {
@ trigger_error ( sprintf ( 'The "%s()" method will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
}
}
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
$context = array ();
2015-08-18 00:00:26 +00:00
}
2016-04-20 16:56:34 +00:00
2018-11-23 12:29:20 +00:00
return $this -> encoder -> supportsEncoding ( $format , $context );
2015-08-18 00:00:26 +00:00
}
/**
* { @ inheritdoc }
*/
2018-11-23 12:29:20 +00:00
public function supportsDecoding ( $format /*, array $context = array()*/ )
2015-08-18 00:00:26 +00:00
{
2018-11-23 12:29:20 +00: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 ()) {
@ trigger_error ( sprintf ( 'The "%s()" method will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.' , __METHOD__ ), E_USER_DEPRECATED );
}
}
2015-08-18 00:00:26 +00:00
2018-11-23 12:29:20 +00:00
$context = array ();
}
return $this -> decoder -> supportsDecoding ( $format , $context );
2015-08-18 00:00:26 +00:00
}
}