Skip to content

Commit cfa19fe

Browse files
committed
Add attribute asymmetric read/write support
1 parent 0539edf commit cfa19fe

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

src/Mapping/Driver/AttributeDriver/PropertyMetadataLoader.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ protected function findPropertyAttribute(\ReflectionProperty $property, string $
2525
return null;
2626
}
2727

28+
/**
29+
* @template TAttribute of object
30+
*
31+
* @param class-string<TAttribute> $name
32+
*
33+
* @return TAttribute|null
34+
*/
35+
protected function findHookAttribute(\ReflectionMethod $hook, string $name): ?object
36+
{
37+
$attributes = $hook->getAttributes($name, \ReflectionAttribute::IS_INSTANCEOF);
38+
39+
foreach ($attributes as $attribute) {
40+
/** @var TAttribute */
41+
return $attribute->newInstance();
42+
}
43+
44+
return null;
45+
}
46+
2847
/**
2948
* @template TAttribute of object
3049
*
@@ -40,4 +59,20 @@ protected function getAllPropertyAttributes(\ReflectionProperty $property, strin
4059
yield $attribute->newInstance();
4160
}
4261
}
62+
63+
/**
64+
* @template TAttribute of object
65+
*
66+
* @param class-string<TAttribute> $name
67+
*
68+
* @return iterable<array-key, TAttribute>
69+
*/
70+
protected function getAllHookAttributes(\ReflectionMethod $hook, string $name): iterable
71+
{
72+
$attributes = $hook->getAttributes($name, \ReflectionAttribute::IS_INSTANCEOF);
73+
74+
foreach ($attributes as $attribute) {
75+
yield $attribute->newInstance();
76+
}
77+
}
4378
}

src/Mapping/Driver/AttributeDriver/TypePropertyMetadataLoader.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,25 @@ public function load(
2222
PropertyMetadata $metadata,
2323
TypeRepositoryInterface $types,
2424
TypeParserInterface $parser,
25+
): void {
26+
$this->loadPropertyType($property, $metadata, $types, $parser);
27+
28+
if (\PHP_VERSION_ID < 80400) {
29+
return;
30+
}
31+
32+
$this->loadReadHookType($property, $metadata, $types, $parser);
33+
$this->loadWriteHookType($property, $metadata, $types, $parser);
34+
}
35+
36+
/**
37+
* @throws \Throwable
38+
*/
39+
private function loadPropertyType(
40+
\ReflectionProperty $property,
41+
PropertyMetadata $metadata,
42+
TypeRepositoryInterface $types,
43+
TypeParserInterface $parser,
2544
): void {
2645
$attribute = $this->findPropertyAttribute($property, MapType::class);
2746

@@ -37,6 +56,64 @@ public function load(
3756
);
3857
}
3958

59+
/**
60+
* @throws \Throwable
61+
*/
62+
private function loadReadHookType(
63+
\ReflectionProperty $property,
64+
PropertyMetadata $metadata,
65+
TypeRepositoryInterface $types,
66+
TypeParserInterface $parser,
67+
): void {
68+
$hook = $property->getHook(\PropertyHookType::Get);
69+
70+
if ($hook === null) {
71+
return;
72+
}
73+
74+
$attribute = $this->findHookAttribute($hook, MapType::class);
75+
76+
if ($attribute === null) {
77+
return;
78+
}
79+
80+
$metadata->read = $this->createPropertyType(
81+
type: $attribute->type,
82+
property: $property,
83+
types: $types,
84+
parser: $parser,
85+
);
86+
}
87+
88+
/**
89+
* @throws \Throwable
90+
*/
91+
private function loadWriteHookType(
92+
\ReflectionProperty $property,
93+
PropertyMetadata $metadata,
94+
TypeRepositoryInterface $types,
95+
TypeParserInterface $parser,
96+
): void {
97+
$hook = $property->getHook(\PropertyHookType::Set);
98+
99+
if ($hook === null) {
100+
return;
101+
}
102+
103+
$attribute = $this->findHookAttribute($hook, MapType::class);
104+
105+
if ($attribute === null) {
106+
return;
107+
}
108+
109+
$metadata->write = $this->createPropertyType(
110+
type: $attribute->type,
111+
property: $property,
112+
types: $types,
113+
parser: $parser,
114+
);
115+
}
116+
40117
/**
41118
* @param non-empty-string $type
42119
*

src/Mapping/MapType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace TypeLang\Mapper\Mapping;
66

7-
#[\Attribute(\Attribute::TARGET_PROPERTY)]
7+
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)]
88
class MapType
99
{
1010
public function __construct(

0 commit comments

Comments
 (0)