vendor/symfony/src/Symfony/Component/Serializer/Serializer.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 namespace Symfony\Component\Serializer;
       
     4 
       
     5 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
       
     6 use Symfony\Component\Serializer\Encoder\EncoderInterface;
       
     7 use Symfony\Component\Serializer\Encoder\DecoderInterface;
       
     8 use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface;
       
     9 use Symfony\Component\Serializer\Exception\RuntimeException;
       
    10 use Symfony\Component\Serializer\Exception\LogicException;
       
    11 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
       
    12 
       
    13 /*
       
    14  * This file is part of the Symfony framework.
       
    15  *
       
    16  * (c) Fabien Potencier <fabien@symfony.com>
       
    17  *
       
    18  * This source file is subject to the MIT license that is bundled
       
    19  * with this source code in the file LICENSE.
       
    20  */
       
    21 
       
    22 /**
       
    23  * Serializer serializes and deserializes data
       
    24  *
       
    25  * objects are turned into arrays by normalizers
       
    26  * arrays are turned into various output formats by encoders
       
    27  *
       
    28  * $serializer->serialize($obj, 'xml')
       
    29  * $serializer->decode($data, 'xml')
       
    30  * $serializer->denormalize($data, 'Class', 'xml')
       
    31  *
       
    32  * @author Jordi Boggiano <j.boggiano@seld.be>
       
    33  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
       
    34  * @author Lukas Kahwe Smith <smith@pooteeweet.org>
       
    35  */
       
    36 class Serializer implements SerializerInterface
       
    37 {
       
    38     protected $normalizers = array();
       
    39     protected $encoders = array();
       
    40     protected $normalizerCache = array();
       
    41     protected $denormalizerCache = array();
       
    42 
       
    43     public function __construct(array $normalizers = array(), array $encoders = array())
       
    44     {
       
    45         foreach ($normalizers as $normalizer) {
       
    46             if ($normalizer instanceof SerializerAwareInterface) {
       
    47                 $normalizer->setSerializer($this);
       
    48             }
       
    49         }
       
    50         $this->normalizers = $normalizers;
       
    51 
       
    52         foreach ($encoders as $encoder) {
       
    53             if ($encoder instanceof SerializerAwareInterface) {
       
    54                 $encoder->setSerializer($this);
       
    55             }
       
    56         }
       
    57         $this->encoders = $encoders;
       
    58     }
       
    59 
       
    60     /**
       
    61      * {@inheritdoc}
       
    62      */
       
    63     public final function serialize($data, $format)
       
    64     {
       
    65         if (!$this->supportsSerialization($format)) {
       
    66             throw new UnexpectedValueException('Serialization for the format '.$format.' is not supported');
       
    67         }
       
    68 
       
    69         $encoder = $this->getEncoder($format);
       
    70 
       
    71         if (!$encoder instanceof NormalizationAwareInterface) {
       
    72             $data = $this->normalize($data, $format);
       
    73         }
       
    74 
       
    75         return $this->encode($data, $format);
       
    76     }
       
    77 
       
    78     /**
       
    79      * {@inheritdoc}
       
    80      */
       
    81     public final function deserialize($data, $type, $format)
       
    82     {
       
    83         if (!$this->supportsDeserialization($format)) {
       
    84             throw new UnexpectedValueException('Deserialization for the format '.$format.' is not supported');
       
    85         }
       
    86 
       
    87         $data = $this->decode($data, $format);
       
    88 
       
    89         return $this->denormalize($data, $type, $format);
       
    90     }
       
    91 
       
    92     /**
       
    93      * {@inheritdoc}
       
    94      */
       
    95     public function normalize($data, $format = null)
       
    96     {
       
    97         if (null === $data || is_scalar($data)) {
       
    98             return $data;
       
    99         }
       
   100         if ($data instanceof \Traversable) {
       
   101             $normalized = array();
       
   102             foreach ($data as $key => $val) {
       
   103                 $normalized[$key] = $this->normalize($val, $format);
       
   104             }
       
   105 
       
   106             return $normalized;
       
   107         }
       
   108         if (is_object($data)) {
       
   109             return $this->normalizeObject($data, $format);
       
   110         }
       
   111         if (is_array($data)) {
       
   112             foreach ($data as $key => $val) {
       
   113                 $data[$key] = $this->normalize($val, $format);
       
   114             }
       
   115 
       
   116             return $data;
       
   117         }
       
   118         throw new UnexpectedValueException('An unexpected value could not be normalized: '.var_export($data, true));
       
   119     }
       
   120 
       
   121     /**
       
   122      * {@inheritdoc}
       
   123      */
       
   124     public function denormalize($data, $type, $format = null)
       
   125     {
       
   126         return $this->denormalizeObject($data, $type, $format);
       
   127     }
       
   128 
       
   129     /**
       
   130      * {@inheritdoc}
       
   131      */
       
   132     public final function encode($data, $format)
       
   133     {
       
   134         return $this->getEncoder($format)->encode($data, $format);
       
   135     }
       
   136 
       
   137     /**
       
   138      * {@inheritdoc}
       
   139      */
       
   140     public final function decode($data, $format)
       
   141     {
       
   142         return $this->getEncoder($format)->decode($data, $format);
       
   143     }
       
   144 
       
   145     /**
       
   146      * Normalizes an object into a set of arrays/scalars
       
   147      *
       
   148      * @param object $object object to normalize
       
   149      * @param string $format format name, present to give the option to normalizers to act differently based on formats
       
   150      * @return array|scalar
       
   151      */
       
   152     private function normalizeObject($object, $format = null)
       
   153     {
       
   154         if (!$this->normalizers) {
       
   155             throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
       
   156         }
       
   157         $class = get_class($object);
       
   158         if (isset($this->normalizerCache[$class][$format])) {
       
   159             return $this->normalizerCache[$class][$format]->normalize($object, $format);
       
   160         }
       
   161         foreach ($this->normalizers as $normalizer) {
       
   162             if ($normalizer->supportsNormalization($object, $class, $format)) {
       
   163                 $this->normalizerCache[$class][$format] = $normalizer;
       
   164 
       
   165                 return $normalizer->normalize($object, $format);
       
   166             }
       
   167         }
       
   168         throw new UnexpectedValueException('Could not normalize object of type '.$class.', no supporting normalizer found.');
       
   169     }
       
   170 
       
   171     /**
       
   172      * Denormalizes data back into an object of the given class
       
   173      *
       
   174      * @param mixed $data data to restore
       
   175      * @param string $class the expected class to instantiate
       
   176      * @param string $format format name, present to give the option to normalizers to act differently based on formats
       
   177      * @return object
       
   178      */
       
   179     private function denormalizeObject($data, $class, $format = null)
       
   180     {
       
   181         if (!$this->normalizers) {
       
   182             throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
       
   183         }
       
   184         if (isset($this->denormalizerCache[$class][$format])) {
       
   185             return $this->denormalizerCache[$class][$format]->denormalize($data, $class, $format);
       
   186         }
       
   187         foreach ($this->normalizers as $normalizer) {
       
   188             if ($normalizer->supportsDenormalization($data, $class, $format)) {
       
   189                 $this->denormalizerCache[$class][$format] = $normalizer;
       
   190 
       
   191                 return $normalizer->denormalize($data, $class, $format);
       
   192             }
       
   193         }
       
   194         throw new UnexpectedValueException('Could not denormalize object of type '.$class.', no supporting normalizer found.');
       
   195     }
       
   196 
       
   197     /**
       
   198      * {@inheritdoc}
       
   199      */
       
   200     public function supportsSerialization($format)
       
   201     {
       
   202         return $this->supportsEncoding($format);
       
   203     }
       
   204 
       
   205     /**
       
   206      * {@inheritdoc}
       
   207      */
       
   208     public function supportsDeserialization($format)
       
   209     {
       
   210         return $this->supportsDecoding($format);
       
   211     }
       
   212 
       
   213     /**
       
   214      * {@inheritdoc}
       
   215      */
       
   216     public function supportsEncoding($format)
       
   217     {
       
   218         try {
       
   219             $encoder = $this->getEncoder($format);
       
   220         } catch (\RuntimeException $e) {
       
   221             return false;
       
   222         }
       
   223 
       
   224         return $encoder instanceof EncoderInterface;
       
   225     }
       
   226 
       
   227     /**
       
   228      * {@inheritdoc}
       
   229      */
       
   230     public function supportsDecoding($format)
       
   231     {
       
   232         try {
       
   233             $encoder = $this->getEncoder($format);
       
   234         } catch (\RuntimeException $e) {
       
   235             return false;
       
   236         }
       
   237 
       
   238         return $encoder instanceof DecoderInterface;
       
   239     }
       
   240 
       
   241     /**
       
   242      * {@inheritdoc}
       
   243      */
       
   244     public function getEncoder($format)
       
   245     {
       
   246         if (!isset($this->encoders[$format])) {
       
   247             throw new RuntimeException(sprintf('No encoder found for format "%s".', $format));
       
   248         }
       
   249 
       
   250         return $this->encoders[$format];
       
   251     }
       
   252 }