Skip to content

Commit fb412ca

Browse files
committed
Add class type extended matching
1 parent 3bc7a86 commit fb412ca

File tree

1 file changed

+52
-5
lines changed

1 file changed

+52
-5
lines changed

src/Type/ClassType/ClassTypeDenormalizer.php

+52-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use TypeLang\Mapper\Exception\Mapping\RuntimeException;
1212
use TypeLang\Mapper\Mapping\Metadata\ClassMetadata;
1313
use TypeLang\Mapper\Mapping\Metadata\DiscriminatorMapMetadata;
14+
use TypeLang\Mapper\Mapping\Metadata\PropertyMetadata;
1415
use TypeLang\Mapper\Runtime\Context;
1516
use TypeLang\Mapper\Runtime\Path\Entry\ObjectEntry;
1617
use TypeLang\Mapper\Runtime\Path\Entry\ObjectPropertyEntry;
@@ -34,7 +35,56 @@ public function __construct(
3435

3536
public function match(mixed $value, Context $context): bool
3637
{
37-
return \is_object($value) || \is_array($value);
38+
return (\is_array($value) || \is_object($value))
39+
&& $this->matchRequiredProperties((array) $value, $context);
40+
}
41+
42+
/**
43+
* @throws \Throwable
44+
*/
45+
private function getPropertyType(PropertyMetadata $meta, Context $context): TypeInterface
46+
{
47+
// Fetch field type
48+
$info = $meta->findTypeInfo();
49+
50+
if ($info === null) {
51+
return $context->getTypeByDefinition('mixed');
52+
}
53+
54+
return $info->getType();
55+
}
56+
57+
/**
58+
* @param array<array-key, mixed> $payload
59+
*/
60+
private function matchRequiredProperties(array $payload, Context $context): bool
61+
{
62+
foreach ($this->metadata->getProperties() as $meta) {
63+
// Match property for existence
64+
if (!\array_key_exists($meta->getExportName(), $payload)) {
65+
// Skip all properties with defaults
66+
if ($meta->hasDefaultValue()) {
67+
continue;
68+
}
69+
70+
return false;
71+
}
72+
73+
// Fetch field value and type
74+
try {
75+
$value = $payload[$meta->getExportName()];
76+
$type = $this->getPropertyType($meta, $context);
77+
} catch (\Throwable) {
78+
return false;
79+
}
80+
81+
// Assert valid type
82+
if (!$type->match($value, $context)) {
83+
return false;
84+
}
85+
}
86+
87+
return true;
3888
}
3989

4090
/**
@@ -165,10 +215,7 @@ private function denormalizeObject(array $value, object $object, Context $contex
165215
// In case of value has been passed
166216
case \array_key_exists($meta->getExportName(), $value):
167217
$element = $value[$meta->getExportName()];
168-
169-
// Fetch field type
170-
$info = $meta->findTypeInfo();
171-
$type = $info !== null ? $info->getType() : $context->getTypeByDefinition('mixed');
218+
$type = $this->getPropertyType($meta, $context);
172219

173220
try {
174221
$element = $type->cast($element, $entrance);

0 commit comments

Comments
 (0)