Skip to content

Commit 064eee6

Browse files
committed
DefaultProcessor: creates MappedObjectType only when necessary
1 parent c69b42d commit 064eee6

File tree

6 files changed

+52
-33
lines changed

6 files changed

+52
-33
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
3131
- initializes `Type` lazily (performance optimization)
3232
- `ArrayShapeType`
3333
- `getFields()` always returns the same instances
34+
- `DefaultProcessor`
35+
- creates `MappedObjectType` only when necessary (performance optimization)
3436

3537
### Removed
3638

src/Context/MappedObjectContext.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,9 @@ public function getType(): MappedObjectType
4545
return $this->type = $type;
4646
}
4747

48+
public function getTypeIfInitialized(): ?MappedObjectType
49+
{
50+
return $this->type;
51+
}
52+
4853
}

src/Context/SkippedFieldsContext.php

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,22 @@
22

33
namespace Orisai\ObjectMapper\Context;
44

5-
use Orisai\ObjectMapper\Processing\Options;
6-
use Orisai\ObjectMapper\Types\MappedObjectType;
7-
85
final class SkippedFieldsContext
96
{
107

11-
private MappedObjectType $type;
12-
13-
private Options $options;
8+
private MappedObjectContext $mappedObjectContext;
149

1510
/** @var array<int|string, SkippedFieldContext> */
1611
private array $skippedFields = [];
1712

18-
public function __construct(MappedObjectType $type, Options $options)
19-
{
20-
$this->type = $type;
21-
$this->options = $options;
22-
}
23-
24-
public function getType(): MappedObjectType
13+
public function __construct(MappedObjectContext $mappedObjectContext)
2514
{
26-
return $this->type;
15+
$this->mappedObjectContext = $mappedObjectContext;
2716
}
2817

29-
public function getOptions(): Options
18+
public function getMappedObjectContext(): MappedObjectContext
3019
{
31-
return $this->options;
20+
return $this->mappedObjectContext;
3221
}
3322

3423
/**

src/Context/TypeContext.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,17 @@ public function createClone(): self
8383
return $clone;
8484
}
8585

86+
/**
87+
* @return static
88+
*
89+
* @internal
90+
*/
91+
public function createCloneWithOptions(Options $options): self
92+
{
93+
$clone = clone $this;
94+
$clone->options = $options;
95+
96+
return $clone;
97+
}
98+
8699
}

src/Processing/DefaultProcessor.php

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ private function handleFields(
252252
$data = $this->handleSentFields($data, $mappedObjectContext, $callContext);
253253
$data = $this->handleMissingFields($data, $mappedObjectContext, $callContext);
254254

255-
$type = $mappedObjectContext->getType();
255+
$type = $mappedObjectContext->getTypeIfInitialized();
256256

257-
if ($type->hasInvalidFields()) {
257+
if ($type !== null && $type->hasInvalidFields()) {
258258
throw InvalidData::create($type, Value::none());
259259
}
260260

@@ -272,7 +272,7 @@ private function handleSentFields(
272272
ProcessorCallContext $callContext
273273
): array
274274
{
275-
$type = $mappedObjectContext->getType();
275+
$type = null;
276276
$options = $mappedObjectContext->getOptions();
277277

278278
$meta = $callContext->getMeta();
@@ -281,7 +281,7 @@ private function handleSentFields(
281281

282282
foreach ($data as $fieldName => $value) {
283283
// Skip invalid field
284-
if ($type->isFieldInvalid($fieldName)) {
284+
if ($type !== null && $type->isFieldInvalid($fieldName)) {
285285
continue;
286286
}
287287

@@ -305,6 +305,7 @@ private function handleSentFields(
305305
: '.';
306306

307307
// Add error to type
308+
$type ??= $mappedObjectContext->getType();
308309
$type->overwriteInvalidField(
309310
$fieldName,
310311
ValueDoesNotMatch::create(
@@ -346,6 +347,7 @@ private function handleSentFields(
346347
$fieldMeta,
347348
);
348349
} catch (ValueDoesNotMatch | InvalidData $exception) {
350+
$type ??= $mappedObjectContext->getType();
349351
$type->overwriteInvalidField($fieldName, $exception);
350352
}
351353
}
@@ -388,7 +390,7 @@ private function handleMissingFields(
388390
ProcessorCallContext $callContext
389391
): array
390392
{
391-
$type = $mappedObjectContext->getType();
393+
$type = null;
392394
$options = $mappedObjectContext->getOptions();
393395
$initializeObjects = $mappedObjectContext->shouldInitializeObjects();
394396

@@ -416,10 +418,14 @@ private function handleMissingFields(
416418
if ($fillDefaultValues) {
417419
$data[$missingField] = $defaultMeta->getValue();
418420
}
419-
} elseif ($requiredFields !== RequiredFields::none() && !$type->isFieldInvalid($missingField)) {
421+
} elseif (
422+
$requiredFields !== RequiredFields::none()
423+
&& ($type === null || !$type->isFieldInvalid($missingField))
424+
) {
420425
// Field is missing and have no default value, mark as invalid
421426
$fieldRuleMeta = $fieldMeta->getRule();
422427
$fieldRule = $this->ruleManager->getRule($fieldRuleMeta->getType());
428+
$type ??= $mappedObjectContext->getType();
423429
$type->overwriteInvalidField(
424430
$missingField,
425431
ValueDoesNotMatch::create(
@@ -469,8 +475,7 @@ private function createFieldContext(
469475
ReflectionProperty $property
470476
): FieldContext
471477
{
472-
$parentType = $mappedObjectContext->getType();
473-
$typeCreator = static fn (): Type => $parentType->getField($fieldName);
478+
$typeCreator = static fn (): Type => $mappedObjectContext->getType()->getField($fieldName);
474479

475480
return new FieldContext(
476481
$this->metaLoader,
@@ -543,11 +548,10 @@ private function handleClassCallbacks(
543548
string $callbackType
544549
)
545550
{
546-
$type = $mappedObjectContext->getType();
547-
548551
try {
549552
$data = $this->applyCallbacks($data, $mappedObjectContext, $callContext, $meta, $callbackType);
550553
} catch (ValueDoesNotMatch | InvalidData $exception) {
554+
$type = $mappedObjectContext->getType();
551555
$caughtType = $exception->getType();
552556

553557
// User thrown type is not the actual type from MappedObjectContext
@@ -616,7 +620,6 @@ private function fillObject(
616620
ProcessorCallContext $callContext
617621
): void
618622
{
619-
$type = $mappedObjectContext->getType();
620623
$options = $mappedObjectContext->getOptions();
621624
$meta = $callContext->getMeta();
622625

@@ -639,7 +642,7 @@ private function fillObject(
639642
// Set skipped properties
640643
$skippedFields = $callContext->getSkippedFields();
641644
if ($skippedFields !== []) {
642-
$skippedContext = new SkippedFieldsContext($type, $options);
645+
$skippedContext = new SkippedFieldsContext($mappedObjectContext);
643646
$this->skippedMap->setSkippedFieldsContext($object, $skippedContext);
644647

645648
foreach ($skippedFields as $fieldName => $skippedFieldContext) {
@@ -713,11 +716,13 @@ public function processSkippedFields(
713716
}
714717

715718
$skippedFieldsContext = $this->skippedMap->getSkippedFieldsContext($object);
719+
$mappedObjectContext = $skippedFieldsContext->getMappedObjectContext();
720+
721+
if ($options !== null) {
722+
$mappedObjectContext = $mappedObjectContext->createCloneWithOptions($options);
723+
}
716724

717-
$type = $skippedFieldsContext->getType();
718-
$typeCreator = static fn (): MappedObjectType => $type;
719-
$options ??= $skippedFieldsContext->getOptions();
720-
$mappedObjectContext = $this->createMappedObjectContext($options, $typeCreator, true);
725+
$type = null;
721726
$skippedFields = $skippedFieldsContext->getSkippedFields();
722727

723728
$meta = $this->metaLoader->load($class);
@@ -757,6 +762,7 @@ public function processSkippedFields(
757762
$fieldMeta,
758763
);
759764
} catch (ValueDoesNotMatch | InvalidData $exception) {
765+
$type ??= $mappedObjectContext->getType();
760766
$type->overwriteInvalidField($fieldName, $exception);
761767

762768
continue;
@@ -768,7 +774,7 @@ public function processSkippedFields(
768774
}
769775

770776
// If any of fields is invalid, throw error
771-
if ($type->hasInvalidFields()) {
777+
if ($type !== null && $type->hasInvalidFields()) {
772778
throw InvalidData::create($type, Value::none());
773779
}
774780

tests/Unit/Context/MappedObjectContextTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ public function test(): void
3131
self::assertSame($deps->processor, $context->getProcessor());
3232
self::assertTrue($context->shouldInitializeObjects());
3333

34+
self::assertNull($context->getTypeIfInitialized());
35+
3436
self::assertEquals($typeCreator(), $context->getType());
3537
self::assertNotSame($typeCreator(), $context->getType());
3638
self::assertSame($context->getType(), $context->getType());
39+
40+
self::assertSame($context->getType(), $context->getTypeIfInitialized());
3741
}
3842

3943
}

0 commit comments

Comments
 (0)