diff --git a/src/Encoder/XsiTypeEncoder.php b/src/Encoder/XsiTypeEncoder.php index b2d2954..e060ac5 100644 --- a/src/Encoder/XsiTypeEncoder.php +++ b/src/Encoder/XsiTypeEncoder.php @@ -25,35 +25,46 @@ public function __construct( */ public function iso(Context $context): Iso { + $innerIso = $this->encoder->iso($context); + return new Iso( - function (mixed $value) use ($context) : string { - return $this->to($context, $value); + function (mixed $value) use ($innerIso) : string { + return $this->to($innerIso, $value); }, - function (string|Element $value) use ($context) : mixed { + function (string|Element $value) use ($context, $innerIso) : mixed { return $this->from( $context, + $innerIso, ($value instanceof Element ? $value : Element::fromString(non_empty_string()->assert($value))) ); } ); } - private function to(Context $context, mixed $value): string + /** + * @param Iso $innerIso + */ + private function to(Iso $innerIso, mixed $value): string { // There is no way to know what xsi:type to use when encoding any type. // The type defined in the wsdl will always be used to encode the value. // If you want more control over the encoded type, please control how to encode by using the MatchingValueEncoder. - return $this->encoder->iso($context)->to($value); + return $innerIso->to($value); } - private function from(Context $context, Element $value): mixed + /** + * @param Iso $innerIso + */ + private function from(Context $context, Iso $innerIso, Element $value): mixed { - /** @var XmlEncoder $encoder */ - $encoder = match (true) { - $this->encoder instanceof Feature\DisregardXsiInformation => $this->encoder, - default => XsiTypeDetector::detectEncoderFromXmlElement($context, $value->element())->unwrapOr($this->encoder) + $iso = match (true) { + $this->encoder instanceof Feature\DisregardXsiInformation => $innerIso, + default => XsiTypeDetector::detectEncoderFromXmlElement($context, $value->element()) + ->map(static fn (XmlEncoder $encoder): Iso => $encoder->iso($context)) + ->unwrapOr($innerIso), }; - return $encoder->iso($context)->from($value); + /** @psalm-suppress ImplicitToStringCast - Encoders accept string|Element in from() */ + return $iso->from($value); } }