55namespace Tempest \Mapper ;
66
77use Closure ;
8+ use Tempest \Reflection \ClassReflector ;
89use Tempest \Reflection \PropertyReflector ;
10+ use Tempest \Reflection \TypeReflector ;
11+ use TypeError ;
912
1013use function Tempest \get ;
1114
@@ -26,6 +29,40 @@ public function addSerializer(string|Closure $for, string|Closure $serializerCla
2629 return $ this ;
2730 }
2831
32+ private function serializerMatches (Closure |string $ for , TypeReflector |string $ input ): bool
33+ {
34+ if (is_callable ($ for )) {
35+ try {
36+ return $ for ($ input );
37+ } catch (TypeError ) { // @mago-expect best-practices/dont-catch-error
38+ return false ;
39+ }
40+ }
41+
42+ if ($ for === $ input ) {
43+ return true ;
44+ }
45+
46+ if ($ input instanceof TypeReflector) {
47+ return $ input ->getName () === $ for || $ input ->matches ($ for );
48+ }
49+
50+ return false ;
51+ }
52+
53+ private function resolveSerializer (Closure |string $ serializerClass , PropertyReflector |TypeReflector |string $ input ): ?Serializer
54+ {
55+ if (is_string ($ serializerClass )) {
56+ return get ($ serializerClass );
57+ }
58+
59+ try {
60+ return $ serializerClass ($ input );
61+ } catch (TypeError ) { // @mago-expect best-practices/dont-catch-error
62+ return null ;
63+ }
64+ }
65+
2966 public function forProperty (PropertyReflector $ property ): ?Serializer
3067 {
3168 $ type = $ property ->getType ();
@@ -46,10 +83,42 @@ public function forProperty(PropertyReflector $property): ?Serializer
4683
4784 // Resolve serializer from manual additions
4885 foreach ($ this ->serializers as [$ for , $ serializerClass ]) {
49- if (is_callable ($ for ) && $ for ($ property ) || is_string ($ for ) && $ type ->matches ($ for ) || $ type ->getName () === $ for ) {
50- return is_callable ($ serializerClass )
51- ? $ serializerClass ($ property )
52- : get ($ serializerClass );
86+ if (! $ this ->serializerMatches ($ for , $ type )) {
87+ continue ;
88+ }
89+
90+ $ serializer = $ this ->resolveSerializer ($ serializerClass , $ property );
91+
92+ if ($ serializer !== null ) {
93+ return $ serializer ;
94+ }
95+ }
96+
97+ return null ;
98+ }
99+
100+ public function forValue (mixed $ value ): ?Serializer
101+ {
102+ if ($ value === null ) {
103+ return null ;
104+ }
105+
106+ if (is_object ($ value )) {
107+ $ input = new ClassReflector ($ value )->getType ();
108+ } else {
109+ $ input = gettype ($ value );
110+ }
111+
112+ // Resolve serializer from manual additions
113+ foreach ($ this ->serializers as [$ for , $ serializerClass ]) {
114+ if (! $ this ->serializerMatches ($ for , $ input )) {
115+ continue ;
116+ }
117+
118+ $ serializer = $ this ->resolveSerializer ($ serializerClass , $ input );
119+
120+ if ($ serializer !== null ) {
121+ return $ serializer ;
53122 }
54123 }
55124
0 commit comments