66use Soap \Encoding \Normalizer \PhpPropertyNameNormalizer ;
77use Soap \Encoding \TypeInference \ComplexTypeBuilder ;
88use Soap \Engine \Metadata \Model \Property ;
9+ use Soap \Engine \Metadata \Model \Type ;
910use Soap \Engine \Metadata \Model \TypeMeta ;
1011use VeeWee \Reflecta \Iso \Iso ;
1112use VeeWee \Reflecta \Lens \Lens ;
@@ -47,17 +48,21 @@ public static function forContext(Context $context): self
4748 $ isAnyPropertyQualified = false ;
4849
4950 foreach ($ sortedProperties as $ property ) {
50- $ typeMeta = $ property ->getType ()->getMeta ();
51+ $ propertyType = $ property ->getType ();
52+ $ propertyTypeMeta = $ propertyType ->getMeta ();
53+ $ propertyContext = $ context ->withType ($ propertyType );
5154 $ name = $ property ->getName ();
5255 $ normalizedName = PhpPropertyNameNormalizer::normalize ($ name );
5356
54- $ shouldLensBeOptional = self ::shouldLensBeOptional ($ typeMeta );
57+ $ encoder = $ context ->registry ->detectEncoderForContext ($ propertyContext );
58+ $ shouldLensBeOptional = self ::shouldLensBeOptional ($ propertyTypeMeta );
5559 $ normalizedProperties [$ normalizedName ] = $ property ;
56- $ encoderLenses [$ normalizedName ] = $ shouldLensBeOptional ? optional (property ($ normalizedName )) : property ($ normalizedName );
57- $ decoderLenses [$ normalizedName ] = $ shouldLensBeOptional ? optional (index ($ name )) : index ($ name );
58- $ isos [$ normalizedName ] = self ::grabIsoForProperty ($ context , $ property );
5960
60- $ isAnyPropertyQualified = $ isAnyPropertyQualified || $ typeMeta ->isQualified ()->unwrapOr (false );
61+ $ encoderLenses [$ normalizedName ] = self ::createEncoderLensForType ($ shouldLensBeOptional , $ normalizedName , $ encoder , $ type , $ property );
62+ $ decoderLenses [$ normalizedName ] = self ::createDecoderLensForType ($ shouldLensBeOptional , $ name , $ encoder , $ type , $ property );
63+ $ isos [$ normalizedName ] = $ encoder ->iso ($ propertyContext );
64+
65+ $ isAnyPropertyQualified = $ isAnyPropertyQualified || $ propertyTypeMeta ->isQualified ()->unwrapOr (false );
6166 }
6267
6368 return new self (
@@ -69,6 +74,46 @@ public static function forContext(Context $context): self
6974 );
7075 }
7176
77+ /**
78+ * @return Lens<object, mixed>
79+ */
80+ private static function createEncoderLensForType (
81+ bool $ shouldLensBeOptional ,
82+ string $ normalizedName ,
83+ XmlEncoder $ encoder ,
84+ Type $ type ,
85+ Property $ property ,
86+ ): Lens {
87+ $ lens = match (true ) {
88+ $ encoder instanceof Feature \DecoratingEncoder => self ::createEncoderLensForType ($ shouldLensBeOptional , $ normalizedName , $ encoder ->decoratedEncoder (), $ type , $ property ),
89+ $ encoder instanceof Feature \ProvidesObjectEncoderLens => $ encoder ::createObjectEncoderLens ($ type , $ property ),
90+ default => property ($ normalizedName )
91+ };
92+
93+ /** @var Lens<object, mixed> */
94+ return $ shouldLensBeOptional ? optional ($ lens ) : $ lens ;
95+ }
96+
97+ /**
98+ * @return Lens<array, mixed>
99+ */
100+ private static function createDecoderLensForType (
101+ bool $ shouldLensBeOptional ,
102+ string $ name ,
103+ XmlEncoder $ encoder ,
104+ Type $ type ,
105+ Property $ property ,
106+ ): Lens {
107+ $ lens = match (true ) {
108+ $ encoder instanceof Feature \DecoratingEncoder => self ::createDecoderLensForType ($ shouldLensBeOptional , $ name , $ encoder ->decoratedEncoder (), $ type , $ property ),
109+ $ encoder instanceof Feature \ProvidesObjectDecoderLens => $ encoder ::createObjectDecoderLens ($ type , $ property ),
110+ default => index ($ name ),
111+ };
112+
113+ /** @var Lens<array, mixed> */
114+ return $ shouldLensBeOptional ? optional ($ lens ) : $ lens ;
115+ }
116+
72117 private static function shouldLensBeOptional (TypeMeta $ meta ): bool
73118 {
74119 if ($ meta ->isNullable ()->unwrapOr (false )) {
@@ -84,15 +129,4 @@ private static function shouldLensBeOptional(TypeMeta $meta): bool
84129
85130 return false ;
86131 }
87-
88- /**
89- * @return Iso<mixed, string>
90- */
91- private static function grabIsoForProperty (Context $ context , Property $ property ): Iso
92- {
93- $ propertyContext = $ context ->withType ($ property ->getType ());
94-
95- return $ context ->registry ->detectEncoderForContext ($ propertyContext )
96- ->iso ($ propertyContext );
97- }
98132}
0 commit comments