comparison vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 7a779792577d
children c2387f117808
comparison
equal deleted inserted replaced
13:5fb285c0d0e3 14:1fec387a4317
11 11
12 namespace Symfony\Component\Serializer\Normalizer; 12 namespace Symfony\Component\Serializer\Normalizer;
13 13
14 use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; 14 use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
15 use Symfony\Component\Serializer\Encoder\JsonEncoder; 15 use Symfony\Component\Serializer\Encoder\JsonEncoder;
16 use Symfony\Component\Serializer\Exception\ExtraAttributesException;
16 use Symfony\Component\Serializer\Exception\LogicException; 17 use Symfony\Component\Serializer\Exception\LogicException;
17 use Symfony\Component\Serializer\Exception\UnexpectedValueException; 18 use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
18 use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; 19 use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
19 use Symfony\Component\PropertyInfo\Type; 20 use Symfony\Component\PropertyInfo\Type;
20 use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; 21 use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
21 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; 22 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
22 use Symfony\Component\Serializer\NameConverter\NameConverterInterface; 23 use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
28 */ 29 */
29 abstract class AbstractObjectNormalizer extends AbstractNormalizer 30 abstract class AbstractObjectNormalizer extends AbstractNormalizer
30 { 31 {
31 const ENABLE_MAX_DEPTH = 'enable_max_depth'; 32 const ENABLE_MAX_DEPTH = 'enable_max_depth';
32 const DEPTH_KEY_PATTERN = 'depth_%s::%s'; 33 const DEPTH_KEY_PATTERN = 'depth_%s::%s';
34 const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement';
33 35
34 private $propertyTypeExtractor; 36 private $propertyTypeExtractor;
35 private $attributesCache = array(); 37 private $attributesCache = array();
38 private $cache = array();
36 39
37 public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null) 40 public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
38 { 41 {
39 parent::__construct($classMetadataFactory, $nameConverter); 42 parent::__construct($classMetadataFactory, $nameConverter);
40 43
44 /** 47 /**
45 * {@inheritdoc} 48 * {@inheritdoc}
46 */ 49 */
47 public function supportsNormalization($data, $format = null) 50 public function supportsNormalization($data, $format = null)
48 { 51 {
49 return is_object($data) && !$data instanceof \Traversable; 52 return \is_object($data) && !$data instanceof \Traversable;
50 } 53 }
51 54
52 /** 55 /**
53 * {@inheritdoc} 56 * {@inheritdoc}
54 */ 57 */
89 foreach ($stack as $attribute => $attributeValue) { 92 foreach ($stack as $attribute => $attributeValue) {
90 if (!$this->serializer instanceof NormalizerInterface) { 93 if (!$this->serializer instanceof NormalizerInterface) {
91 throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer', $attribute)); 94 throw new LogicException(sprintf('Cannot normalize attribute "%s" because the injected serializer is not a normalizer', $attribute));
92 } 95 }
93 96
94 $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $context)); 97 $data = $this->updateData($data, $attribute, $this->serializer->normalize($attributeValue, $format, $this->createChildContext($context, $attribute)));
95 } 98 }
96 99
97 return $data; 100 return $data;
98 } 101 }
99 102
123 } 126 }
124 127
125 return $allowedAttributes; 128 return $allowedAttributes;
126 } 129 }
127 130
131 if (isset($context['attributes'])) {
132 return $this->extractAttributes($object, $format, $context);
133 }
134
128 if (isset($this->attributesCache[$class])) { 135 if (isset($this->attributesCache[$class])) {
129 return $this->attributesCache[$class]; 136 return $this->attributesCache[$class];
130 } 137 }
131 138
132 return $this->attributesCache[$class] = $this->extractAttributes($object, $format, $context); 139 return $this->attributesCache[$class] = $this->extractAttributes($object, $format, $context);
158 /** 165 /**
159 * {@inheritdoc} 166 * {@inheritdoc}
160 */ 167 */
161 public function supportsDenormalization($data, $type, $format = null) 168 public function supportsDenormalization($data, $type, $format = null)
162 { 169 {
163 return class_exists($type); 170 return isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = class_exists($type);
164 } 171 }
165 172
166 /** 173 /**
167 * {@inheritdoc} 174 * {@inheritdoc}
168 */ 175 */
169 public function denormalize($data, $class, $format = null, array $context = array()) 176 public function denormalize($data, $class, $format = null, array $context = array())
170 { 177 {
171 if (!isset($context['cache_key'])) { 178 if (!isset($context['cache_key'])) {
172 $context['cache_key'] = $this->getCacheKey($format, $context); 179 $context['cache_key'] = $this->getCacheKey($format, $context);
173 } 180 }
181
174 $allowedAttributes = $this->getAllowedAttributes($class, $context, true); 182 $allowedAttributes = $this->getAllowedAttributes($class, $context, true);
175 $normalizedData = $this->prepareForDenormalization($data); 183 $normalizedData = $this->prepareForDenormalization($data);
184 $extraAttributes = array();
176 185
177 $reflectionClass = new \ReflectionClass($class); 186 $reflectionClass = new \ReflectionClass($class);
178 $object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes, $format); 187 $object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes, $format);
179 188
180 foreach ($normalizedData as $attribute => $value) { 189 foreach ($normalizedData as $attribute => $value) {
181 if ($this->nameConverter) { 190 if ($this->nameConverter) {
182 $attribute = $this->nameConverter->denormalize($attribute); 191 $attribute = $this->nameConverter->denormalize($attribute);
183 } 192 }
184 193
185 if (($allowedAttributes !== false && !in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) { 194 if ((false !== $allowedAttributes && !in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) {
195 if (isset($context[self::ALLOW_EXTRA_ATTRIBUTES]) && !$context[self::ALLOW_EXTRA_ATTRIBUTES]) {
196 $extraAttributes[] = $attribute;
197 }
198
186 continue; 199 continue;
187 } 200 }
188 201
189 $value = $this->validateAndDenormalize($class, $attribute, $value, $format, $context); 202 $value = $this->validateAndDenormalize($class, $attribute, $value, $format, $context);
190 try { 203 try {
191 $this->setAttributeValue($object, $attribute, $value, $format, $context); 204 $this->setAttributeValue($object, $attribute, $value, $format, $context);
192 } catch (InvalidArgumentException $e) { 205 } catch (InvalidArgumentException $e) {
193 throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); 206 throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e);
194 } 207 }
208 }
209
210 if (!empty($extraAttributes)) {
211 throw new ExtraAttributesException($extraAttributes);
195 } 212 }
196 213
197 return $object; 214 return $object;
198 } 215 }
199 216
217 * @param string|null $format 234 * @param string|null $format
218 * @param array $context 235 * @param array $context
219 * 236 *
220 * @return mixed 237 * @return mixed
221 * 238 *
222 * @throws UnexpectedValueException 239 * @throws NotNormalizableValueException
223 * @throws LogicException 240 * @throws LogicException
224 */ 241 */
225 private function validateAndDenormalize($currentClass, $attribute, $data, $format, array $context) 242 private function validateAndDenormalize($currentClass, $attribute, $data, $format, array $context)
226 { 243 {
227 if (null === $this->propertyTypeExtractor || null === $types = $this->propertyTypeExtractor->getTypes($currentClass, $attribute)) { 244 if (null === $this->propertyTypeExtractor || null === $types = $this->propertyTypeExtractor->getTypes($currentClass, $attribute)) {
251 if (Type::BUILTIN_TYPE_OBJECT === $builtinType) { 268 if (Type::BUILTIN_TYPE_OBJECT === $builtinType) {
252 if (!$this->serializer instanceof DenormalizerInterface) { 269 if (!$this->serializer instanceof DenormalizerInterface) {
253 throw new LogicException(sprintf('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer', $attribute, $class)); 270 throw new LogicException(sprintf('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer', $attribute, $class));
254 } 271 }
255 272
256 if ($this->serializer->supportsDenormalization($data, $class, $format)) { 273 $childContext = $this->createChildContext($context, $attribute);
257 return $this->serializer->denormalize($data, $class, $format, $context); 274 if ($this->serializer->supportsDenormalization($data, $class, $format, $childContext)) {
275 return $this->serializer->denormalize($data, $class, $format, $childContext);
258 } 276 }
259 } 277 }
260 278
261 // JSON only has a Number type corresponding to both int and float PHP types. 279 // JSON only has a Number type corresponding to both int and float PHP types.
262 // PHP's json_encode, JavaScript's JSON.stringify, Go's json.Marshal as well as most other JSON encoders convert 280 // PHP's json_encode, JavaScript's JSON.stringify, Go's json.Marshal as well as most other JSON encoders convert
271 if (call_user_func('is_'.$builtinType, $data)) { 289 if (call_user_func('is_'.$builtinType, $data)) {
272 return $data; 290 return $data;
273 } 291 }
274 } 292 }
275 293
276 throw new UnexpectedValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data))); 294 if (!empty($context[self::DISABLE_TYPE_ENFORCEMENT])) {
295 return $data;
296 }
297
298 throw new NotNormalizableValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data)));
277 } 299 }
278 300
279 /** 301 /**
280 * Sets an attribute and apply the name converter if necessary. 302 * Sets an attribute and apply the name converter if necessary.
281 * 303 *