annotate vendor/symfony/serializer/Serializer.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents a9cd425dd02b
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Serializer;
Chris@0 13
Chris@0 14 use Symfony\Component\Serializer\Encoder\ChainDecoder;
Chris@0 15 use Symfony\Component\Serializer\Encoder\ChainEncoder;
Chris@4 16 use Symfony\Component\Serializer\Encoder\DecoderInterface;
Chris@0 17 use Symfony\Component\Serializer\Encoder\EncoderInterface;
Chris@4 18 use Symfony\Component\Serializer\Exception\LogicException;
Chris@0 19 use Symfony\Component\Serializer\Exception\NotEncodableValueException;
Chris@0 20 use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
Chris@0 21 use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
Chris@4 22 use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
Chris@0 23 use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
Chris@0 24 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * Serializer serializes and deserializes data.
Chris@0 28 *
Chris@0 29 * objects are turned into arrays by normalizers.
Chris@0 30 * arrays are turned into various output formats by encoders.
Chris@0 31 *
Chris@4 32 * $serializer->serialize($obj, 'xml')
Chris@4 33 * $serializer->decode($data, 'xml')
Chris@4 34 * $serializer->denormalize($data, 'Class', 'xml')
Chris@0 35 *
Chris@0 36 * @author Jordi Boggiano <j.boggiano@seld.be>
Chris@0 37 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
Chris@0 38 * @author Lukas Kahwe Smith <smith@pooteeweet.org>
Chris@0 39 * @author Kévin Dunglas <dunglas@gmail.com>
Chris@0 40 */
Chris@0 41 class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface
Chris@0 42 {
Chris@0 43 /**
Chris@0 44 * @var Encoder\ChainEncoder
Chris@0 45 */
Chris@0 46 protected $encoder;
Chris@0 47
Chris@0 48 /**
Chris@0 49 * @var Encoder\ChainDecoder
Chris@0 50 */
Chris@0 51 protected $decoder;
Chris@0 52
Chris@0 53 /**
Chris@0 54 * @var array
Chris@0 55 */
Chris@4 56 protected $normalizers = [];
Chris@0 57
Chris@0 58 /**
Chris@0 59 * @var array
Chris@0 60 *
Chris@0 61 * @deprecated since 3.1 will be removed in 4.0
Chris@0 62 */
Chris@4 63 protected $normalizerCache = [];
Chris@0 64
Chris@0 65 /**
Chris@0 66 * @var array
Chris@0 67 *
Chris@0 68 * @deprecated since 3.1 will be removed in 4.0
Chris@0 69 */
Chris@4 70 protected $denormalizerCache = [];
Chris@0 71
Chris@4 72 public function __construct(array $normalizers = [], array $encoders = [])
Chris@0 73 {
Chris@0 74 foreach ($normalizers as $normalizer) {
Chris@0 75 if ($normalizer instanceof SerializerAwareInterface) {
Chris@0 76 $normalizer->setSerializer($this);
Chris@0 77 }
Chris@0 78
Chris@0 79 if ($normalizer instanceof DenormalizerAwareInterface) {
Chris@0 80 $normalizer->setDenormalizer($this);
Chris@0 81 }
Chris@0 82
Chris@0 83 if ($normalizer instanceof NormalizerAwareInterface) {
Chris@0 84 $normalizer->setNormalizer($this);
Chris@0 85 }
Chris@0 86 }
Chris@0 87 $this->normalizers = $normalizers;
Chris@0 88
Chris@4 89 $decoders = [];
Chris@4 90 $realEncoders = [];
Chris@0 91 foreach ($encoders as $encoder) {
Chris@0 92 if ($encoder instanceof SerializerAwareInterface) {
Chris@0 93 $encoder->setSerializer($this);
Chris@0 94 }
Chris@0 95 if ($encoder instanceof DecoderInterface) {
Chris@0 96 $decoders[] = $encoder;
Chris@0 97 }
Chris@0 98 if ($encoder instanceof EncoderInterface) {
Chris@0 99 $realEncoders[] = $encoder;
Chris@0 100 }
Chris@0 101 }
Chris@0 102 $this->encoder = new ChainEncoder($realEncoders);
Chris@0 103 $this->decoder = new ChainDecoder($decoders);
Chris@0 104 }
Chris@0 105
Chris@0 106 /**
Chris@0 107 * {@inheritdoc}
Chris@0 108 */
Chris@4 109 final public function serialize($data, $format, array $context = [])
Chris@0 110 {
Chris@0 111 if (!$this->supportsEncoding($format, $context)) {
Chris@0 112 throw new NotEncodableValueException(sprintf('Serialization for the format %s is not supported', $format));
Chris@0 113 }
Chris@0 114
Chris@0 115 if ($this->encoder->needsNormalization($format, $context)) {
Chris@0 116 $data = $this->normalize($data, $format, $context);
Chris@0 117 }
Chris@0 118
Chris@0 119 return $this->encode($data, $format, $context);
Chris@0 120 }
Chris@0 121
Chris@0 122 /**
Chris@0 123 * {@inheritdoc}
Chris@0 124 */
Chris@4 125 final public function deserialize($data, $type, $format, array $context = [])
Chris@0 126 {
Chris@0 127 if (!$this->supportsDecoding($format, $context)) {
Chris@0 128 throw new NotEncodableValueException(sprintf('Deserialization for the format %s is not supported', $format));
Chris@0 129 }
Chris@0 130
Chris@0 131 $data = $this->decode($data, $format, $context);
Chris@0 132
Chris@0 133 return $this->denormalize($data, $type, $format, $context);
Chris@0 134 }
Chris@0 135
Chris@0 136 /**
Chris@0 137 * {@inheritdoc}
Chris@0 138 */
Chris@4 139 public function normalize($data, $format = null, array $context = [])
Chris@0 140 {
Chris@0 141 // If a normalizer supports the given data, use it
Chris@0 142 if ($normalizer = $this->getNormalizer($data, $format, $context)) {
Chris@0 143 return $normalizer->normalize($data, $format, $context);
Chris@0 144 }
Chris@0 145
Chris@0 146 if (null === $data || is_scalar($data)) {
Chris@0 147 return $data;
Chris@0 148 }
Chris@0 149
Chris@0 150 if (\is_array($data) || $data instanceof \Traversable) {
Chris@4 151 $normalized = [];
Chris@0 152 foreach ($data as $key => $val) {
Chris@0 153 $normalized[$key] = $this->normalize($val, $format, $context);
Chris@0 154 }
Chris@0 155
Chris@0 156 return $normalized;
Chris@0 157 }
Chris@0 158
Chris@0 159 if (\is_object($data)) {
Chris@0 160 if (!$this->normalizers) {
Chris@0 161 throw new LogicException('You must register at least one normalizer to be able to normalize objects.');
Chris@0 162 }
Chris@0 163
Chris@0 164 throw new NotNormalizableValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', \get_class($data)));
Chris@0 165 }
Chris@0 166
Chris@0 167 throw new NotNormalizableValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true)));
Chris@0 168 }
Chris@0 169
Chris@0 170 /**
Chris@0 171 * {@inheritdoc}
Chris@0 172 *
Chris@0 173 * @throws NotNormalizableValueException
Chris@0 174 */
Chris@4 175 public function denormalize($data, $type, $format = null, array $context = [])
Chris@0 176 {
Chris@0 177 if (!$this->normalizers) {
Chris@0 178 throw new LogicException('You must register at least one normalizer to be able to denormalize objects.');
Chris@0 179 }
Chris@0 180
Chris@0 181 if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) {
Chris@0 182 return $normalizer->denormalize($data, $type, $format, $context);
Chris@0 183 }
Chris@0 184
Chris@0 185 throw new NotNormalizableValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type));
Chris@0 186 }
Chris@0 187
Chris@0 188 /**
Chris@0 189 * {@inheritdoc}
Chris@0 190 */
Chris@4 191 public function supportsNormalization($data, $format = null/*, array $context = []*/)
Chris@0 192 {
Chris@0 193 if (\func_num_args() > 2) {
Chris@0 194 $context = \func_get_arg(2);
Chris@0 195 } else {
Chris@0 196 if (__CLASS__ !== \get_class($this)) {
Chris@0 197 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@0 198 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@4 199 @trigger_error(sprintf('The "%s()" method will have a third `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@0 200 }
Chris@0 201 }
Chris@0 202
Chris@4 203 $context = [];
Chris@0 204 }
Chris@0 205
Chris@0 206 return null !== $this->getNormalizer($data, $format, $context);
Chris@0 207 }
Chris@0 208
Chris@0 209 /**
Chris@0 210 * {@inheritdoc}
Chris@0 211 */
Chris@4 212 public function supportsDenormalization($data, $type, $format = null/*, array $context = []*/)
Chris@0 213 {
Chris@0 214 if (\func_num_args() > 3) {
Chris@0 215 $context = \func_get_arg(3);
Chris@0 216 } else {
Chris@0 217 if (__CLASS__ !== \get_class($this)) {
Chris@0 218 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@0 219 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@4 220 @trigger_error(sprintf('The "%s()" method will have a fourth `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@0 221 }
Chris@0 222 }
Chris@0 223
Chris@4 224 $context = [];
Chris@0 225 }
Chris@0 226
Chris@0 227 return null !== $this->getDenormalizer($data, $type, $format, $context);
Chris@0 228 }
Chris@0 229
Chris@0 230 /**
Chris@0 231 * Returns a matching normalizer.
Chris@0 232 *
Chris@0 233 * @param mixed $data Data to get the serializer for
Chris@0 234 * @param string $format Format name, present to give the option to normalizers to act differently based on formats
Chris@0 235 * @param array $context Options available to the normalizer
Chris@0 236 *
Chris@0 237 * @return NormalizerInterface|null
Chris@0 238 */
Chris@0 239 private function getNormalizer($data, $format, array $context)
Chris@0 240 {
Chris@0 241 foreach ($this->normalizers as $normalizer) {
Chris@0 242 if ($normalizer instanceof NormalizerInterface && $normalizer->supportsNormalization($data, $format, $context)) {
Chris@0 243 return $normalizer;
Chris@0 244 }
Chris@0 245 }
Chris@0 246 }
Chris@0 247
Chris@0 248 /**
Chris@0 249 * Returns a matching denormalizer.
Chris@0 250 *
Chris@0 251 * @param mixed $data Data to restore
Chris@0 252 * @param string $class The expected class to instantiate
Chris@0 253 * @param string $format Format name, present to give the option to normalizers to act differently based on formats
Chris@0 254 * @param array $context Options available to the denormalizer
Chris@0 255 *
Chris@0 256 * @return DenormalizerInterface|null
Chris@0 257 */
Chris@0 258 private function getDenormalizer($data, $class, $format, array $context)
Chris@0 259 {
Chris@0 260 foreach ($this->normalizers as $normalizer) {
Chris@0 261 if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $class, $format, $context)) {
Chris@0 262 return $normalizer;
Chris@0 263 }
Chris@0 264 }
Chris@0 265 }
Chris@0 266
Chris@0 267 /**
Chris@0 268 * {@inheritdoc}
Chris@0 269 */
Chris@4 270 final public function encode($data, $format, array $context = [])
Chris@0 271 {
Chris@0 272 return $this->encoder->encode($data, $format, $context);
Chris@0 273 }
Chris@0 274
Chris@0 275 /**
Chris@0 276 * {@inheritdoc}
Chris@0 277 */
Chris@4 278 final public function decode($data, $format, array $context = [])
Chris@0 279 {
Chris@0 280 return $this->decoder->decode($data, $format, $context);
Chris@0 281 }
Chris@0 282
Chris@0 283 /**
Chris@0 284 * {@inheritdoc}
Chris@0 285 */
Chris@4 286 public function supportsEncoding($format/*, array $context = []*/)
Chris@0 287 {
Chris@0 288 if (\func_num_args() > 1) {
Chris@0 289 $context = \func_get_arg(1);
Chris@0 290 } else {
Chris@0 291 if (__CLASS__ !== \get_class($this)) {
Chris@0 292 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@0 293 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@4 294 @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@0 295 }
Chris@0 296 }
Chris@0 297
Chris@4 298 $context = [];
Chris@0 299 }
Chris@0 300
Chris@0 301 return $this->encoder->supportsEncoding($format, $context);
Chris@0 302 }
Chris@0 303
Chris@0 304 /**
Chris@0 305 * {@inheritdoc}
Chris@0 306 */
Chris@4 307 public function supportsDecoding($format/*, array $context = []*/)
Chris@0 308 {
Chris@0 309 if (\func_num_args() > 1) {
Chris@0 310 $context = \func_get_arg(1);
Chris@0 311 } else {
Chris@0 312 if (__CLASS__ !== \get_class($this)) {
Chris@0 313 $r = new \ReflectionMethod($this, __FUNCTION__);
Chris@0 314 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
Chris@4 315 @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED);
Chris@0 316 }
Chris@0 317 }
Chris@0 318
Chris@4 319 $context = [];
Chris@0 320 }
Chris@0 321
Chris@0 322 return $this->decoder->supportsDecoding($format, $context);
Chris@0 323 }
Chris@0 324 }