diff --git a/src/Metadata/ClassMetadata.php b/src/Metadata/ClassMetadata.php index 24b176d8..9b3c3083 100644 --- a/src/Metadata/ClassMetadata.php +++ b/src/Metadata/ClassMetadata.php @@ -5,6 +5,7 @@ namespace Patchlevel\Hydrator\Metadata; use ReflectionClass; +use ReflectionParameter; /** * @phpstan-type serialized array{ @@ -23,6 +24,9 @@ final class ClassMetadata /** @var array */ public readonly array $properties; + /** @var array|null */ + private array|null $promotedConstructorDefaults = null; + /** * @param ReflectionClass $reflection * @param list $properties @@ -62,6 +66,32 @@ public function newInstance(): object return $this->reflection->newInstanceWithoutConstructor(); } + /** @return array */ + public function promotedConstructorDefaults(): array + { + if ($this->promotedConstructorDefaults !== null) { + return $this->promotedConstructorDefaults; + } + + $constructor = $this->reflection->getConstructor(); + + if (!$constructor) { + return $this->promotedConstructorDefaults = []; + } + + $result = []; + + foreach ($constructor->getParameters() as $parameter) { + if (!$parameter->isPromoted() || !$parameter->isDefaultValueAvailable()) { + continue; + } + + $result[$parameter->getName()] = $parameter; + } + + return $this->promotedConstructorDefaults = $result; + } + /** @return serialized */ public function __serialize(): array { diff --git a/src/Middleware/TransformMiddleware.php b/src/Middleware/TransformMiddleware.php index d9464c2a..c8c44fa0 100644 --- a/src/Middleware/TransformMiddleware.php +++ b/src/Middleware/TransformMiddleware.php @@ -9,7 +9,6 @@ use Patchlevel\Hydrator\Metadata\ClassMetadata; use Patchlevel\Hydrator\NormalizationFailure; use Patchlevel\Hydrator\TypeMismatch; -use ReflectionParameter; use Throwable; use TypeError; @@ -43,9 +42,7 @@ public function hydrate(ClassMetadata $metadata, array $data, array $context, St continue; } - if ($constructorParameters === null) { - $constructorParameters = $this->promotedConstructorParametersWithDefaultValue($metadata); - } + $constructorParameters ??= $metadata->promotedConstructorDefaults(); if (!array_key_exists($propertyMetadata->propertyName, $constructorParameters)) { continue; @@ -138,31 +135,4 @@ public function extract(ClassMetadata $metadata, object $object, array $context, return $data; } - - /** @return array */ - private function promotedConstructorParametersWithDefaultValue(ClassMetadata $metadata): array - { - $constructor = $metadata->reflection->getConstructor(); - - if (!$constructor) { - return []; - } - - $parameters = $constructor->getParameters(); - $result = []; - - foreach ($parameters as $parameter) { - if (!$parameter->isPromoted()) { - continue; - } - - if (!$parameter->isDefaultValueAvailable()) { - continue; - } - - $result[$parameter->getName()] = $parameter; - } - - return $result; - } }