From 925a842161ef2d79f705010a6d02511f714a5aa9 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Tue, 11 Jun 2024 14:11:36 +0200 Subject: [PATCH] Normalize property names to supported php names in the object encoder --- src/Encoder/ObjectEncoder.php | 12 ++++-- src/Normalizer/PhpPropertyNameNormalizer.php | 29 +++++++++++++ tests/Unit/Encoder/ObjectEncoderTest.php | 41 +++++++++++++++++++ .../PhpPropertyNameNormalizerTest.php | 33 +++++++++++++++ 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 src/Normalizer/PhpPropertyNameNormalizer.php create mode 100644 tests/Unit/Normalizer/PhpPropertyNameNormalizerTest.php diff --git a/src/Encoder/ObjectEncoder.php b/src/Encoder/ObjectEncoder.php index 99f29b4..e9cdcd6 100644 --- a/src/Encoder/ObjectEncoder.php +++ b/src/Encoder/ObjectEncoder.php @@ -4,6 +4,7 @@ namespace Soap\Encoding\Encoder; use Closure; +use Soap\Encoding\Normalizer\PhpPropertyNameNormalizer; use Soap\Encoding\TypeInference\ComplexTypeBuilder; use Soap\Encoding\TypeInference\XsiTypeDetector; use Soap\Encoding\Xml\Reader\DocumentToLookupArrayReader; @@ -16,6 +17,7 @@ use VeeWee\Reflecta\Iso\Iso; use VeeWee\Reflecta\Lens\Lens; use function Psl\Dict\map; +use function Psl\Dict\pull; use function Psl\Dict\reindex; use function Psl\Iter\any; use function Psl\Vec\sort_by; @@ -97,7 +99,10 @@ private function to(Context $context, array $properties, object|array $data): st $properties, function (Property $property) use ($context, $data, $defaultAction) : Closure { $type = $property->getType(); - $lens = $this->decorateLensForType(property($property->getName()), $type); + $lens = $this->decorateLensForType( + property(PhpPropertyNameNormalizer::normalize($property->getName())), + $type + ); /** * @psalm-var mixed $value * @psalm-suppress PossiblyInvalidArgument - Psalm gets lost in the lens. @@ -136,7 +141,7 @@ private function from(Context $context, array $properties, string $data): object $nodes = (new DocumentToLookupArrayReader())($data); return object_data($this->className)->from( - map( + pull( $properties, function (Property $property) use ($context, $nodes): mixed { $type = $property->getType(); @@ -158,7 +163,8 @@ function (Property $property) use ($context, $nodes): mixed { onValue: fn (): mixed => $value !== null ? $this->grabIsoForProperty($context, $property)->from($value) : $defaultValue, onElements: fn (): mixed => $value !== null ? $this->grabIsoForProperty($context, $property)->from($value) : $defaultValue, ); - } + }, + static fn (Property $property) => PhpPropertyNameNormalizer::normalize($property->getName()), ) ); } diff --git a/src/Normalizer/PhpPropertyNameNormalizer.php b/src/Normalizer/PhpPropertyNameNormalizer.php new file mode 100644 index 0000000..eda9f4b --- /dev/null +++ b/src/Normalizer/PhpPropertyNameNormalizer.php @@ -0,0 +1,29 @@ +assert( + implode('', $parts) + ); + } +} diff --git a/tests/Unit/Encoder/ObjectEncoderTest.php b/tests/Unit/Encoder/ObjectEncoderTest.php index d0660e2..447e42c 100644 --- a/tests/Unit/Encoder/ObjectEncoderTest.php +++ b/tests/Unit/Encoder/ObjectEncoderTest.php @@ -125,6 +125,47 @@ public static function provideIsomorphicCases(): iterable 'xml' => 'truegreen', 'data' => new User(active: true, hat: new Hat('green')), ]; + + yield 'unsupported-property-chars' => [ + ...$baseConfig, + 'context' => self::createContext( + $xsdType, + new TypeCollection( + new Type( + XsdType::create('user') + ->withXmlTypeName('user') + ->withXmlNamespace("https://test") + ->withXmlNamespaceName('test') + ->withXmlTargetNodeName('user') + ->withMeta( + static fn (TypeMeta $meta): TypeMeta => $meta + ->withIsQualified(true) + ->withIsElement(true) + ), + new PropertyCollection( + new Property( + 'bon-jour', + XsdType::create('bon-jour') + ->withXmlTypeName('boolean') + ->withXmlTargetNodeName('bon-jour') + ->withXmlNamespace(Xmlns::xsd()->value()) + ->withXmlNamespaceName('xsd') + ->withMeta( + static fn (TypeMeta $meta): TypeMeta => $meta + ->withIsSimple(true) + ->withIsElement(true) + ->withIsQualified(true) + ) + ), + ) + ) + ) + ), + 'xml' => 'true', + 'data' => (object)[ + 'bonJour' => true, + ], + ]; } diff --git a/tests/Unit/Normalizer/PhpPropertyNameNormalizerTest.php b/tests/Unit/Normalizer/PhpPropertyNameNormalizerTest.php new file mode 100644 index 0000000..c796aee --- /dev/null +++ b/tests/Unit/Normalizer/PhpPropertyNameNormalizerTest.php @@ -0,0 +1,33 @@ +