Skip to content

Commit 5bab92b

Browse files
committed
Remove runtime reflection from FieldRutimeMeta
1 parent 8322fd9 commit 5bab92b

File tree

8 files changed

+126
-30
lines changed

8 files changed

+126
-30
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2424
- `DefaultProcessor`
2525
- Simplify finding missing fields (performance optimization)
2626
- Reduce calls needed to find field names for "did you mean" error helper (performance optimization)
27-
- Call `unset()` only for initialized properties (performance optimization)
2827
- Create functions for setting and unsetting non public-set properties only once (performance optimization)
2928
- Callbacks
3029
- renamed
@@ -62,9 +61,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6261

6362
- `Options` - `withProcessedClass()`, `getProcessedClass()` - no longer used
6463
- Runtime reflection (performance optimization), from:
65-
- `PropertyContext`
6664
- `CallbackRuntimeMeta`
6765
- `Callback`
66+
- `PropertyContext`
67+
- `FieldRuntimeMeta`
6868

6969
## [0.3.0](https://github.com/orisai/object-mapper/compare/0.2.0...0.3.0) - 2025-01-21
7070

src/Meta/MetaResolver.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Orisai\ObjectMapper\Meta\Runtime\ClassRuntimeMeta;
2222
use Orisai\ObjectMapper\Meta\Runtime\FieldRuntimeMeta;
2323
use Orisai\ObjectMapper\Meta\Runtime\ModifierRuntimeMeta;
24+
use Orisai\ObjectMapper\Meta\Runtime\PhpPropertyMeta;
2425
use Orisai\ObjectMapper\Meta\Runtime\RuleRuntimeMeta;
2526
use Orisai\ObjectMapper\Meta\Runtime\RuntimeMeta;
2627
use Orisai\ObjectMapper\Meta\Shared\DefaultValueMeta;
@@ -217,7 +218,7 @@ private function propertyNameToFieldName(FieldRuntimeMeta $fieldMeta)
217218
return $modifier->args->name;
218219
}
219220

220-
return $fieldMeta->property->getName();
221+
return $fieldMeta->property->name;
221222
}
222223

223224
/**
@@ -260,7 +261,7 @@ private function resolveFieldMeta(
260261
$context,
261262
),
262263
$defaultValue,
263-
$reflector,
264+
PhpPropertyMeta::from($reflector),
264265
);
265266
}
266267

src/Meta/Runtime/FieldRuntimeMeta.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Orisai\ObjectMapper\Args\Args;
66
use Orisai\ObjectMapper\Meta\Shared\DefaultValueMeta;
77
use Orisai\ObjectMapper\Modifiers\Modifier;
8-
use ReflectionProperty;
98

109
final class FieldRuntimeMeta extends NodeRuntimeMeta
1110
{
@@ -15,7 +14,7 @@ final class FieldRuntimeMeta extends NodeRuntimeMeta
1514

1615
public DefaultValueMeta $default;
1716

18-
public ReflectionProperty $property;
17+
public PhpPropertyMeta $property;
1918

2019
/** @var array<class-string<Modifier<Args>>, ModifierRuntimeMeta<Args>> */
2120
public array $modifiers;
@@ -31,7 +30,7 @@ public function __construct(
3130
array $modifiers,
3231
RuleRuntimeMeta $rule,
3332
DefaultValueMeta $default,
34-
ReflectionProperty $property
33+
PhpPropertyMeta $property
3534
)
3635
{
3736
parent::__construct($callbacks, $docs);
@@ -60,8 +59,7 @@ public function __serialize(): array
6059
'parent' => parent::__serialize(),
6160
'rule' => $this->rule,
6261
'default' => $this->default,
63-
'class' => $this->property->getDeclaringClass()->getName(),
64-
'property' => $this->property->getName(),
62+
'property' => $this->property,
6563
'modifiers' => $this->modifiers,
6664
];
6765
}
@@ -74,7 +72,7 @@ public function __unserialize(array $data): void
7472
parent::__unserialize($data['parent']);
7573
$this->rule = $data['rule'];
7674
$this->default = $data['default'];
77-
$this->property = new ReflectionProperty($data['class'], $data['property']);
75+
$this->property = $data['property'];
7876
$this->modifiers = $data['modifiers'];
7977
}
8078

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Orisai\ObjectMapper\Meta\Runtime;
4+
5+
use Orisai\ObjectMapper\MappedObject;
6+
use ReflectionClass;
7+
use ReflectionProperty;
8+
use const PHP_VERSION_ID;
9+
10+
/**
11+
* @readonly
12+
*/
13+
final class PhpPropertyMeta
14+
{
15+
16+
/** @var class-string<MappedObject> */
17+
public string $declaringClass;
18+
19+
public string $name;
20+
21+
public bool $isPublicSet;
22+
23+
/**
24+
* @param class-string<MappedObject> $declaringClass
25+
*/
26+
public function __construct(
27+
string $declaringClass,
28+
string $name,
29+
bool $isPublicSet
30+
)
31+
{
32+
$this->declaringClass = $declaringClass;
33+
$this->name = $name;
34+
$this->isPublicSet = $isPublicSet;
35+
}
36+
37+
public static function from(ReflectionProperty $property): self
38+
{
39+
/** @var ReflectionClass<MappedObject> $class */
40+
$class = $property->getDeclaringClass();
41+
42+
return new self(
43+
$class->getName(),
44+
$property->getName(),
45+
self::isPublicSet($property),
46+
);
47+
}
48+
49+
private static function isPublicSet(ReflectionProperty $property): bool
50+
{
51+
return $property->isPublic()
52+
&& (PHP_VERSION_ID < 8_01_00 || !$property->isReadOnly());
53+
}
54+
55+
}

src/Processing/DefaultProcessor.php

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
use function array_map;
3535
use function assert;
3636
use function is_array;
37-
use const PHP_VERSION_ID;
3837

3938
final class DefaultProcessor implements Processor
4039
{
@@ -328,13 +327,13 @@ private function handleSentFields(
328327
}
329328

330329
$property = $fieldMeta->property;
331-
$className = $property->getDeclaringClass()->getName();
332-
$propertyName = $property->getName();
330+
$className = $property->declaringClass;
331+
$propertyName = $property->name;
333332
$propertyContext = $this->propertyContextCache[$className][$propertyName]
334333
?? (
335334
$this->propertyContextCache[$className][$propertyName] = new PropertyContext(
336335
$fieldMeta->default,
337-
$fieldMeta->property->getName(),
336+
$fieldMeta->property->name,
338337
$fieldName,
339338
));
340339

@@ -581,18 +580,13 @@ private function fillObject(
581580
// Reset mapped properties state
582581
foreach ($fieldsMeta as $fieldMeta) {
583582
$property = $fieldMeta->property;
584-
$declaringClass = $property->getDeclaringClass();
585-
$name = $property->getName();
586-
587-
if (
588-
$property->isInitialized($object)
589-
&& $property->isPublic()
590-
&& (PHP_VERSION_ID < 8_01_00 || !$property->isReadOnly())
591-
) {
583+
$name = $property->name;
584+
585+
if ($property->isPublicSet) {
592586
unset($object->$name);
593587
} else {
594588
// phpcs:disable SlevomatCodingStandard.Functions.StaticClosure
595-
$unsetter->bindTo($object, $declaringClass->getName())($object, $name);
589+
$unsetter->bindTo($object, $property->declaringClass)($object, $name);
596590
// phpcs:enable
597591
}
598592
}
@@ -603,14 +597,14 @@ private function fillObject(
603597
// Set processed data
604598
foreach ($data as $fieldName => $value) {
605599
$property = $fieldsMeta[$fieldName]->property;
606-
$name = $property->getName();
600+
$name = $property->name;
607601

608-
if ($property->isPublic() && (PHP_VERSION_ID < 8_01_00 || !$property->isReadOnly())) {
602+
if ($property->isPublicSet) {
609603
$object->$name = $value;
610604
} else {
611605
$setter->bindTo(
612606
$object,
613-
$property->getDeclaringClass()->getName(),
607+
$property->declaringClass,
614608
)($object, $name, $value);
615609
}
616610
}

tests/Unit/Meta/Runtime/FieldRuntimeMetaTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
use Orisai\ObjectMapper\Meta\Runtime\FieldRuntimeMeta;
1313
use Orisai\ObjectMapper\Meta\Runtime\ModifierRuntimeMeta;
1414
use Orisai\ObjectMapper\Meta\Runtime\PhpMethodMeta;
15+
use Orisai\ObjectMapper\Meta\Runtime\PhpPropertyMeta;
1516
use Orisai\ObjectMapper\Meta\Runtime\RuleRuntimeMeta;
1617
use Orisai\ObjectMapper\Meta\Shared\DefaultValueMeta;
1718
use Orisai\ObjectMapper\Meta\Shared\DocMeta;
1819
use Orisai\ObjectMapper\Modifiers\FieldNameArgs;
1920
use Orisai\ObjectMapper\Modifiers\FieldNameModifier;
2021
use Orisai\ObjectMapper\Rules\MixedRule;
2122
use PHPUnit\Framework\TestCase;
22-
use ReflectionProperty;
2323
use Tests\Orisai\ObjectMapper\Doubles\NoDefaultsVO;
2424
use function serialize;
2525
use function unserialize;
@@ -29,7 +29,7 @@ final class FieldRuntimeMetaTest extends TestCase
2929

3030
public function test(): void
3131
{
32-
$property = new ReflectionProperty(NoDefaultsVO::class, 'string');
32+
$property = new PhpPropertyMeta(NoDefaultsVO::class, 'property', true);
3333

3434
$beforeCallbacks = [
3535
new CallbackRuntimeMeta(
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Tests\Orisai\ObjectMapper\Unit\Meta\Runtime;
4+
5+
use Generator;
6+
use Orisai\ObjectMapper\MappedObject;
7+
use Orisai\ObjectMapper\Meta\Runtime\PhpPropertyMeta;
8+
use PHPUnit\Framework\TestCase;
9+
use Tests\Orisai\ObjectMapper\Doubles\DefaultsVO;
10+
use Tests\Orisai\ObjectMapper\Doubles\NoDefaultsVO;
11+
12+
final class PhpPropertyMetaTest extends TestCase
13+
{
14+
15+
/**
16+
* @param class-string<MappedObject> $declaringClass
17+
*
18+
* @dataProvider provide
19+
*/
20+
public function test(
21+
string $declaringClass,
22+
string $name,
23+
bool $isPublicSet
24+
): void
25+
{
26+
$meta = new PhpPropertyMeta($declaringClass, $name, $isPublicSet);
27+
28+
self::assertSame($declaringClass, $meta->declaringClass);
29+
self::assertSame($name, $meta->name);
30+
self::assertSame($isPublicSet, $meta->isPublicSet);
31+
}
32+
33+
public function provide(): Generator
34+
{
35+
yield [
36+
NoDefaultsVO::class,
37+
'property',
38+
true,
39+
];
40+
41+
yield [
42+
DefaultsVO::class,
43+
'anotherProperty',
44+
false,
45+
];
46+
}
47+
48+
}

tests/Unit/Meta/Runtime/RuntimeMetaTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
use Orisai\ObjectMapper\Args\EmptyArgs;
66
use Orisai\ObjectMapper\Meta\Runtime\ClassRuntimeMeta;
77
use Orisai\ObjectMapper\Meta\Runtime\FieldRuntimeMeta;
8+
use Orisai\ObjectMapper\Meta\Runtime\PhpPropertyMeta;
89
use Orisai\ObjectMapper\Meta\Runtime\RuleRuntimeMeta;
910
use Orisai\ObjectMapper\Meta\Runtime\RuntimeMeta;
1011
use Orisai\ObjectMapper\Meta\Shared\DefaultValueMeta;
1112
use Orisai\ObjectMapper\Rules\MixedRule;
1213
use PHPUnit\Framework\TestCase;
13-
use ReflectionProperty;
1414
use Tests\Orisai\ObjectMapper\Doubles\NoDefaultsVO;
1515
use function serialize;
1616
use function unserialize;
@@ -28,7 +28,7 @@ public function test(): void
2828
[],
2929
new RuleRuntimeMeta(MixedRule::class, new EmptyArgs()),
3030
DefaultValueMeta::fromNothing(),
31-
new ReflectionProperty(NoDefaultsVO::class, 'string'),
31+
new PhpPropertyMeta(NoDefaultsVO::class, 'property', true),
3232
),
3333
];
3434

0 commit comments

Comments
 (0)