From b25d6089fd222d62398eea159911086b60fe760f Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Thu, 2 Jan 2025 15:42:08 +0100 Subject: [PATCH] Use the new naming logic for specifying the xml type name as well so that the encoder doesnt get confused --- .../Configurator/XmlTypeInfoConfigurator.php | 13 ++++++- .../AttributeDeclaringParentTypeDetector.php | 15 -------- .../Detector/AttributeTypeNameDetector.php | 34 +++++++++++++++++++ .../Visitor/AttributeContainerVisitor.php | 29 ++-------------- 4 files changed, 49 insertions(+), 42 deletions(-) create mode 100644 src/Metadata/Converter/Types/Detector/AttributeTypeNameDetector.php diff --git a/src/Metadata/Converter/Types/Configurator/XmlTypeInfoConfigurator.php b/src/Metadata/Converter/Types/Configurator/XmlTypeInfoConfigurator.php index 0ae37b2..5a2e0b5 100644 --- a/src/Metadata/Converter/Types/Configurator/XmlTypeInfoConfigurator.php +++ b/src/Metadata/Converter/Types/Configurator/XmlTypeInfoConfigurator.php @@ -3,10 +3,14 @@ namespace Soap\WsdlReader\Metadata\Converter\Types\Configurator; +use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem; +use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem; use GoetasWebservices\XML\XSDReader\Schema\Item; use GoetasWebservices\XML\XSDReader\Schema\SchemaItem; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; use Soap\Engine\Metadata\Model\XsdType as EngineType; +use Soap\WsdlReader\Metadata\Converter\Types\Detector\AttributeTypeNameDetector; +use Soap\WsdlReader\Metadata\Converter\Types\Detector\ElementTypeNameDetector; use Soap\WsdlReader\Metadata\Converter\Types\TypesConverterContext; final class XmlTypeInfoConfigurator @@ -25,9 +29,16 @@ public function __invoke(EngineType $engineType, mixed $xsdType, TypesConverterC $targetNamespace = $xsdType->getSchema()->getTargetNamespace() ?? ''; $typeNamespace = $type?->getSchema()->getTargetNamespace() ?: $targetNamespace; + $parentContext = $context->parent()->unwrapOr(null); + $xmlTypeName = match(true) { + $parentContext && $item instanceof ElementItem => (new ElementTypeNameDetector())($item, $parentContext), + $parentContext && $item instanceof AttributeItem => (new AttributeTypeNameDetector())($item, $parentContext), + default => $typeName, + }; + return $engineType ->withXmlTargetNodeName($itemName ?: $typeName) - ->withXmlTypeName($typeName ?: $itemName ?: '') + ->withXmlTypeName($xmlTypeName) ->withXmlNamespace($typeNamespace) ->withXmlNamespaceName( $context->knownNamespaces->lookupNameFromNamespace($typeNamespace)->unwrapOr( diff --git a/src/Metadata/Converter/Types/Detector/AttributeDeclaringParentTypeDetector.php b/src/Metadata/Converter/Types/Detector/AttributeDeclaringParentTypeDetector.php index 3aab317..c523078 100644 --- a/src/Metadata/Converter/Types/Detector/AttributeDeclaringParentTypeDetector.php +++ b/src/Metadata/Converter/Types/Detector/AttributeDeclaringParentTypeDetector.php @@ -8,7 +8,6 @@ use GoetasWebservices\XML\XSDReader\Schema\SchemaItem; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; use Psl\Option\Option; -use Soap\WsdlReader\Metadata\Converter\Types\ParentContext; use function Psl\Option\none; use function Psl\Option\some; @@ -50,18 +49,4 @@ public function __invoke(AttributeItem $item, ?SchemaItem $parent): Option return none(); } - - - /** - * @param Option $parentContext - * @return Option - */ - public static function detectWithParentContext(AttributeItem $item, Option $parentContext): Option - { - /** @var self $calculate */ - static $calculate = new self(); - - return $parentContext - ->andThen(static fn (ParentContext $context) => $calculate($item, $context->currentParent())); - } } diff --git a/src/Metadata/Converter/Types/Detector/AttributeTypeNameDetector.php b/src/Metadata/Converter/Types/Detector/AttributeTypeNameDetector.php new file mode 100644 index 0000000..a3de8cf --- /dev/null +++ b/src/Metadata/Converter/Types/Detector/AttributeTypeNameDetector.php @@ -0,0 +1,34 @@ +getType() : null; + $attributeRestriction = $attributeType?->getRestriction(); + $attributeTypeName = $attributeType?->getName(); + $attributeRestrictionName = ($attributeRestriction && !$attributeRestriction->getChecks()) ? $attributeRestriction->getBase()?->getName() : null; + + $typeName = $attributeTypeName ?: ($attributeRestrictionName ?: $attribute->getName()); + + // If a name cannot be determined from the type, we fallback to the attribute name: + // Prefix the attribute name with the parent element name resulting in a more unique type-name. + if (!$attributeTypeName && !$attributeRestrictionName) { + $typeName = (new AttributeDeclaringParentTypeDetector())($attribute, $parentContext->currentParent()) + ->andThen(static fn (Type $parent): Option => from_nullable($parent->getName())) + ->map(static fn (string $parentName): string => $parentName . ucfirst($typeName)) + ->unwrapOr($typeName); + } + + return $typeName; + } +} diff --git a/src/Metadata/Converter/Types/Visitor/AttributeContainerVisitor.php b/src/Metadata/Converter/Types/Visitor/AttributeContainerVisitor.php index 2ef860d..d746da2 100644 --- a/src/Metadata/Converter/Types/Visitor/AttributeContainerVisitor.php +++ b/src/Metadata/Converter/Types/Visitor/AttributeContainerVisitor.php @@ -5,19 +5,16 @@ use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeContainer; use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem; -use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeSingle; use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group; use GoetasWebservices\XML\XSDReader\Schema\Type\Type; -use Psl\Option\Option; use Soap\Engine\Metadata\Collection\PropertyCollection; use Soap\Engine\Metadata\Model\Property; use Soap\Engine\Metadata\Model\TypeMeta; use Soap\Engine\Metadata\Model\XsdType as EngineType; use Soap\WsdlReader\Metadata\Converter\Types\Configurator; -use Soap\WsdlReader\Metadata\Converter\Types\Detector\AttributeDeclaringParentTypeDetector; +use Soap\WsdlReader\Metadata\Converter\Types\Detector\AttributeTypeNameDetector; use Soap\WsdlReader\Metadata\Converter\Types\TypesConverterContext; use function Psl\Fun\pipe; -use function Psl\Option\from_nullable; use function Psl\Result\wrap; use function Psl\Type\instance_of; use function Psl\Vec\flat_map; @@ -91,27 +88,7 @@ private function parseAttribute(AttributeItem $attribute, TypesConverterContext return $this->parseAttributes($attribute, $context); } - // Detecting the type-name for an attribute is complex. - // We first try to use the type name, - // Next up is the base type of the restriction if there aren't any restriction checks configured. - // Finally there is a fallback to the attribute name - $attributeType = $attribute instanceof AttributeSingle ? $attribute->getType() : null; - $attributeRestriction = $attributeType?->getRestriction(); - $attributeTypeName = $attributeType?->getName(); - $attributeRestrictionName = ($attributeRestriction && !$attributeRestriction->getChecks()) ? $attributeRestriction->getBase()?->getName() : null; - - $typeName = $attributeTypeName ?: ($attributeRestrictionName ?: $attribute->getName()); - $engineType = EngineType::guess($typeName); - - // If a name cannot be determined from the type, we fallback to the attribute name: - // Prefix the attribute name with the parent element name resulting in a more unique type-name. - if (!$attributeTypeName && !$attributeRestrictionName) { - $engineType = AttributeDeclaringParentTypeDetector::detectWithParentContext($attribute, $context->parent()) - ->andThen(static fn (Type $parent): Option => from_nullable($parent->getName())) - ->map(static fn (string $parentName): EngineType => $engineType->copy($parentName . ucfirst($typeName))) - ->unwrapOr($engineType); - } - + $typeName = (new AttributeTypeNameDetector())($attribute, $context->parent()->unwrap()); $configure = pipe( static fn (EngineType $engineType): EngineType => (new Configurator\AttributeConfigurator())($engineType, $attribute, $context), ); @@ -119,7 +96,7 @@ private function parseAttribute(AttributeItem $attribute, TypesConverterContext return new PropertyCollection( new Property( $attribute->getName(), - $configure($engineType) + $configure(EngineType::guess($typeName)) ) ); }