11
11
use TypeLang \Mapper \Exception \Mapping \RuntimeException ;
12
12
use TypeLang \Mapper \Mapping \Metadata \ClassMetadata ;
13
13
use TypeLang \Mapper \Mapping \Metadata \DiscriminatorMapMetadata ;
14
+ use TypeLang \Mapper \Mapping \Metadata \PropertyMetadata ;
14
15
use TypeLang \Mapper \Runtime \Context ;
15
16
use TypeLang \Mapper \Runtime \Path \Entry \ObjectEntry ;
16
17
use TypeLang \Mapper \Runtime \Path \Entry \ObjectPropertyEntry ;
@@ -34,7 +35,56 @@ public function __construct(
34
35
35
36
public function match (mixed $ value , Context $ context ): bool
36
37
{
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 ;
38
88
}
39
89
40
90
/**
@@ -165,10 +215,7 @@ private function denormalizeObject(array $value, object $object, Context $contex
165
215
// In case of value has been passed
166
216
case \array_key_exists ($ meta ->getExportName (), $ value ):
167
217
$ 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 );
172
219
173
220
try {
174
221
$ element = $ type ->cast ($ element , $ entrance );
0 commit comments