Skip to content

Commit

Permalink
Merge pull request #11 from php-soap/complex-containing-anonymous-ele…
Browse files Browse the repository at this point in the history
…ments

Extract nested inline complex element types
  • Loading branch information
veewee authored Aug 25, 2023
2 parents 879030c + 59bc765 commit 94e8b00
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 8 deletions.
5 changes: 4 additions & 1 deletion src/Metadata/Converter/SchemaToTypesConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public function __invoke(Schema $schema, TypesConverterContext $context): TypeCo
return $context->visit($schema, function () use ($schema, $context): TypeCollection {
return new TypeCollection(
...filter_nulls([
...map($schema->getTypes(), static fn (Type $type): SoapType => (new TypeVisitor())($type, $context)),
...flat_map(
$schema->getTypes(),
static fn (Type $type): TypeCollection => (new TypeVisitor())($type, $context)
),
...map($schema->getElements(), static fn (ElementDef $element): ?SoapType => (new ElementVisitor())($element, $context)),
...flat_map(
$schema->getSchemas(),
Expand Down
4 changes: 2 additions & 2 deletions src/Metadata/Converter/Types/Visitor/ElementVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Soap\WsdlReader\Metadata\Converter\Types\Visitor;

use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
use GoetasWebservices\XML\XSDReader\Schema\Element\AbstractElementSingle;
use Soap\Engine\Metadata\Model\Type as EngineType;
use Soap\Engine\Metadata\Model\XsdType as MetaType;
use Soap\WsdlReader\Metadata\Converter\Types\Configurator;
Expand All @@ -12,7 +12,7 @@

final class ElementVisitor
{
public function __invoke(ElementDef $element, TypesConverterContext $context): ?EngineType
public function __invoke(AbstractElementSingle $element, TypesConverterContext $context): ?EngineType
{
// When there is no type set on the element, we cannot do anything with it here. There should always be one somehow.
$xsdType = $element->getType();
Expand Down
56 changes: 52 additions & 4 deletions src/Metadata/Converter/Types/Visitor/TypeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,72 @@

namespace Soap\WsdlReader\Metadata\Converter\Types\Visitor;

use GoetasWebservices\XML\XSDReader\Schema\Element\AbstractElementSingle;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementRef;
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
use Soap\Engine\Metadata\Collection\TypeCollection;
use Soap\Engine\Metadata\Model\Type as EngineType;
use Soap\Engine\Metadata\Model\XsdType as MetaType;
use Soap\WsdlReader\Metadata\Converter\Types\Configurator;
use Soap\WsdlReader\Metadata\Converter\Types\TypesConverterContext;
use function Psl\Fun\pipe;
use function Psl\Vec\filter_nulls;
use function Psl\Vec\map;

final class TypeVisitor
{
public function __invoke(Type $xsdType, TypesConverterContext $context): EngineType
public function __invoke(Type $xsdType, TypesConverterContext $context): TypeCollection
{
$configure = pipe(
static fn (MetaType $metaType): MetaType => (new Configurator\TypeConfigurator())($metaType, $xsdType, $context),
);

return new EngineType(
$configure(MetaType::guess($xsdType->getName() ?? '')),
(new PropertiesVisitor())($xsdType, $context)
return new TypeCollection(
new EngineType(
$configure(MetaType::guess($xsdType->getName() ?? '')),
(new PropertiesVisitor())($xsdType, $context)
),
...$this->parseNestedInlineElements($xsdType, $context),
);
}

/**
* Complex types may contain nested inline types.
* Let's unwrap them:
*/
private function parseNestedInlineElements(Type $xsdType, TypesConverterContext $context): TypeCollection
{
if (!$xsdType instanceof ComplexType) {
return new TypeCollection();
}

$elementVisitor = new ElementVisitor();

return new TypeCollection(
...filter_nulls(
map(
$xsdType->getElements(),
static function (ElementItem $element) use ($elementVisitor, $context): ?EngineType {
if (!$element instanceof AbstractElementSingle || $element instanceof ElementRef) {
return null;
}

// There is no need to create types for simple elements like strings.
if (!$element->getType() instanceof ComplexType) {
return null;
}

// If the element links to a named type, we already know about it.
if ($element->getType()?->getName()) {
return null;
}

return $elementVisitor($element, $context);
}
)
)
);
}
}
5 changes: 4 additions & 1 deletion tests/PhpCompatibility/schema036.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ Types:
> http://test-uri/:testType {
int $int
testType2 $testType2
}
}
> http://test-uri/:testType2 {
int $int
}
51 changes: 51 additions & 0 deletions tests/PhpCompatibility/schema1002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
SOAP XML Schema 18: union with list
--FILE--
<?php
include __DIR__."/test_schema.inc";
$schema = <<<EOF
<complexType name="VoluntaryChangesType">
<annotation>
<documentation xml:lang="en">Specifies charges and/or penalties associated with making ticket changes after purchase.</documentation>
</annotation>
<sequence minOccurs="0">
<element name="Penalty" minOccurs="0">
<annotation>
<documentation xml:lang="en">Specifies penalty charges as either a currency amount or a percentage of the fare</documentation>
</annotation>
<complexType>
<attribute name="PenaltyType" type="string" use="optional">
<annotation>
<documentation xml:lang="en">Indicates the type of penalty involved in the search or response.</documentation>
</annotation>
</attribute>
<attribute name="DepartureStatus" type="string" use="optional">
<annotation>
<documentation xml:lang="en">Identifier used to indicate whether the change occurs before or after departure from the origin city.</documentation>
</annotation>
</attribute>
</complexType>
</element>
</sequence>
<attribute name="VolChangeInd" type="boolean" use="optional">
<annotation>
<documentation xml:lang="en">Indicator used to specify whether voluntary change and other penalties are involved in the search or response.</documentation>
</annotation>
</attribute>
</complexType>
EOF;
test_schema($schema,'type="tns:VoluntaryChangesType"');
?>
--EXPECT--
Methods:
> test(VoluntaryChangesType $testParam): void

Types:
> http://test-uri/:VoluntaryChangesType {
?Penalty $Penalty
@boolean $VolChangeInd
}
> http://test-uri/:Penalty {
@string $PenaltyType
@string $DepartureStatus
}

0 comments on commit 94e8b00

Please sign in to comment.