diff --git a/DataCollector/SerializerDataCollector.php b/DataCollector/SerializerDataCollector.php index 9dd1752fa..671239d28 100644 --- a/DataCollector/SerializerDataCollector.php +++ b/DataCollector/SerializerDataCollector.php @@ -33,7 +33,7 @@ public function reset(): void $this->collected = []; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { // Everything is collected during the request, and formatted on kernel terminate. } diff --git a/Debug/TraceableNormalizer.php b/Debug/TraceableNormalizer.php index 4bdd3f7b4..fc4db40ad 100644 --- a/Debug/TraceableNormalizer.php +++ b/Debug/TraceableNormalizer.php @@ -48,7 +48,7 @@ public function getSupportedTypes(?string $format): array return $this->normalizer->getSupportedTypes($format); } - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { if (!$this->normalizer instanceof NormalizerInterface) { throw new \BadMethodCallException(sprintf('The "%s()" method cannot be called as nested normalizer doesn\'t implements "%s".', __METHOD__, NormalizerInterface::class)); @@ -65,7 +65,7 @@ public function normalize(mixed $object, string $format = null, array $context = return $normalized; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { if (!$this->normalizer instanceof NormalizerInterface) { return false; @@ -74,7 +74,7 @@ public function supportsNormalization(mixed $data, string $format = null, array return $this->normalizer->supportsNormalization($data, $format, $context); } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { if (!$this->normalizer instanceof DenormalizerInterface) { throw new \BadMethodCallException(sprintf('The "%s()" method cannot be called as nested normalizer doesn\'t implements "%s".', __METHOD__, DenormalizerInterface::class)); @@ -91,7 +91,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $denormalized; } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { if (!$this->normalizer instanceof DenormalizerInterface) { return false; diff --git a/Debug/TraceableSerializer.php b/Debug/TraceableSerializer.php index 2a8e96c7a..2e375e08d 100644 --- a/Debug/TraceableSerializer.php +++ b/Debug/TraceableSerializer.php @@ -69,7 +69,7 @@ public function deserialize(mixed $data, string $type, string $format, array $co return $result; } - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { $context[self::DEBUG_TRACE_ID] = $traceId = uniqid(); @@ -84,7 +84,7 @@ public function normalize(mixed $object, string $format = null, array $context = return $result; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { $context[self::DEBUG_TRACE_ID] = $traceId = uniqid(); @@ -139,12 +139,12 @@ public function getSupportedTypes(?string $format): array return $this->serializer->getSupportedTypes($format); } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $this->serializer->supportsNormalization($data, $format, $context); } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return $this->serializer->supportsDenormalization($data, $type, $format, $context); } diff --git a/Encoder/JsonEncoder.php b/Encoder/JsonEncoder.php index 0d8bf8d09..dabb89c58 100644 --- a/Encoder/JsonEncoder.php +++ b/Encoder/JsonEncoder.php @@ -27,7 +27,7 @@ class JsonEncoder implements EncoderInterface, DecoderInterface JsonDecode::ASSOCIATIVE => true, ]; - public function __construct(JsonEncode $encodingImpl = null, JsonDecode $decodingImpl = null, array $defaultContext = []) + public function __construct(?JsonEncode $encodingImpl = null, ?JsonDecode $decodingImpl = null, array $defaultContext = []) { $this->defaultContext = array_merge($this->defaultContext, $defaultContext); $this->encodingImpl = $encodingImpl ?? new JsonEncode($this->defaultContext); diff --git a/Encoder/XmlEncoder.php b/Encoder/XmlEncoder.php index 26ee3237c..7b177e49d 100644 --- a/Encoder/XmlEncoder.php +++ b/Encoder/XmlEncoder.php @@ -340,7 +340,7 @@ private function addXmlNamespaces(array $data, \DOMNode $node, \DOMDocument $doc * * @throws NotEncodableValueException */ - private function buildXml(\DOMNode $parentNode, mixed $data, string $format, array $context, string $xmlRootNodeName = null): bool + private function buildXml(\DOMNode $parentNode, mixed $data, string $format, array $context, ?string $xmlRootNodeName = null): bool { $append = true; $removeEmptyTags = $context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? false; @@ -414,7 +414,7 @@ private function buildXml(\DOMNode $parentNode, mixed $data, string $format, arr /** * Selects the type of node to create and appends it to the parent. */ - private function appendNode(\DOMNode $parentNode, mixed $data, string $format, array $context, string $nodeName, string $key = null): bool + private function appendNode(\DOMNode $parentNode, mixed $data, string $format, array $context, string $nodeName, ?string $key = null): bool { $dom = $parentNode instanceof \DOMDocument ? $parentNode : $parentNode->ownerDocument; $node = $dom->createElement($nodeName); diff --git a/Encoder/YamlEncoder.php b/Encoder/YamlEncoder.php index 031a3105e..53ec93001 100644 --- a/Encoder/YamlEncoder.php +++ b/Encoder/YamlEncoder.php @@ -50,7 +50,7 @@ class YamlEncoder implements EncoderInterface, DecoderInterface self::YAML_FLAGS => 0, ]; - public function __construct(Dumper $dumper = null, Parser $parser = null, array $defaultContext = []) + public function __construct(?Dumper $dumper = null, ?Parser $parser = null, array $defaultContext = []) { if (!class_exists(Dumper::class)) { throw new RuntimeException('The YamlEncoder class requires the "Yaml" component. Install "symfony/yaml" to use it.'); diff --git a/Exception/ExtraAttributesException.php b/Exception/ExtraAttributesException.php index d681de419..24b031ae3 100644 --- a/Exception/ExtraAttributesException.php +++ b/Exception/ExtraAttributesException.php @@ -20,7 +20,7 @@ class ExtraAttributesException extends RuntimeException { public function __construct( private readonly array $extraAttributes, - \Throwable $previous = null, + ?\Throwable $previous = null, ) { $msg = sprintf('Extra attributes are not allowed ("%s" %s unknown).', implode('", "', $extraAttributes), \count($extraAttributes) > 1 ? 'are' : 'is'); diff --git a/Exception/MissingConstructorArgumentsException.php b/Exception/MissingConstructorArgumentsException.php index ee8fcb5dc..ad3f5c82b 100644 --- a/Exception/MissingConstructorArgumentsException.php +++ b/Exception/MissingConstructorArgumentsException.php @@ -23,7 +23,7 @@ class MissingConstructorArgumentsException extends RuntimeException public function __construct( string $message, int $code = 0, - \Throwable $previous = null, + ?\Throwable $previous = null, private array $missingArguments = [], private ?string $class = null, ) { diff --git a/Exception/NotNormalizableValueException.php b/Exception/NotNormalizableValueException.php index 148c60ada..279be4127 100644 --- a/Exception/NotNormalizableValueException.php +++ b/Exception/NotNormalizableValueException.php @@ -27,7 +27,7 @@ class NotNormalizableValueException extends UnexpectedValueException * safely to your user. In other words, avoid catching other exceptions and * passing their message directly to this class. */ - public static function createForUnexpectedDataType(string $message, mixed $data, array $expectedTypes, string $path = null, bool $useMessageForUser = false, int $code = 0, \Throwable $previous = null): self + public static function createForUnexpectedDataType(string $message, mixed $data, array $expectedTypes, ?string $path = null, bool $useMessageForUser = false, int $code = 0, ?\Throwable $previous = null): self { $self = new self($message, $code, $previous); diff --git a/Extractor/ObjectPropertyListExtractor.php b/Extractor/ObjectPropertyListExtractor.php index c237e13a7..8422b0786 100644 --- a/Extractor/ObjectPropertyListExtractor.php +++ b/Extractor/ObjectPropertyListExtractor.php @@ -21,7 +21,7 @@ final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorIn private PropertyListExtractorInterface $propertyListExtractor; private \Closure $objectClassResolver; - public function __construct(PropertyListExtractorInterface $propertyListExtractor, callable $objectClassResolver = null) + public function __construct(PropertyListExtractorInterface $propertyListExtractor, ?callable $objectClassResolver = null) { $this->propertyListExtractor = $propertyListExtractor; $this->objectClassResolver = ($objectClassResolver ?? 'get_class')(...); diff --git a/Mapping/AttributeMetadata.php b/Mapping/AttributeMetadata.php index c77d07e5e..eaa14eb6e 100644 --- a/Mapping/AttributeMetadata.php +++ b/Mapping/AttributeMetadata.php @@ -110,7 +110,7 @@ public function getMaxDepth(): ?int return $this->maxDepth; } - public function setSerializedName(string $serializedName = null): void + public function setSerializedName(?string $serializedName = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/serializer', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -124,7 +124,7 @@ public function getSerializedName(): ?string return $this->serializedName; } - public function setSerializedPath(PropertyPath $serializedPath = null): void + public function setSerializedPath(?PropertyPath $serializedPath = null): void { $this->serializedPath = $serializedPath; } diff --git a/Mapping/ClassMetadata.php b/Mapping/ClassMetadata.php index 3a711634a..5cec14c91 100644 --- a/Mapping/ClassMetadata.php +++ b/Mapping/ClassMetadata.php @@ -44,7 +44,7 @@ class ClassMetadata implements ClassMetadataInterface /** * Constructs a metadata for the given class. */ - public function __construct(string $class, ClassDiscriminatorMapping $classDiscriminatorMapping = null) + public function __construct(string $class, ?ClassDiscriminatorMapping $classDiscriminatorMapping = null) { $this->name = $class; $this->classDiscriminatorMapping = $classDiscriminatorMapping; @@ -90,7 +90,7 @@ public function getClassDiscriminatorMapping(): ?ClassDiscriminatorMapping return $this->classDiscriminatorMapping; } - public function setClassDiscriminatorMapping(ClassDiscriminatorMapping $mapping = null): void + public function setClassDiscriminatorMapping(?ClassDiscriminatorMapping $mapping = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/serializer', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/NameConverter/AdvancedNameConverterInterface.php b/NameConverter/AdvancedNameConverterInterface.php index 4e7ed504f..1e74f4d20 100644 --- a/NameConverter/AdvancedNameConverterInterface.php +++ b/NameConverter/AdvancedNameConverterInterface.php @@ -18,7 +18,7 @@ */ interface AdvancedNameConverterInterface extends NameConverterInterface { - public function normalize(string $propertyName, string $class = null, string $format = null, array $context = []): string; + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string; - public function denormalize(string $propertyName, string $class = null, string $format = null, array $context = []): string; + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string; } diff --git a/NameConverter/MetadataAwareNameConverter.php b/NameConverter/MetadataAwareNameConverter.php index d1a0b28f2..64abd37d3 100644 --- a/NameConverter/MetadataAwareNameConverter.php +++ b/NameConverter/MetadataAwareNameConverter.php @@ -41,7 +41,7 @@ public function __construct( ) { } - public function normalize(string $propertyName, string $class = null, string $format = null, array $context = []): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { if (null === $class) { return $this->normalizeFallback($propertyName, $class, $format, $context); @@ -54,7 +54,7 @@ public function normalize(string $propertyName, string $class = null, string $fo return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); } - public function denormalize(string $propertyName, string $class = null, string $format = null, array $context = []): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { if (null === $class) { return $this->denormalizeFallback($propertyName, $class, $format, $context); @@ -86,7 +86,7 @@ private function getCacheValueForNormalization(string $propertyName, string $cla return $attributesMetadata[$propertyName]->getSerializedName() ?? null; } - private function normalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string + private function normalizeFallback(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return $this->fallbackNameConverter ? $this->fallbackNameConverter->normalize($propertyName, $class, $format, $context) : $propertyName; } @@ -101,7 +101,7 @@ private function getCacheValueForDenormalization(string $propertyName, string $c return self::$attributesMetadataCache[$cacheKey][$propertyName] ?? null; } - private function denormalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string + private function denormalizeFallback(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return $this->fallbackNameConverter ? $this->fallbackNameConverter->denormalize($propertyName, $class, $format, $context) : $propertyName; } diff --git a/Normalizer/AbstractNormalizer.php b/Normalizer/AbstractNormalizer.php index 06c316eb0..a88544154 100644 --- a/Normalizer/AbstractNormalizer.php +++ b/Normalizer/AbstractNormalizer.php @@ -143,7 +143,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn /** * Sets the {@link ClassMetadataFactoryInterface} to use. */ - public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, array $defaultContext = []) + public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, array $defaultContext = []) { $this->classMetadataFactory = $classMetadataFactory; $this->nameConverter = $nameConverter; @@ -201,7 +201,7 @@ protected function isCircularReference(object $object, array &$context): bool * * @throws CircularReferenceException */ - protected function handleCircularReference(object $object, string $format = null, array $context = []): mixed + protected function handleCircularReference(object $object, ?string $format = null, array $context = []): mixed { $circularReferenceHandler = $context[self::CIRCULAR_REFERENCE_HANDLER] ?? $this->defaultContext[self::CIRCULAR_REFERENCE_HANDLER]; if ($circularReferenceHandler) { @@ -270,7 +270,7 @@ protected function getGroups(array $context): array * * @return bool */ - protected function isAllowedAttribute(object|string $classOrObject, string $attribute, string $format = null, array $context = []) + protected function isAllowedAttribute(object|string $classOrObject, string $attribute, ?string $format = null, array $context = []) { $ignoredAttributes = $context[self::IGNORED_ATTRIBUTES] ?? $this->defaultContext[self::IGNORED_ATTRIBUTES]; if (\in_array($attribute, $ignoredAttributes)) { @@ -321,7 +321,7 @@ protected function getConstructor(array &$data, string $class, array &$context, * @throws RuntimeException * @throws MissingConstructorArgumentsException */ - protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null) + protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null) { if (null !== $object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE)) { unset($context[self::OBJECT_TO_POPULATE]); @@ -361,7 +361,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex $variadicParameters[$parameterKey] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format); } - $params = array_merge($params, $variadicParameters); + $params = array_merge(array_values($params), $variadicParameters); $unsetKeys[] = $key; } } elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) { @@ -403,7 +403,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name), $data, ['unknown'], - $context['deserialization_path'] ?? null, + $attributeContext['deserialization_path'] ?? null, true ); $context['not_normalizable_value_exceptions'][] = $exception; @@ -460,7 +460,7 @@ protected function instantiateObject(array &$data, string $class, array &$contex /** * @internal */ - protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, string $format = null): mixed + protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, ?string $format = null): mixed { try { if (($parameterType = $parameter->getType()) instanceof \ReflectionNamedType && !$parameterType->isBuiltin()) { diff --git a/Normalizer/AbstractObjectNormalizer.php b/Normalizer/AbstractObjectNormalizer.php index d43cbbbdd..11ba28c75 100644 --- a/Normalizer/AbstractObjectNormalizer.php +++ b/Normalizer/AbstractObjectNormalizer.php @@ -116,11 +116,11 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer protected $classDiscriminatorResolver; public function __construct( - ClassMetadataFactoryInterface $classMetadataFactory = null, - NameConverterInterface $nameConverter = null, + ?ClassMetadataFactoryInterface $classMetadataFactory = null, + ?NameConverterInterface $nameConverter = null, private ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, - ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, - callable $objectClassResolver = null, + ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, + ?callable $objectClassResolver = null, array $defaultContext = [], ) { parent::__construct($classMetadataFactory, $nameConverter, $defaultContext); @@ -143,7 +143,7 @@ public function __construct( * * @return bool */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */) + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */) { return \is_object($data) && !$data instanceof \Traversable; } @@ -151,7 +151,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @return array|string|int|float|bool|\ArrayObject|null */ - public function normalize(mixed $object, string $format = null, array $context = []) + public function normalize(mixed $object, ?string $format = null, array $context = []) { if (!isset($context['cache_key'])) { $context['cache_key'] = $this->getCacheKey($format, $context); @@ -232,7 +232,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @return object */ - protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, string $format = null) + protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null) { if ($class !== $mappedClass = $this->getMappedClass($data, $class, $context)) { return $this->instantiateObject($data, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format); @@ -283,21 +283,21 @@ protected function getAttributes(object $object, ?string $format, array $context * * @return string[] */ - abstract protected function extractAttributes(object $object, string $format = null, array $context = []); + abstract protected function extractAttributes(object $object, ?string $format = null, array $context = []); /** * Gets the attribute value. * * @return mixed */ - abstract protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []); + abstract protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []); /** * @param array $context * * @return bool */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */) + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */) { return class_exists($type) || (interface_exists($type, false) && null !== $this->classDiscriminatorResolver?->getMappingForClass($type)); } @@ -305,7 +305,7 @@ public function supportsDenormalization(mixed $data, string $type, string $forma /** * @return mixed */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []) + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []) { if (!isset($context['cache_key'])) { $context['cache_key'] = $this->getCacheKey($format, $context); @@ -398,7 +398,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar sprintf('Failed to denormalize attribute "%s" value for class "%s": '.$e->getMessage(), $attribute, $type), $data, ['unknown'], - $context['deserialization_path'] ?? null, + $attributeContext['deserialization_path'] ?? null, false, $e->getCode(), $e @@ -421,7 +421,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * @return void */ - abstract protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []); + abstract protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []); /** * Validates the submitted data and denormalizes it. @@ -619,7 +619,7 @@ private function validateAndDenormalize(array $types, string $currentClass, stri /** * @internal */ - protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, string $format = null): mixed + protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, mixed $parameterData, array $context, ?string $format = null): mixed { if ($parameter->isVariadic() || null === $this->propertyTypeExtractor || null === $types = $this->getTypes($class->getName(), $parameterName)) { return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format); @@ -734,7 +734,11 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str protected function createChildContext(array $parentContext, string $attribute, ?string $format): array { $context = parent::createChildContext($parentContext, $attribute, $format); - $context['cache_key'] = $this->getCacheKey($format, $context); + if ($context['cache_key'] ?? false) { + $context['cache_key'] .= '-'.$attribute; + } elseif (false !== ($context['cache_key'] ?? null)) { + $context['cache_key'] = $this->getCacheKey($format, $context); + } return $context; } diff --git a/Normalizer/ArrayDenormalizer.php b/Normalizer/ArrayDenormalizer.php index e6669634a..38aee6d86 100644 --- a/Normalizer/ArrayDenormalizer.php +++ b/Normalizer/ArrayDenormalizer.php @@ -44,7 +44,7 @@ public function getSupportedTypes(?string $format): array /** * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): array + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): array { if (null === $this->denormalizer) { throw new BadMethodCallException('Please set a denormalizer before calling denormalize()!'); @@ -74,7 +74,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $data; } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { if (null === $this->denormalizer) { throw new BadMethodCallException(sprintf('The nested denormalizer needs to be set to allow "%s()" to be used.', __METHOD__)); diff --git a/Normalizer/BackedEnumNormalizer.php b/Normalizer/BackedEnumNormalizer.php index fc7a70188..8b0aa7f5a 100644 --- a/Normalizer/BackedEnumNormalizer.php +++ b/Normalizer/BackedEnumNormalizer.php @@ -34,7 +34,7 @@ public function getSupportedTypes(?string $format): array ]; } - public function normalize(mixed $object, string $format = null, array $context = []): int|string + public function normalize(mixed $object, ?string $format = null, array $context = []): int|string { if (!$object instanceof \BackedEnum) { throw new InvalidArgumentException('The data must belong to a backed enumeration.'); @@ -43,7 +43,7 @@ public function normalize(mixed $object, string $format = null, array $context = return $object->value; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof \BackedEnum; } @@ -51,7 +51,7 @@ public function supportsNormalization(mixed $data, string $format = null, array /** * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { if (!is_subclass_of($type, \BackedEnum::class)) { throw new InvalidArgumentException('The data must belong to a backed enumeration.'); @@ -84,7 +84,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar } } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return is_subclass_of($type, \BackedEnum::class); } diff --git a/Normalizer/ConstraintViolationListNormalizer.php b/Normalizer/ConstraintViolationListNormalizer.php index 2b6a8ec2e..814b6f872 100644 --- a/Normalizer/ConstraintViolationListNormalizer.php +++ b/Normalizer/ConstraintViolationListNormalizer.php @@ -45,7 +45,7 @@ public function getSupportedTypes(?string $format): array ]; } - public function normalize(mixed $object, string $format = null, array $context = []): array + public function normalize(mixed $object, ?string $format = null, array $context = []): array { if (\array_key_exists(self::PAYLOAD_FIELDS, $context)) { $payloadFieldsToSerialize = $context[self::PAYLOAD_FIELDS]; @@ -111,7 +111,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof ConstraintViolationListInterface; } diff --git a/Normalizer/ContextAwareDenormalizerInterface.php b/Normalizer/ContextAwareDenormalizerInterface.php index a02951093..19fe3ad1f 100644 --- a/Normalizer/ContextAwareDenormalizerInterface.php +++ b/Normalizer/ContextAwareDenormalizerInterface.php @@ -23,5 +23,5 @@ interface ContextAwareDenormalizerInterface extends DenormalizerInterface /** * @param array $context options that denormalizers have access to */ - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool; + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool; } diff --git a/Normalizer/ContextAwareNormalizerInterface.php b/Normalizer/ContextAwareNormalizerInterface.php index 44f2f0219..164d638e5 100644 --- a/Normalizer/ContextAwareNormalizerInterface.php +++ b/Normalizer/ContextAwareNormalizerInterface.php @@ -23,5 +23,5 @@ interface ContextAwareNormalizerInterface extends NormalizerInterface /** * @param array $context options that normalizers have access to */ - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool; + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool; } diff --git a/Normalizer/CustomNormalizer.php b/Normalizer/CustomNormalizer.php index f45f36296..d7f61b4d4 100644 --- a/Normalizer/CustomNormalizer.php +++ b/Normalizer/CustomNormalizer.php @@ -32,12 +32,12 @@ public function getSupportedTypes(?string $format): array ]; } - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { return $object->normalize($this->serializer, $format, $context); } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { $object = $this->extractObjectToPopulate($type, $context) ?? new $type(); $object->denormalize($this->serializer, $data, $format, $context); @@ -52,7 +52,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar * @param string|null $format The format being (de-)serialized from or into * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof NormalizableInterface; } @@ -65,7 +65,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar * @param string|null $format The format being deserialized from * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return is_subclass_of($type, DenormalizableInterface::class); } diff --git a/Normalizer/DataUriNormalizer.php b/Normalizer/DataUriNormalizer.php index 0b4d0b273..9252a69b5 100644 --- a/Normalizer/DataUriNormalizer.php +++ b/Normalizer/DataUriNormalizer.php @@ -35,7 +35,7 @@ class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface, C private readonly ?MimeTypeGuesserInterface $mimeTypeGuesser; - public function __construct(MimeTypeGuesserInterface $mimeTypeGuesser = null) + public function __construct(?MimeTypeGuesserInterface $mimeTypeGuesser = null) { if (!$mimeTypeGuesser && class_exists(MimeTypes::class)) { $mimeTypeGuesser = MimeTypes::getDefault(); @@ -55,7 +55,7 @@ public function getSupportedTypes(?string $format): array ]; } - public function normalize(mixed $object, string $format = null, array $context = []): string + public function normalize(mixed $object, ?string $format = null, array $context = []): string { if (!$object instanceof \SplFileInfo) { throw new InvalidArgumentException('The object must be an instance of "\SplFileInfo".'); @@ -81,7 +81,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof \SplFileInfo; } @@ -94,7 +94,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar * @throws InvalidArgumentException * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): \SplFileInfo + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \SplFileInfo { if (null === $data || !preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) { throw NotNormalizableValueException::createForUnexpectedDataType('The provided "data:" URI is not valid.', $data, ['string'], $context['deserialization_path'] ?? null, true); @@ -123,7 +123,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return isset(self::SUPPORTED_TYPES[$type]); } diff --git a/Normalizer/DateIntervalNormalizer.php b/Normalizer/DateIntervalNormalizer.php index 202f0e861..ce59a71a9 100644 --- a/Normalizer/DateIntervalNormalizer.php +++ b/Normalizer/DateIntervalNormalizer.php @@ -45,7 +45,7 @@ public function getSupportedTypes(?string $format): array /** * @throws InvalidArgumentException */ - public function normalize(mixed $object, string $format = null, array $context = []): string + public function normalize(mixed $object, ?string $format = null, array $context = []): string { if (!$object instanceof \DateInterval) { throw new InvalidArgumentException('The object must be an instance of "\DateInterval".'); @@ -57,7 +57,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof \DateInterval; } @@ -75,7 +75,7 @@ public function hasCacheableSupportsMethod(): bool /** * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): \DateInterval + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateInterval { if (!\is_string($data)) { throw NotNormalizableValueException::createForUnexpectedDataType('Data expected to be a string.', $data, ['string'], $context['deserialization_path'] ?? null, true); @@ -124,7 +124,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return \DateInterval::class === $type; } diff --git a/Normalizer/DateTimeNormalizer.php b/Normalizer/DateTimeNormalizer.php index 37fa2ef42..82d2657c5 100644 --- a/Normalizer/DateTimeNormalizer.php +++ b/Normalizer/DateTimeNormalizer.php @@ -63,7 +63,7 @@ public function getSupportedTypes(?string $format): array /** * @throws InvalidArgumentException */ - public function normalize(mixed $object, string $format = null, array $context = []): string + public function normalize(mixed $object, ?string $format = null, array $context = []): string { if (!$object instanceof \DateTimeInterface) { throw new InvalidArgumentException('The object must implement the "\DateTimeInterface".'); @@ -83,7 +83,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof \DateTimeInterface; } @@ -91,7 +91,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): \DateTimeInterface + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateTimeInterface { if (\is_int($data) || \is_float($data)) { switch ($context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY] ?? null) { @@ -141,7 +141,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return isset(self::SUPPORTED_TYPES[$type]); } diff --git a/Normalizer/DateTimeZoneNormalizer.php b/Normalizer/DateTimeZoneNormalizer.php index b4e1584ad..892a576ce 100644 --- a/Normalizer/DateTimeZoneNormalizer.php +++ b/Normalizer/DateTimeZoneNormalizer.php @@ -34,7 +34,7 @@ public function getSupportedTypes(?string $format): array /** * @throws InvalidArgumentException */ - public function normalize(mixed $object, string $format = null, array $context = []): string + public function normalize(mixed $object, ?string $format = null, array $context = []): string { if (!$object instanceof \DateTimeZone) { throw new InvalidArgumentException('The object must be an instance of "\DateTimeZone".'); @@ -46,7 +46,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof \DateTimeZone; } @@ -54,7 +54,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @throws NotNormalizableValueException */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): \DateTimeZone + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): \DateTimeZone { if ('' === $data || null === $data) { throw NotNormalizableValueException::createForUnexpectedDataType('The data is either an empty string or null, you should pass a string that can be parsed as a DateTimeZone.', $data, [Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true); @@ -70,7 +70,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return \DateTimeZone::class === $type; } diff --git a/Normalizer/DenormalizableInterface.php b/Normalizer/DenormalizableInterface.php index 503f3cb51..1811c93a4 100644 --- a/Normalizer/DenormalizableInterface.php +++ b/Normalizer/DenormalizableInterface.php @@ -36,5 +36,5 @@ interface DenormalizableInterface * * @return void */ - public function denormalize(DenormalizerInterface $denormalizer, array|string|int|float|bool $data, string $format = null, array $context = []); + public function denormalize(DenormalizerInterface $denormalizer, array|string|int|float|bool $data, ?string $format = null, array $context = []); } diff --git a/Normalizer/DenormalizerInterface.php b/Normalizer/DenormalizerInterface.php index d047ec298..98c59fc66 100644 --- a/Normalizer/DenormalizerInterface.php +++ b/Normalizer/DenormalizerInterface.php @@ -46,7 +46,7 @@ interface DenormalizerInterface * @throws RuntimeException Occurs if the class cannot be instantiated * @throws ExceptionInterface Occurs for all the other cases of errors */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []); + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []); /** * Checks whether the given class is supported for denormalization by this normalizer. @@ -58,7 +58,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar * * @return bool */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */); + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */); /** * Returns the types potentially supported by this denormalizer. diff --git a/Normalizer/FormErrorNormalizer.php b/Normalizer/FormErrorNormalizer.php index 57d9bd4bb..8c0d3a1c0 100644 --- a/Normalizer/FormErrorNormalizer.php +++ b/Normalizer/FormErrorNormalizer.php @@ -22,7 +22,7 @@ final class FormErrorNormalizer implements NormalizerInterface, CacheableSupport public const TYPE = 'type'; public const CODE = 'status_code'; - public function normalize(mixed $object, string $format = null, array $context = []): array + public function normalize(mixed $object, ?string $format = null, array $context = []): array { $data = [ 'title' => $context[self::TITLE] ?? 'Validation Failed', @@ -45,7 +45,7 @@ public function getSupportedTypes(?string $format): array ]; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof FormInterface && $data->isSubmitted() && !$data->isValid(); } diff --git a/Normalizer/GetSetMethodNormalizer.php b/Normalizer/GetSetMethodNormalizer.php index b47ea6a5f..b4e2bef56 100644 --- a/Normalizer/GetSetMethodNormalizer.php +++ b/Normalizer/GetSetMethodNormalizer.php @@ -48,7 +48,7 @@ public function getSupportedTypes(?string $format): array /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return parent::supportsNormalization($data, $format) && $this->supports($data::class); } @@ -56,7 +56,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); } @@ -104,7 +104,7 @@ private function isGetMethod(\ReflectionMethod $method): bool ); } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { $reflectionObject = new \ReflectionObject($object); $reflectionMethods = $reflectionObject->getMethods(\ReflectionMethod::IS_PUBLIC); @@ -125,7 +125,7 @@ protected function extractAttributes(object $object, string $format = null, arra return $attributes; } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { $ucfirsted = ucfirst($attribute); @@ -150,7 +150,7 @@ protected function getAttributeValue(object $object, string $attribute, string $ /** * @return void */ - protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []) + protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []) { $setter = 'set'.ucfirst($attribute); $key = $object::class.':'.$setter; diff --git a/Normalizer/JsonSerializableNormalizer.php b/Normalizer/JsonSerializableNormalizer.php index 238cffa1e..0753c8ba7 100644 --- a/Normalizer/JsonSerializableNormalizer.php +++ b/Normalizer/JsonSerializableNormalizer.php @@ -23,7 +23,7 @@ */ class JsonSerializableNormalizer extends AbstractNormalizer { - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { if ($this->isCircularReference($object, $context)) { return $this->handleCircularReference($object, $format, $context); @@ -50,7 +50,7 @@ public function getSupportedTypes(?string $format): array /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof \JsonSerializable; } @@ -58,12 +58,12 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return false; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { throw new LogicException(sprintf('Cannot denormalize with "%s".', \JsonSerializable::class)); } diff --git a/Normalizer/MimeMessageNormalizer.php b/Normalizer/MimeMessageNormalizer.php index ab9544bf2..07a170d6b 100644 --- a/Normalizer/MimeMessageNormalizer.php +++ b/Normalizer/MimeMessageNormalizer.php @@ -17,6 +17,7 @@ use Symfony\Component\Mime\Header\UnstructuredHeader; use Symfony\Component\Mime\Message; use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\RawMessage; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerInterface; @@ -63,7 +64,7 @@ public function setSerializer(SerializerInterface $serializer): void $this->normalizer->setSerializer($serializer); } - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { if ($object instanceof Headers) { $ret = []; @@ -74,18 +75,21 @@ public function normalize(mixed $object, string $format = null, array $context = return $ret; } + $ret = $this->normalizer->normalize($object, $format, $context); + if ($object instanceof AbstractPart) { - $ret = $this->normalizer->normalize($object, $format, $context); $ret['class'] = $object::class; unset($ret['seekable'], $ret['cid'], $ret['handle']); + } - return $ret; + if ($object instanceof RawMessage && \array_key_exists('message', $ret) && null === $ret['message']) { + unset($ret['message']); } - return $this->normalizer->normalize($object, $format, $context); + return $ret; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { if (Headers::class === $type) { $ret = []; @@ -107,12 +111,12 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $this->normalizer->denormalize($data, $type, $format, $context); } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof Message || $data instanceof Headers || $data instanceof HeaderInterface || $data instanceof Address || $data instanceof AbstractPart; } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return is_a($type, Message::class, true) || Headers::class === $type || AbstractPart::class === $type; } diff --git a/Normalizer/NormalizableInterface.php b/Normalizer/NormalizableInterface.php index 0bad9d183..7be598668 100644 --- a/Normalizer/NormalizableInterface.php +++ b/Normalizer/NormalizableInterface.php @@ -33,5 +33,5 @@ interface NormalizableInterface * based on different output formats * @param array $context Options for normalizing this object */ - public function normalize(NormalizerInterface $normalizer, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null; + public function normalize(NormalizerInterface $normalizer, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null; } diff --git a/Normalizer/NormalizerInterface.php b/Normalizer/NormalizerInterface.php index 5710167f4..4bf04602e 100644 --- a/Normalizer/NormalizerInterface.php +++ b/Normalizer/NormalizerInterface.php @@ -38,7 +38,7 @@ interface NormalizerInterface * @throws LogicException Occurs when the normalizer is not called in an expected context * @throws ExceptionInterface Occurs for all the other cases of errors */ - public function normalize(mixed $object, string $format = null, array $context = []); + public function normalize(mixed $object, ?string $format = null, array $context = []); /** * Checks whether the given class is supported for normalization by this normalizer. @@ -49,7 +49,7 @@ public function normalize(mixed $object, string $format = null, array $context = * * @return bool */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */); + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */); /** * Returns the types potentially supported by this normalizer. diff --git a/Normalizer/ObjectNormalizer.php b/Normalizer/ObjectNormalizer.php index 3f4638ca6..eb37f8897 100644 --- a/Normalizer/ObjectNormalizer.php +++ b/Normalizer/ObjectNormalizer.php @@ -34,7 +34,7 @@ class ObjectNormalizer extends AbstractObjectNormalizer private readonly \Closure $objectClassResolver; - public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) + public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyAccessorInterface $propertyAccessor = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = []) { if (!class_exists(PropertyAccess::class)) { throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.'); @@ -62,7 +62,7 @@ public function hasCacheableSupportsMethod(): bool return __CLASS__ === static::class; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { if (\stdClass::class === $object::class) { return array_keys((array) $object); @@ -125,7 +125,7 @@ protected function extractAttributes(object $object, string $format = null, arra return array_keys($attributes); } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { $mapping = $this->classDiscriminatorResolver?->getMappingForMappedObject($object); @@ -137,7 +137,7 @@ protected function getAttributeValue(object $object, string $attribute, string $ /** * @return void */ - protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []) + protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []) { try { $this->propertyAccessor->setValue($object, $attribute, $value); diff --git a/Normalizer/ObjectToPopulateTrait.php b/Normalizer/ObjectToPopulateTrait.php index 23be4c6af..21ad5f7ad 100644 --- a/Normalizer/ObjectToPopulateTrait.php +++ b/Normalizer/ObjectToPopulateTrait.php @@ -21,7 +21,7 @@ trait ObjectToPopulateTrait * @param string|null $key They in which to look for the object to populate. * Keeps backwards compatibility with `AbstractNormalizer`. */ - protected function extractObjectToPopulate(string $class, array $context, string $key = null): ?object + protected function extractObjectToPopulate(string $class, array $context, ?string $key = null): ?object { $key ??= AbstractNormalizer::OBJECT_TO_POPULATE; diff --git a/Normalizer/ProblemNormalizer.php b/Normalizer/ProblemNormalizer.php index f7a8077ec..66e2d0647 100644 --- a/Normalizer/ProblemNormalizer.php +++ b/Normalizer/ProblemNormalizer.php @@ -50,7 +50,7 @@ public function getSupportedTypes(?string $format): array ]; } - public function normalize(mixed $object, string $format = null, array $context = []): array + public function normalize(mixed $object, ?string $format = null, array $context = []): array { if (!$object instanceof FlattenException) { throw new InvalidArgumentException(sprintf('The object must implement "%s".', FlattenException::class)); @@ -109,7 +109,7 @@ public function normalize(mixed $object, string $format = null, array $context = /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return $data instanceof FlattenException; } diff --git a/Normalizer/PropertyNormalizer.php b/Normalizer/PropertyNormalizer.php index 7b3a26426..6a5d0acd8 100644 --- a/Normalizer/PropertyNormalizer.php +++ b/Normalizer/PropertyNormalizer.php @@ -47,7 +47,7 @@ class PropertyNormalizer extends AbstractObjectNormalizer */ public const NORMALIZE_VISIBILITY = 'normalize_visibility'; - public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) + public function __construct(?ClassMetadataFactoryInterface $classMetadataFactory = null, ?NameConverterInterface $nameConverter = null, ?PropertyTypeExtractorInterface $propertyTypeExtractor = null, ?ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, ?callable $objectClassResolver = null, array $defaultContext = []) { parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext); @@ -64,7 +64,7 @@ public function getSupportedTypes(?string $format): array /** * @param array $context */ - public function supportsNormalization(mixed $data, string $format = null /* , array $context = [] */): bool + public function supportsNormalization(mixed $data, ?string $format = null /* , array $context = [] */): bool { return parent::supportsNormalization($data, $format) && $this->supports($data::class); } @@ -72,7 +72,7 @@ public function supportsNormalization(mixed $data, string $format = null /* , ar /** * @param array $context */ - public function supportsDenormalization(mixed $data, string $type, string $format = null /* , array $context = [] */): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null /* , array $context = [] */): bool { return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); } @@ -110,7 +110,7 @@ private function supports(string $class): bool return false; } - protected function isAllowedAttribute(object|string $classOrObject, string $attribute, string $format = null, array $context = []): bool + protected function isAllowedAttribute(object|string $classOrObject, string $attribute, ?string $format = null, array $context = []): bool { if (!parent::isAllowedAttribute($classOrObject, $attribute, $format, $context)) { return false; @@ -143,7 +143,7 @@ protected function isAllowedAttribute(object|string $classOrObject, string $attr return false; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { $reflectionObject = new \ReflectionObject($object); $attributes = []; @@ -161,7 +161,7 @@ protected function extractAttributes(object $object, string $format = null, arra return array_unique($attributes); } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { try { $reflectionProperty = $this->getReflectionProperty($object, $attribute); @@ -190,7 +190,7 @@ protected function getAttributeValue(object $object, string $attribute, string $ /** * @return void */ - protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []) + protected function setAttributeValue(object $object, string $attribute, mixed $value, ?string $format = null, array $context = []) { try { $reflectionProperty = $this->getReflectionProperty($object, $attribute); diff --git a/Normalizer/UidNormalizer.php b/Normalizer/UidNormalizer.php index 0dfeae7b8..a5f8b8c0d 100644 --- a/Normalizer/UidNormalizer.php +++ b/Normalizer/UidNormalizer.php @@ -51,7 +51,7 @@ public function getSupportedTypes(?string $format): array /** * @param AbstractUid $object */ - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { return match ($context[self::NORMALIZATION_FORMAT_KEY] ?? $this->defaultContext[self::NORMALIZATION_FORMAT_KEY]) { self::NORMALIZATION_FORMAT_CANONICAL => (string) $object, @@ -62,12 +62,12 @@ public function normalize(mixed $object, string $format = null, array $context = }; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof AbstractUid; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { try { if (AbstractUid::class === $type) { @@ -88,7 +88,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar } } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { if (AbstractUid::class === $type) { trigger_deprecation('symfony/serializer', '6.1', 'Supporting denormalization for the "%s" type in "%s" is deprecated, use one of "%s" child class instead.', AbstractUid::class, __CLASS__, AbstractUid::class); diff --git a/Normalizer/UnwrappingDenormalizer.php b/Normalizer/UnwrappingDenormalizer.php index 3708b1a08..aa4d74c45 100644 --- a/Normalizer/UnwrappingDenormalizer.php +++ b/Normalizer/UnwrappingDenormalizer.php @@ -28,7 +28,7 @@ final class UnwrappingDenormalizer implements DenormalizerInterface, SerializerA private readonly PropertyAccessorInterface $propertyAccessor; - public function __construct(PropertyAccessorInterface $propertyAccessor = null) + public function __construct(?PropertyAccessorInterface $propertyAccessor = null) { $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor(); } @@ -38,7 +38,7 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { $propertyPath = $context[self::UNWRAP_PATH]; $context['unwrapped'] = true; @@ -58,7 +58,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $this->serializer->denormalize($data, $type, $format, $context); } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return \array_key_exists(self::UNWRAP_PATH, $context) && !isset($context['unwrapped']); } diff --git a/Serializer.php b/Serializer.php index f65281492..7044c2f20 100644 --- a/Serializer.php +++ b/Serializer.php @@ -152,7 +152,7 @@ final public function deserialize(mixed $data, string $type, string $format, arr return $this->denormalize($data, $type, $format, $context); } - public function normalize(mixed $data, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $data, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { // If a normalizer supports the given data, use it if ($normalizer = $this->getNormalizer($data, $format, $context)) { @@ -195,7 +195,7 @@ public function normalize(mixed $data, string $format = null, array $context = [ * @throws NotNormalizableValueException * @throws PartialDenormalizationException Occurs when one or more properties of $type fails to denormalize */ - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS], $context['not_normalizable_value_exceptions'])) { throw new LogicException('Passing a value for "not_normalizable_value_exceptions" context key is not allowed.'); @@ -252,12 +252,12 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return null !== $this->getNormalizer($data, $format, $context); } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return isset(self::SCALAR_TYPES[$type]) || null !== $this->getDenormalizer($data, $type, $format, $context); } diff --git a/Tests/Debug/TraceableSerializerTest.php b/Tests/Debug/TraceableSerializerTest.php index 9cc43d40a..ea3c851c6 100644 --- a/Tests/Debug/TraceableSerializerTest.php +++ b/Tests/Debug/TraceableSerializerTest.php @@ -140,7 +140,7 @@ public function deserialize(mixed $data, string $type, string $format, array $co return 'deserialized'; } - public function normalize(mixed $object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { return 'normalized'; } @@ -150,17 +150,17 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return true; } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): mixed + public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed { return 'denormalized'; } - public function supportsDenormalization(mixed $data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool { return true; } diff --git a/Tests/Fixtures/DummyWithWithVariadicParameterConstructor.php b/Tests/Fixtures/DummyWithWithVariadicParameterConstructor.php new file mode 100644 index 000000000..7b3819ac9 --- /dev/null +++ b/Tests/Fixtures/DummyWithWithVariadicParameterConstructor.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +class DummyWithWithVariadicParameterConstructor +{ + private $foo; + + private $bar; + + private $baz; + + public function __construct(string $foo, int $bar = 1, Dummy ...$baz) + { + $this->foo = $foo; + $this->bar = $bar; + $this->baz = $baz; + } + + public function getFoo(): string + { + return $this->foo; + } + + public function getBar(): int + { + return $this->bar; + } + + /** @return Dummy[] */ + public function getBaz(): array + { + return $this->baz; + } +} diff --git a/Tests/Normalizer/AbstractNormalizerTest.php b/Tests/Normalizer/AbstractNormalizerTest.php index 9720d323b..1166a37e9 100644 --- a/Tests/Normalizer/AbstractNormalizerTest.php +++ b/Tests/Normalizer/AbstractNormalizerTest.php @@ -30,6 +30,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\AbstractNormalizerDummy; use Symfony\Component\Serializer\Tests\Fixtures\Annotations\IgnoreDummy; use Symfony\Component\Serializer\Tests\Fixtures\Dummy; +use Symfony\Component\Serializer\Tests\Fixtures\DummyWithWithVariadicParameterConstructor; use Symfony\Component\Serializer\Tests\Fixtures\NullableConstructorArgumentDummy; use Symfony\Component\Serializer\Tests\Fixtures\NullableOptionalConstructorArgumentDummy; use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorDummy; @@ -255,6 +256,25 @@ public static function getNormalizer() yield [new ObjectNormalizer(null, null, null, $extractor)]; } + public function testVariadicConstructorDenormalization() + { + $data = [ + 'foo' => 'woo', + 'baz' => [ + ['foo' => null, 'bar' => null, 'baz' => null, 'qux' => null], + ['foo' => null, 'bar' => null, 'baz' => null, 'qux' => null], + ], + ]; + + $normalizer = new ObjectNormalizer(); + $normalizer->setSerializer(new Serializer([$normalizer])); + + $expected = new DummyWithWithVariadicParameterConstructor('woo', 1, new Dummy(), new Dummy()); + $actual = $normalizer->denormalize($data, DummyWithWithVariadicParameterConstructor::class); + + $this->assertEquals($expected, $actual); + } + public static function getNormalizerWithCustomNameConverter() { $extractor = new PhpDocExtractor(); diff --git a/Tests/Normalizer/AbstractObjectNormalizerTest.php b/Tests/Normalizer/AbstractObjectNormalizerTest.php index fa34dcf20..a07fcd54e 100644 --- a/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -774,7 +774,7 @@ public function testDefaultExcludeFromCacheKey() $object->bar = 'not called'; $normalizer = new class(null, null, null, null, null, [AbstractObjectNormalizer::EXCLUDE_FROM_CACHE_KEY => ['foo']]) extends AbstractObjectNormalizerDummy { - public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool + public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { AbstractObjectNormalizerTest::assertContains('foo', $this->defaultContext[ObjectNormalizer::EXCLUDE_FROM_CACHE_KEY]); $data->bar = 'called'; @@ -862,17 +862,17 @@ protected function getAllowedAttributes($classOrObject, array $context, bool $at return ['foo']; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { return []; } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { return $object->$attribute; } - protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = []): void + protected function setAttributeValue(object $object, string $attribute, $value, ?string $format = null, array $context = []): void { } }; @@ -922,6 +922,116 @@ public function testDenormalizeUntypedStringObject() $this->assertEquals(new DummyWithStringObject(new DummyString()), $actual); $this->assertEquals('', $actual->value->value); } + + public function testProvidingContextCacheKeyGeneratesSameChildContextCacheKey() + { + $foobar = new Dummy(); + $foobar->foo = new EmptyDummy(); + $foobar->bar = 'bar'; + $foobar->baz = 'baz'; + + $normalizer = new class() extends AbstractObjectNormalizerDummy { + public $childContextCacheKey; + + protected function extractAttributes(object $object, string $format = null, array $context = []): array + { + return array_keys((array) $object); + } + + protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + { + return $object->{$attribute}; + } + + protected function createChildContext(array $parentContext, string $attribute, ?string $format): array + { + $childContext = parent::createChildContext($parentContext, $attribute, $format); + $this->childContextCacheKey = $childContext['cache_key']; + + return $childContext; + } + }; + + $serializer = new Serializer([$normalizer]); + + $serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/1']); + $firstChildContextCacheKey = $normalizer->childContextCacheKey; + + $serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/2']); + $secondChildContextCacheKey = $normalizer->childContextCacheKey; + + $this->assertSame($firstChildContextCacheKey, $secondChildContextCacheKey); + } + + public function testChildContextKeepsOriginalContextCacheKey() + { + $foobar = new Dummy(); + $foobar->foo = new EmptyDummy(); + $foobar->bar = 'bar'; + $foobar->baz = 'baz'; + + $normalizer = new class() extends AbstractObjectNormalizerDummy { + public $childContextCacheKey; + + protected function extractAttributes(object $object, string $format = null, array $context = []): array + { + return array_keys((array) $object); + } + + protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + { + return $object->{$attribute}; + } + + protected function createChildContext(array $parentContext, string $attribute, ?string $format): array + { + $childContext = parent::createChildContext($parentContext, $attribute, $format); + $this->childContextCacheKey = $childContext['cache_key']; + + return $childContext; + } + }; + + $serializer = new Serializer([$normalizer]); + $serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/1']); + + $this->assertSame('hardcoded-foo', $normalizer->childContextCacheKey); + } + + public function testChildContextCacheKeyStaysFalseWhenOriginalCacheKeyIsFalse() + { + $foobar = new Dummy(); + $foobar->foo = new EmptyDummy(); + $foobar->bar = 'bar'; + $foobar->baz = 'baz'; + + $normalizer = new class() extends AbstractObjectNormalizerDummy { + public $childContextCacheKey; + + protected function extractAttributes(object $object, string $format = null, array $context = []): array + { + return array_keys((array) $object); + } + + protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + { + return $object->{$attribute}; + } + + protected function createChildContext(array $parentContext, string $attribute, ?string $format): array + { + $childContext = parent::createChildContext($parentContext, $attribute, $format); + $this->childContextCacheKey = $childContext['cache_key']; + + return $childContext; + } + }; + + $serializer = new Serializer([$normalizer]); + $serializer->normalize($foobar, null, ['cache_key' => false]); + + $this->assertFalse($normalizer->childContextCacheKey); + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -931,26 +1041,26 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { return []; } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { } - protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = []): void + protected function setAttributeValue(object $object, string $attribute, $value, ?string $format = null, array $context = []): void { $object->$attribute = $value; } - protected function isAllowedAttribute($classOrObject, string $attribute, string $format = null, array $context = []): bool + protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool { return \in_array($attribute, ['foo', 'baz', 'quux', 'value']); } - public function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null): object + public function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, ?string $format = null): object { return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format); } @@ -1140,15 +1250,15 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { } - protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = []): void + protected function setAttributeValue(object $object, string $attribute, $value, ?string $format = null, array $context = []): void { if (property_exists($object, $attribute)) { $object->$attribute = $value; @@ -1238,7 +1348,7 @@ public function deserialize($data, string $type, string $format, array $context { } - public function denormalize($data, string $type, string $format = null, array $context = []): mixed + public function denormalize($data, string $type, ?string $format = null, array $context = []): mixed { foreach ($this->normalizers as $normalizer) { if ($normalizer instanceof DenormalizerInterface && $normalizer->supportsDenormalization($data, $type, $format, $context)) { @@ -1254,7 +1364,7 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool { return true; } @@ -1267,25 +1377,25 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - protected function extractAttributes(object $object, string $format = null, array $context = []): array + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array { } - protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = []): mixed + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []): mixed { } - protected function setAttributeValue(object $object, string $attribute, $value, string $format = null, array $context = []): void + protected function setAttributeValue(object $object, string $attribute, $value, ?string $format = null, array $context = []): void { $object->$attribute = $value; } - protected function isAllowedAttribute($classOrObject, string $attribute, string $format = null, array $context = []): bool + protected function isAllowedAttribute($classOrObject, string $attribute, ?string $format = null, array $context = []): bool { return true; } - public function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null): object + public function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, ?string $format = null): object { return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format); } @@ -1309,7 +1419,7 @@ class ArrayDenormalizerDummy implements DenormalizerInterface, SerializerAwareIn /** * @throws NotNormalizableValueException */ - public function denormalize($data, string $type, string $format = null, array $context = []): mixed + public function denormalize($data, string $type, ?string $format = null, array $context = []): mixed { $serializer = $this->serializer; $type = substr($type, 0, -2); @@ -1326,7 +1436,7 @@ public function getSupportedTypes(?string $format): array return $this->serializer->getSupportedTypes($format); } - public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool { return str_ends_with($type, '[]') && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); diff --git a/Tests/Normalizer/ConstraintViolationListNormalizerTest.php b/Tests/Normalizer/ConstraintViolationListNormalizerTest.php index 8e8df388d..bb045b8ae 100644 --- a/Tests/Normalizer/ConstraintViolationListNormalizerTest.php +++ b/Tests/Normalizer/ConstraintViolationListNormalizerTest.php @@ -116,7 +116,7 @@ public function testNormalizeWithNameConverter() /** * @dataProvider payloadFieldsProvider */ - public function testNormalizePayloadFields($fields, array $expected = null) + public function testNormalizePayloadFields($fields, ?array $expected = null) { $constraint = new NotNull(); $constraint->payload = ['severity' => 'warning', 'anotherField2' => 'aValue']; diff --git a/Tests/Normalizer/Features/CallbacksObject.php b/Tests/Normalizer/Features/CallbacksObject.php index 19ad3f547..d484f8b8a 100644 --- a/Tests/Normalizer/Features/CallbacksObject.php +++ b/Tests/Normalizer/Features/CallbacksObject.php @@ -20,7 +20,7 @@ class CallbacksObject */ public $foo; - public function __construct($bar = null, string $foo = null) + public function __construct($bar = null, ?string $foo = null) { $this->bar = $bar; $this->foo = $foo; diff --git a/Tests/Normalizer/ObjectNormalizerTest.php b/Tests/Normalizer/ObjectNormalizerTest.php index 153cab759..3658f1e1c 100644 --- a/Tests/Normalizer/ObjectNormalizerTest.php +++ b/Tests/Normalizer/ObjectNormalizerTest.php @@ -93,7 +93,7 @@ protected function setUp(): void $this->createNormalizer(); } - private function createNormalizer(array $defaultContext = [], ClassMetadataFactoryInterface $classMetadataFactory = null) + private function createNormalizer(array $defaultContext = [], ?ClassMetadataFactoryInterface $classMetadataFactory = null) { $this->serializer = $this->createMock(ObjectSerializerNormalizer::class); $this->normalizer = new ObjectNormalizer($classMetadataFactory, null, null, null, null, null, $defaultContext); @@ -775,12 +775,12 @@ public function testDenormalizeFalsePseudoType() public function testAdvancedNameConverter() { $nameConverter = new class() implements AdvancedNameConverterInterface { - public function normalize(string $propertyName, string $class = null, string $format = null, array $context = []): string + public function normalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return sprintf('%s-%s-%s-%s', $propertyName, $class, $format, $context['foo']); } - public function denormalize(string $propertyName, string $class = null, string $format = null, array $context = []): string + public function denormalize(string $propertyName, ?string $class = null, ?string $format = null, array $context = []): string { return sprintf('%s-%s-%s-%s', $propertyName, $class, $format, $context['foo']); } @@ -1074,7 +1074,7 @@ class DummyWithConstructorObjectAndDefaultValue private $foo; private $inner; - public function __construct($foo = 'a', ObjectInner $inner = null) + public function __construct($foo = 'a', ?ObjectInner $inner = null) { $this->foo = $foo; $this->inner = $inner; diff --git a/Tests/Normalizer/TestDenormalizer.php b/Tests/Normalizer/TestDenormalizer.php index 70518c797..cd51b3c19 100644 --- a/Tests/Normalizer/TestDenormalizer.php +++ b/Tests/Normalizer/TestDenormalizer.php @@ -20,7 +20,7 @@ */ class TestDenormalizer implements DenormalizerInterface { - public function denormalize($data, string $type, string $format = null, array $context = []): mixed + public function denormalize($data, string $type, ?string $format = null, array $context = []): mixed { } @@ -29,7 +29,7 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool + public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool { return true; } diff --git a/Tests/Normalizer/TestNormalizer.php b/Tests/Normalizer/TestNormalizer.php index 26e5917e7..941fef42b 100644 --- a/Tests/Normalizer/TestNormalizer.php +++ b/Tests/Normalizer/TestNormalizer.php @@ -20,7 +20,7 @@ */ class TestNormalizer implements NormalizerInterface { - public function normalize($object, string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null + public function normalize($object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null { return null; } @@ -30,7 +30,7 @@ public function getSupportedTypes(?string $format): array return ['*' => false]; } - public function supportsNormalization($data, string $format = null, array $context = []): bool + public function supportsNormalization($data, ?string $format = null, array $context = []): bool { return true; } diff --git a/Tests/SerializerTest.php b/Tests/SerializerTest.php index daabf8e6c..2a79e9a97 100644 --- a/Tests/SerializerTest.php +++ b/Tests/SerializerTest.php @@ -1064,7 +1064,7 @@ public function testCollectDenormalizationErrors(?ClassMetadataFactory $classMet 'expectedTypes' => [ 'unknown', ], - 'path' => 'php74FullWithConstructor', + 'path' => 'php74FullWithConstructor.constructorArgument', 'useMessageForUser' => true, 'message' => 'Failed to create object because the class misses the "constructorArgument" property.', ], @@ -1197,6 +1197,70 @@ public function testCollectDenormalizationErrors2(?ClassMetadataFactory $classMe $this->assertSame($expected, $exceptionsAsArray); } + public function testCollectDenormalizationErrorsWithoutTypeExtractor() + { + $json = ' + { + "string": [], + "int": [], + "float": [] + }'; + + $serializer = new Serializer([new ObjectNormalizer()], ['json' => new JsonEncoder()]); + + try { + $serializer->deserialize($json, Php74Full::class, 'json', [ + DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS => true, + ]); + + $this->fail(); + } catch (\Throwable $th) { + $this->assertInstanceOf(PartialDenormalizationException::class, $th); + } + + $this->assertInstanceOf(Php74Full::class, $th->getData()); + + $exceptionsAsArray = array_map(fn (NotNormalizableValueException $e): array => [ + 'currentType' => $e->getCurrentType(), + 'expectedTypes' => $e->getExpectedTypes(), + 'path' => $e->getPath(), + 'useMessageForUser' => $e->canUseMessageForUser(), + 'message' => $e->getMessage(), + ], $th->getErrors()); + + $expected = [ + [ + 'currentType' => 'array', + 'expectedTypes' => [ + 'unknown', + ], + 'path' => 'string', + 'useMessageForUser' => false, + 'message' => 'Failed to denormalize attribute "string" value for class "Symfony\\Component\\Serializer\\Tests\\Fixtures\\Php74Full": Expected argument of type "string", "array" given at property path "string".', + ], + [ + 'currentType' => 'array', + 'expectedTypes' => [ + 'unknown', + ], + 'path' => 'int', + 'useMessageForUser' => false, + 'message' => 'Failed to denormalize attribute "int" value for class "Symfony\\Component\\Serializer\\Tests\\Fixtures\\Php74Full": Expected argument of type "int", "array" given at property path "int".', + ], + [ + 'currentType' => 'array', + 'expectedTypes' => [ + 'unknown', + ], + 'path' => 'float', + 'useMessageForUser' => false, + 'message' => 'Failed to denormalize attribute "float" value for class "Symfony\\Component\\Serializer\\Tests\\Fixtures\\Php74Full": Expected argument of type "float", "array" given at property path "float".', + ], + ]; + + $this->assertSame($expected, $exceptionsAsArray); + } + /** * @dataProvider provideCollectDenormalizationErrors */ @@ -1248,7 +1312,7 @@ public function testCollectDenormalizationErrorsWithConstructor(?ClassMetadataFa 'expectedTypes' => [ 'unknown', ], - 'path' => null, + 'path' => 'string', 'useMessageForUser' => true, 'message' => 'Failed to create object because the class misses the "string" property.', ], @@ -1257,7 +1321,7 @@ public function testCollectDenormalizationErrorsWithConstructor(?ClassMetadataFa 'expectedTypes' => [ 'unknown', ], - 'path' => null, + 'path' => 'int', 'useMessageForUser' => true, 'message' => 'Failed to create object because the class misses the "int" property.', ], @@ -1307,7 +1371,7 @@ public function testCollectDenormalizationErrorsWithInvalidConstructorTypes() [ 'currentType' => 'string', 'expectedTypes' => [ - 0 => 'bool', + 'bool', ], 'path' => 'bool', 'useMessageForUser' => false, @@ -1316,7 +1380,7 @@ public function testCollectDenormalizationErrorsWithInvalidConstructorTypes() [ 'currentType' => 'bool', 'expectedTypes' => [ - 0 => 'int', + 'int', ], 'path' => 'int', 'useMessageForUser' => false, @@ -1544,7 +1608,7 @@ public function testPartialDenormalizationWithMissingConstructorTypes() 'expectedTypes' => [ 'unknown', ], - 'path' => null, + 'path' => 'two', 'useMessageForUser' => true, 'message' => 'Failed to create object because the class misses the "two" property.', ], diff --git a/composer.json b/composer.json index 5efabab21..d0f66972f 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/mime": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", + "symfony/property-access": "^5.4.26|^6.3", "symfony/property-info": "^5.4.24|^6.2.11", "symfony/uid": "^5.4|^6.0", "symfony/validator": "^5.4|^6.0",