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