2929use Orisai \ObjectMapper \Types \MessageType ;
3030use Orisai \ObjectMapper \Types \Type ;
3131use ReflectionProperty ;
32- use function array_diff ;
3332use function array_key_exists ;
3433use function array_keys ;
3534use function array_map ;
@@ -221,8 +220,11 @@ private function handleFields(
221220 DynamicContext $ dynamic
222221 ): array
223222 {
224- $ data = $ this ->handleSentFields ($ data , $ call , $ dynamic );
225- $ data = $ this ->handleMissingFields ($ data , $ call , $ dynamic );
223+ $ meta = $ call ->getMeta ();
224+ $ fieldsMeta = $ meta ->getFields ();
225+
226+ $ data = $ this ->handleSentFields ($ data , $ call , $ dynamic , $ fieldsMeta );
227+ $ data = $ this ->handleMissingFields ($ data , $ call , $ dynamic , $ fieldsMeta );
226228
227229 $ type = $ call ->getTypeIfInitialized ();
228230
@@ -236,28 +238,32 @@ private function handleFields(
236238 /**
237239 * @param array<int|string, mixed> $data
238240 * @param ProcessorCallContext<MappedObject> $call
241+ * @param array<int|string, FieldRuntimeMeta> $fieldsMeta
242+ * @param-out array<int|string, FieldRuntimeMeta> $fieldsMeta
239243 * @return array<int|string, mixed>
240244 */
241245 private function handleSentFields (
242246 array $ data ,
243247 ProcessorCallContext $ call ,
244- DynamicContext $ dynamic
248+ DynamicContext $ dynamic ,
249+ array &$ fieldsMeta
245250 ): array
246251 {
247252 $ type = null ;
248253 $ options = $ dynamic ->getOptions ();
249254
250- $ meta = $ call ->getMeta ();
251- $ fieldsMeta = $ meta ->getFields ();
252255 $ fieldNames = array_keys ($ fieldsMeta );
253256
254257 foreach ($ data as $ fieldName => $ value ) {
255258 // Skip invalid field
256259 if ($ type !== null && $ type ->isFieldInvalid ($ fieldName )) {
260+ unset($ fieldsMeta [$ fieldName ]);
261+
257262 continue ;
258263 }
259264
260265 $ fieldMeta = $ fieldsMeta [$ fieldName ] ?? null ;
266+ unset($ fieldsMeta [$ fieldName ]);
261267
262268 // Unknown field
263269 if ($ fieldMeta === null ) {
@@ -321,60 +327,45 @@ private function handleSentFields(
321327 /**
322328 * @param array<int|string, mixed> $data
323329 * @param ProcessorCallContext<MappedObject> $call
324- * @return array<int|string>
325- */
326- private function findMissingFields (array $ data , ProcessorCallContext $ call ): array
327- {
328- $ meta = $ call ->getMeta ();
329-
330- return array_diff (
331- array_keys ($ meta ->getFields ()),
332- array_keys ($ data ),
333- );
334- }
335-
336- /**
337- * @param array<int|string, mixed> $data
338- * @param ProcessorCallContext<MappedObject> $call
330+ * @param array<int|string, FieldRuntimeMeta> $fieldsMeta
339331 * @return array<int|string, mixed>
340332 */
341333 private function handleMissingFields (
342334 array $ data ,
343335 ProcessorCallContext $ call ,
344- DynamicContext $ dynamic
336+ DynamicContext $ dynamic ,
337+ array $ fieldsMeta
345338 ): array
346339 {
347340 $ type = null ;
348341 $ options = $ dynamic ->getOptions ();
349342 $ initializeObjects = $ dynamic ->shouldInitializeObjects ();
350343
351- $ meta = $ call ->getMeta ();
352- $ fieldsMeta = $ meta ->getFields ();
353-
354344 $ requiredFields = $ options ->getRequiredFields ();
355345 $ fillDefaultValues = $ initializeObjects || $ options ->isPrefillDefaultValues ();
356346
357- foreach ($ this ->findMissingFields ($ data , $ call ) as $ missingField ) {
358- $ fieldMeta = $ fieldsMeta [$ missingField ];
347+ // $fieldsMeta contains only missing fields at this point
348+ foreach ($ fieldsMeta as $ fieldName => $ fieldMeta ) {
349+ $ fieldMeta = $ fieldsMeta [$ fieldName ];
359350 $ defaultMeta = $ fieldMeta ->getDefault ();
360351
361352 if ($ requiredFields === RequiredFields::nonDefault () && $ defaultMeta ->hasValue ()) {
362353 // Add default value if defaults are not required and should be used
363354 // If VOs are initialized then values are always prefilled - user can work with them in after callback,
364355 // and they are defined by VO anyway
365356 if ($ fillDefaultValues ) {
366- $ data [$ missingField ] = $ defaultMeta ->getValue ();
357+ $ data [$ fieldName ] = $ defaultMeta ->getValue ();
367358 }
368359 } elseif (
369360 $ requiredFields !== RequiredFields::none ()
370- && ($ type === null || !$ type ->isFieldInvalid ($ missingField ))
361+ && ($ type === null || !$ type ->isFieldInvalid ($ fieldName ))
371362 ) {
372363 // Field is missing and have no default value, mark as invalid
373364 $ fieldRuleMeta = $ fieldMeta ->getRule ();
374365 $ fieldRule = $ this ->ruleManager ->getRule ($ fieldRuleMeta ->getType ());
375366 $ type ??= $ call ->getType ();
376367 $ type ->overwriteInvalidField (
377- $ missingField ,
368+ $ fieldName ,
378369 ValueDoesNotMatch::create (
379370 $ fieldRule ->createType (
380371 $ fieldRuleMeta ->getArgs (),
0 commit comments