7
7
use PBaszak \UltraMapper \Blueprint \Application \Model \Assets \ClassBlueprint ;
8
8
use PBaszak \UltraMapper \Blueprint \Application \Model \Assets \PropertyBlueprint ;
9
9
use PBaszak \UltraMapper \Mapper \Application \Attribute \TargetProperty ;
10
+ use PBaszak \UltraMapper \Mapper \Application \Contract \TypeInterface ;
10
11
11
12
class TargetPropertyAttributeStrategy implements MatchingStrategyInterface
12
13
{
@@ -17,36 +18,38 @@ public function confirmClassMatching(string $processType, ClassBlueprint $origin
17
18
18
19
public function confirmPropertiesMatching (string $ processType , PropertyBlueprint $ origin , PropertyBlueprint $ source , PropertyBlueprint $ target ): bool
19
20
{
20
- if ($ sourceTargetProperty = $ this ->getPropertyTargetPropertyAttribute ($ source , $ processType )) {
21
- // source has same name as origin, source has target property attribute
22
- if ($ origin ->originName === $ source ->originName && $ target ->originName === $ sourceTargetProperty ->name ) {
23
- $ target ->options ['name ' ] ??= $ sourceTargetProperty ->name ;
21
+ $ sourceTargetProperty = $ this ->getPropertyTargetPropertyAttribute ($ source , $ processType );
22
+ $ hasSourceTargetProperty = null !== $ sourceTargetProperty ;
23
+ $ targetTargetProperty = $ this ->getPropertyTargetPropertyAttribute ($ target , $ processType );
24
+ $ hasTargetTargetProperty = null !== $ targetTargetProperty ;
25
+
26
+ // source affects source
27
+ if ($ this ->isTargetPropertyAttrHasAffect ($ processType , 'source ' , 'source ' , $ hasSourceTargetProperty , $ hasTargetTargetProperty )) {
28
+ if ($ origin ->originName === $ source ->originName && $ origin ->originName === $ target ->originName ) {
29
+ $ source ->options ['name ' ] = $ sourceTargetProperty ->name ;
24
30
25
31
return true ;
26
32
}
27
33
}
28
34
29
- if ($ originTargetProperty = $ this ->getPropertyTargetPropertyAttribute ($ origin , $ processType )) {
30
- // source has same name as origin, but the origin has target property attribute
31
- if ($ origin ->originName === $ source ->originName && $ source ->originName === $ originTargetProperty ->name ) {
32
- $ target ->options ['name ' ] ??= $ originTargetProperty ->name ;
33
-
35
+ // source affects target
36
+ if ($ this ->isTargetPropertyAttrHasAffect ($ processType , 'source ' , 'target ' , $ hasSourceTargetProperty , $ hasTargetTargetProperty )) {
37
+ if ($ origin ->originName === $ source ->originName && $ sourceTargetProperty ->name === $ target ->originName ) {
34
38
return true ;
35
39
}
36
40
}
37
41
38
- if ($ targetTargetProperty = $ this ->getPropertyTargetPropertyAttribute ($ target , $ processType )) {
39
- // target has same name as origin, target has target property attribute
40
- if ($ origin ->originName === $ target ->originName && $ source ->originName === $ targetTargetProperty ->name ) {
41
- $ source ->options ['name ' ] ??= $ targetTargetProperty ->name ;
42
-
42
+ // target affects source
43
+ if ($ this ->isTargetPropertyAttrHasAffect ($ processType , 'target ' , 'source ' , $ hasSourceTargetProperty , $ hasTargetTargetProperty )) {
44
+ if ($ origin ->originName === $ target ->originName && $ targetTargetProperty ->name === $ source ->originName ) {
43
45
return true ;
44
46
}
47
+ }
45
48
46
- // target has same name as source, but the target has target property attribute
47
- if ($ source -> originName === $ target-> originName && $ origin -> originName === $ targetTargetProperty -> name ) {
48
- // do nothing, source and target are already matched, only origin has different originName but it's match
49
- // based on target property attribute with both source and target
49
+ // target affects target
50
+ if ($ this -> isTargetPropertyAttrHasAffect ( $ processType , ' target ' , ' target ' , $ hasSourceTargetProperty , $ hasTargetTargetProperty ) ) {
51
+ if ( $ origin -> originName === $ target-> originName && $ origin-> originName === $ source -> originName ) {
52
+ $ target-> options [ ' name ' ] = $ targetTargetProperty -> name ;
50
53
51
54
return true ;
52
55
}
@@ -55,14 +58,60 @@ public function confirmPropertiesMatching(string $processType, PropertyBlueprint
55
58
return false ;
56
59
}
57
60
61
+ /**
62
+ * @param string<"source"|"target"> $declarationPlace
63
+ * @param string<"source"|"target"> $context (the resource which is possible affected by target property attribute)
64
+ * @param bool $sourceHas whether source has target property attribute
65
+ * @param bool $targetHas whether target has target property attribute
66
+ */
67
+ protected function isTargetPropertyAttrHasAffect (string $ processType , string $ declarationPlace , string $ context , bool $ sourceHas , bool $ targetHas ): bool
68
+ {
69
+ return match ($ processType ) {
70
+ TypeInterface::NORMALIZATION_PROCESS => match ($ declarationPlace ) {
71
+ 'source ' => false ,
72
+ 'target ' => match ($ context ) {
73
+ 'source ' => false ,
74
+ 'target ' => $ targetHas ,
75
+ }
76
+ },
77
+ TypeInterface::DENORMALIZATION_PROCESS => match ($ declarationPlace ) {
78
+ 'source ' => match ($ context ) {
79
+ 'source ' => $ sourceHas ,
80
+ 'target ' => false ,
81
+ },
82
+ 'target ' => false ,
83
+ },
84
+ TypeInterface::MAPPING_PROCESS => match ($ declarationPlace ) {
85
+ 'source ' => match ($ context ) {
86
+ 'source ' => false ,
87
+ 'target ' => $ targetHas ,
88
+ },
89
+ 'target ' => match ($ context ) {
90
+ 'source ' => $ sourceHas ,
91
+ 'target ' => false ,
92
+ }
93
+ },
94
+ TypeInterface::TRANSFORMATION_PROCESS => match ($ declarationPlace ) {
95
+ 'source ' => match ($ context ) {
96
+ 'source ' => false ,
97
+ 'target ' => $ targetHas ,
98
+ },
99
+ 'target ' => match ($ context ) {
100
+ 'source ' => $ sourceHas ,
101
+ 'target ' => false ,
102
+ }
103
+ },
104
+ };
105
+ }
106
+
58
107
protected function getPropertyTargetPropertyAttribute (PropertyBlueprint $ blueprint , string $ processType ): ?TargetProperty
59
108
{
60
- foreach ($ blueprint ->attributes [TargetProperty::class] as $ attribute ) {
109
+ foreach ($ blueprint ->attributes [TargetProperty::class] ?? [] as $ attribute ) {
61
110
/** @var TargetProperty $instance */
62
111
$ instance = $ attribute ->newInstance ();
63
112
64
113
$ binaryProcessType = $ instance ::PROCESS_TYPE_MAP [$ processType ];
65
- if ($ instance ->useNameFor & $ binaryProcessType === $ binaryProcessType ) {
114
+ if (( $ instance ->useNameFor & $ binaryProcessType) === $ binaryProcessType ) {
66
115
return $ instance ;
67
116
}
68
117
}
@@ -81,7 +130,7 @@ protected function getClassTargetPropertyAttribute(ClassBlueprint $blueprint, st
81
130
$ instance = $ attribute ->newInstance ();
82
131
83
132
$ binaryProcessType = $ instance ::PROCESS_TYPE_MAP [$ processType ];
84
- if ($ instance ->usePathFor & $ binaryProcessType === $ binaryProcessType ) {
133
+ if (( $ instance ->usePathFor & $ binaryProcessType) === $ binaryProcessType ) {
85
134
return $ instance ;
86
135
}
87
136
}
0 commit comments