From e4b82300d8757fb979c1b035964379a572eadad9 Mon Sep 17 00:00:00 2001 From: Rico Sonntag Date: Fri, 14 Nov 2025 10:32:10 +0100 Subject: [PATCH] docs(value): expand phpdoc for conversion components --- src/JsonMapper/Value/CustomTypeRegistry.php | 20 +++++++- .../BuiltinValueConversionStrategy.php | 47 +++++++++++++++++-- .../CollectionValueConversionStrategy.php | 22 ++++++++- .../CustomTypeValueConversionStrategy.php | 23 +++++++++ .../DateTimeValueConversionStrategy.php | 18 +++++++ .../Strategy/EnumValueConversionStrategy.php | 18 +++++++ .../Strategy/NullValueConversionStrategy.php | 18 +++++++ .../ObjectTypeConversionGuardTrait.php | 17 +++++-- .../ObjectValueConversionStrategy.php | 27 +++++++++-- .../PassthroughValueConversionStrategy.php | 18 +++++++ .../ValueConversionStrategyInterface.php | 18 +++++++ src/JsonMapper/Value/ValueConverter.php | 13 ++++- 12 files changed, 247 insertions(+), 12 deletions(-) diff --git a/src/JsonMapper/Value/CustomTypeRegistry.php b/src/JsonMapper/Value/CustomTypeRegistry.php index 7b99dd8..a8aaff4 100644 --- a/src/JsonMapper/Value/CustomTypeRegistry.php +++ b/src/JsonMapper/Value/CustomTypeRegistry.php @@ -30,7 +30,10 @@ final class CustomTypeRegistry /** * Registers the converter for the provided class name. * - * @param callable(mixed):mixed|callable(mixed, MappingContext):mixed $converter + * @param string $className Fully-qualified class name handled by the converter. + * @param callable(mixed):mixed|callable(mixed, MappingContext):mixed $converter Callback responsible for creating the destination value. + * + * @return void */ public function register(string $className, callable $converter): void { @@ -39,6 +42,10 @@ public function register(string $className, callable $converter): void /** * Registers a custom type handler. + * + * @param TypeHandlerInterface $handler Handler performing support checks and conversion for a particular type. + * + * @return void */ public function registerHandler(TypeHandlerInterface $handler): void { @@ -47,6 +54,11 @@ public function registerHandler(TypeHandlerInterface $handler): void /** * Returns TRUE if a handler for the type exists. + * + * @param Type $type Type information describing the target property. + * @param mixed $value JSON value that should be converted. + * + * @return bool TRUE when at least one registered handler supports the value. */ public function supports(Type $type, mixed $value): bool { @@ -61,6 +73,12 @@ public function supports(Type $type, mixed $value): bool /** * Executes the converter for the class. + * + * @param Type $type Type information describing the target property. + * @param mixed $value JSON value that should be converted. + * @param MappingContext $context Mapping context providing runtime configuration and state. + * + * @return mixed Converted value returned by the first supporting handler. */ public function convert(Type $type, mixed $value, MappingContext $context): mixed { diff --git a/src/JsonMapper/Value/Strategy/BuiltinValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/BuiltinValueConversionStrategy.php index ee4a602..2556fcb 100644 --- a/src/JsonMapper/Value/Strategy/BuiltinValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/BuiltinValueConversionStrategy.php @@ -40,11 +40,29 @@ */ final class BuiltinValueConversionStrategy implements ValueConversionStrategyInterface { + /** + * Determines whether the provided type represents a builtin PHP value. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the target type is a builtin PHP type. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return $type instanceof BuiltinType; } + /** + * Converts the provided value to the builtin type defined by the metadata. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Value cast to the requested builtin type when possible. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { assert($type instanceof BuiltinType); @@ -64,7 +82,12 @@ public function convert(mixed $value, Type $type, MappingContext $context): mixe } /** - * @param BuiltinType $type + * Normalizes common scalar representations before the conversion happens. + * + * @param mixed $value Raw value coming from the input payload. + * @param BuiltinType $type Type metadata describing the target property. + * + * @return mixed Normalized value that is compatible with the builtin type conversion. */ private function normalizeValue(mixed $value, BuiltinType $type): mixed { @@ -126,7 +149,13 @@ private function normalizeValue(mixed $value, BuiltinType $type): mixed } /** - * @param BuiltinType $type + * Validates that the value matches the builtin type or records a mismatch. + * + * @param mixed $value Normalized value used during conversion. + * @param BuiltinType $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return void */ private function guardCompatibility(mixed $value, BuiltinType $type, MappingContext $context): void { @@ -160,13 +189,25 @@ private function guardCompatibility(mixed $value, BuiltinType $type, MappingCont } /** - * @param BuiltinType $type + * Determines whether the builtin type allows null values. + * + * @param BuiltinType $type Type metadata describing the target property. + * + * @return bool TRUE when the builtin type can be null. */ private function allowsNull(BuiltinType $type): bool { return $type->isNullable(); } + /** + * Checks whether the value matches the builtin type identifier. + * + * @param mixed $value Normalized value used during conversion. + * @param TypeIdentifier $identifier Identifier of the builtin type to check against. + * + * @return bool TRUE when the value matches the identifier requirements. + */ private function isCompatibleValue(mixed $value, TypeIdentifier $identifier): bool { return match ($identifier->value) { diff --git a/src/JsonMapper/Value/Strategy/CollectionValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/CollectionValueConversionStrategy.php index 12d3db5..f3f7e05 100644 --- a/src/JsonMapper/Value/Strategy/CollectionValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/CollectionValueConversionStrategy.php @@ -24,18 +24,38 @@ final readonly class CollectionValueConversionStrategy implements ValueConversionStrategyInterface { /** - * @param CollectionFactoryInterface $collectionFactory + * Creates the strategy with the provided collection factory. + * + * @param CollectionFactoryInterface $collectionFactory Factory responsible for instantiating collections during conversion. */ public function __construct( private CollectionFactoryInterface $collectionFactory, ) { } + /** + * Determines whether the supplied type represents a collection. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the target type is a collection type. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return $type instanceof CollectionType; } + /** + * Converts the JSON value into a collection instance. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Collection created by the factory based on the type metadata. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { assert($type instanceof CollectionType); diff --git a/src/JsonMapper/Value/Strategy/CustomTypeValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/CustomTypeValueConversionStrategy.php index c408a85..5093d59 100644 --- a/src/JsonMapper/Value/Strategy/CustomTypeValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/CustomTypeValueConversionStrategy.php @@ -20,16 +20,39 @@ */ final readonly class CustomTypeValueConversionStrategy implements ValueConversionStrategyInterface { + /** + * Creates the strategy backed by the custom type registry. + * + * @param CustomTypeRegistry $registry Registry containing the custom handlers. + */ public function __construct( private CustomTypeRegistry $registry, ) { } + /** + * Determines whether the registry can handle the provided type. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the registry has a matching custom handler. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return $this->registry->supports($type, $value); } + /** + * Converts the value using the registered handler. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Value produced by the registered custom handler. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { return $this->registry->convert($type, $value, $context); diff --git a/src/JsonMapper/Value/Strategy/DateTimeValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/DateTimeValueConversionStrategy.php index ac60f44..8c54049 100644 --- a/src/JsonMapper/Value/Strategy/DateTimeValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/DateTimeValueConversionStrategy.php @@ -32,6 +32,15 @@ final class DateTimeValueConversionStrategy implements ValueConversionStrategyIn { use ObjectTypeConversionGuardTrait; + /** + * Determines whether the requested type is a supported date or interval class. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the type represents a supported date/time object. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { $objectType = $this->extractObjectType($type); @@ -45,6 +54,15 @@ public function supports(mixed $value, Type $type, MappingContext $context): boo return is_a($className, DateTimeImmutable::class, true) || is_a($className, DateInterval::class, true); } + /** + * Converts ISO-8601 strings and timestamps into the desired date/time object. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Instance of the configured date/time class. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { return $this->convertObjectValue( diff --git a/src/JsonMapper/Value/Strategy/EnumValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/EnumValueConversionStrategy.php index 1672d55..db4b1c6 100644 --- a/src/JsonMapper/Value/Strategy/EnumValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/EnumValueConversionStrategy.php @@ -31,6 +31,15 @@ final class EnumValueConversionStrategy implements ValueConversionStrategyInterf { use ObjectTypeConversionGuardTrait; + /** + * Determines whether the provided type is a backed enum. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the target type resolves to a backed enum. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { $objectType = $this->extractObjectType($type); @@ -48,6 +57,15 @@ public function supports(mixed $value, Type $type, MappingContext $context): boo return is_a($className, BackedEnum::class, true); } + /** + * Converts the JSON scalar into the matching enum case. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Backed enum instance returned by the case factory method. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { return $this->convertObjectValue( diff --git a/src/JsonMapper/Value/Strategy/NullValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/NullValueConversionStrategy.php index 72a3a68..535a4d0 100644 --- a/src/JsonMapper/Value/Strategy/NullValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/NullValueConversionStrategy.php @@ -19,11 +19,29 @@ */ final class NullValueConversionStrategy implements ValueConversionStrategyInterface { + /** + * Determines whether the incoming value represents a null assignment. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the value is exactly null. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return $value === null; } + /** + * Returns null to preserve the absence of a value. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return null Always returns null for supported values. + */ public function convert(mixed $value, Type $type, MappingContext $context): null { return null; diff --git a/src/JsonMapper/Value/Strategy/ObjectTypeConversionGuardTrait.php b/src/JsonMapper/Value/Strategy/ObjectTypeConversionGuardTrait.php index 1c9b474..4633f0b 100644 --- a/src/JsonMapper/Value/Strategy/ObjectTypeConversionGuardTrait.php +++ b/src/JsonMapper/Value/Strategy/ObjectTypeConversionGuardTrait.php @@ -24,7 +24,9 @@ trait ObjectTypeConversionGuardTrait /** * Returns the provided type when it represents an object with a class name. * - * @return ObjectType|null + * @param Type $type Type metadata describing the target property. + * + * @return ObjectType|null Object type when the metadata targets a concrete class; otherwise null. */ private function extractObjectType(Type $type): ?ObjectType { @@ -42,7 +44,11 @@ private function extractObjectType(Type $type): ?ObjectType /** * Ensures null values comply with the target object's nullability. * - * @param ObjectType $type + * @param mixed $value Raw value coming from the input payload. + * @param ObjectType $type Object type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return void */ private function guardNullableValue(mixed $value, ObjectType $type, MappingContext $context): void { @@ -60,7 +66,12 @@ private function guardNullableValue(mixed $value, ObjectType $type, MappingConte /** * Executes the provided converter when a valid object type is available. * - * @param callable(string, mixed): mixed $converter + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * @param mixed $value Raw value coming from the input payload. + * @param callable(string, mixed): mixed $converter Callback that performs the actual conversion when a class-string is available. + * + * @return mixed Result from the converter or the original value when no object type was detected. */ private function convertObjectValue(Type $type, MappingContext $context, mixed $value, callable $converter): mixed { diff --git a/src/JsonMapper/Value/Strategy/ObjectValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/ObjectValueConversionStrategy.php index 51fb6ae..414e1cd 100644 --- a/src/JsonMapper/Value/Strategy/ObjectValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/ObjectValueConversionStrategy.php @@ -29,7 +29,10 @@ final readonly class ObjectValueConversionStrategy implements ValueConversionStrategyInterface { /** - * @param Closure(mixed, class-string, MappingContext):mixed $mapper + * Creates the strategy with the class resolver and mapper callback. + * + * @param ClassResolver $classResolver Resolver used to select the concrete class to instantiate. + * @param Closure(mixed, class-string, MappingContext):mixed $mapper Callback responsible for mapping values into objects. */ public function __construct( private ClassResolver $classResolver, @@ -37,11 +40,29 @@ public function __construct( ) { } + /** + * Determines whether the metadata describes an object type. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the target type represents an object. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return $type instanceof ObjectType; } + /** + * Delegates conversion to the mapper for the resolved class. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Value returned by the mapper callback. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { if (!($type instanceof ObjectType)) { @@ -68,9 +89,9 @@ public function convert(mixed $value, Type $type, MappingContext $context): mixe /** * Resolves the class name from the provided object type. * - * @param ObjectType $type + * @param ObjectType $type Object type metadata describing the target property. * - * @return class-string + * @return class-string Concrete class name extracted from the metadata. */ private function resolveClassName(ObjectType $type): string { diff --git a/src/JsonMapper/Value/Strategy/PassthroughValueConversionStrategy.php b/src/JsonMapper/Value/Strategy/PassthroughValueConversionStrategy.php index 74aba11..f5ddf06 100644 --- a/src/JsonMapper/Value/Strategy/PassthroughValueConversionStrategy.php +++ b/src/JsonMapper/Value/Strategy/PassthroughValueConversionStrategy.php @@ -19,11 +19,29 @@ */ final class PassthroughValueConversionStrategy implements ValueConversionStrategyInterface { + /** + * Always supports conversion and acts as the terminal strategy. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool Always TRUE so the strategy can act as the final fallback. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool { return true; } + /** + * Returns the original value without modification. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Unmodified value passed through from the input. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { return $value; diff --git a/src/JsonMapper/Value/Strategy/ValueConversionStrategyInterface.php b/src/JsonMapper/Value/Strategy/ValueConversionStrategyInterface.php index ba2b471..f37020d 100644 --- a/src/JsonMapper/Value/Strategy/ValueConversionStrategyInterface.php +++ b/src/JsonMapper/Value/Strategy/ValueConversionStrategyInterface.php @@ -19,7 +19,25 @@ */ interface ValueConversionStrategyInterface { + /** + * Determines whether the strategy can convert the provided value for the requested type. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return bool TRUE when the strategy should perform the conversion. + */ public function supports(mixed $value, Type $type, MappingContext $context): bool; + /** + * Converts the value into a representation compatible with the requested type. + * + * @param mixed $value Raw value coming from the input payload. + * @param Type $type Type metadata describing the target property. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Result of the conversion when the strategy supports the value. + */ public function convert(mixed $value, Type $type, MappingContext $context): mixed; } diff --git a/src/JsonMapper/Value/ValueConverter.php b/src/JsonMapper/Value/ValueConverter.php index b9c183e..0f68da6 100644 --- a/src/JsonMapper/Value/ValueConverter.php +++ b/src/JsonMapper/Value/ValueConverter.php @@ -30,6 +30,10 @@ final class ValueConverter /** * Registers the strategy at the end of the chain. + * + * @param ValueConversionStrategyInterface $strategy Strategy executed when it supports the provided value. + * + * @return void */ public function addStrategy(ValueConversionStrategyInterface $strategy): void { @@ -38,6 +42,12 @@ public function addStrategy(ValueConversionStrategyInterface $strategy): void /** * Converts the value using the first matching strategy. + * + * @param mixed $value Raw JSON value that needs to be converted. + * @param Type $type Target type metadata that should be satisfied by the conversion result. + * @param MappingContext $context Mapping context providing configuration such as strict mode. + * + * @return mixed Result from the first strategy that declares support for the value. */ public function convert(mixed $value, Type $type, MappingContext $context): mixed { @@ -48,6 +58,7 @@ public function convert(mixed $value, Type $type, MappingContext $context): mixe } throw new LogicException( - sprintf('No conversion strategy available for type %s.', $type::class)); + sprintf('No conversion strategy available for type %s.', $type::class) + ); } }