Skip to content

Commit 8fe42c9

Browse files
committed
Simplify finding missing fields (performance optimization)
1 parent 91cd07b commit 8fe42c9

File tree

2 files changed

+25
-30
lines changed

2 files changed

+25
-30
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased](https://github.com/orisai/object-mapper/compare/0.3.0...v1.x)
99

10+
### Changed
11+
12+
- Simplify finding missing fields (performance optimization)
13+
1014
### Fixed
1115

1216
- PHPStan generics

src/Processing/DefaultProcessor.php

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
use Orisai\ObjectMapper\Types\MessageType;
3030
use Orisai\ObjectMapper\Types\Type;
3131
use ReflectionProperty;
32-
use function array_diff;
3332
use function array_key_exists;
3433
use function array_keys;
3534
use 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

Comments
 (0)