diff --git a/src/Formatter/XsdTypeFormatter.php b/src/Formatter/XsdTypeFormatter.php index 9870cd2..a077ec2 100644 --- a/src/Formatter/XsdTypeFormatter.php +++ b/src/Formatter/XsdTypeFormatter.php @@ -4,6 +4,7 @@ namespace Soap\WsdlReader\Formatter; use Soap\Engine\Metadata\Model\XsdType; +use Soap\WsdlReader\Metadata\Predicate\IsConsideredNullableType; final class XsdTypeFormatter { @@ -11,7 +12,7 @@ public function __invoke(XsdType $xsdType): string { $meta = $xsdType->getMeta(); $isList = $meta->isList()->unwrapOr(false) && !$meta->isAlias()->unwrapOr(false); - $isNullable = $meta->isNullable()->unwrapOr(false); + $isNullable = (new IsConsideredNullableType())($meta); $min = $meta->minOccurs()->unwrapOr(1); $max = $meta->maxOccurs()->unwrapOr(1); diff --git a/src/Metadata/Predicate/IsConsideredNullableType.php b/src/Metadata/Predicate/IsConsideredNullableType.php new file mode 100644 index 0000000..250c03e --- /dev/null +++ b/src/Metadata/Predicate/IsConsideredNullableType.php @@ -0,0 +1,29 @@ +isNullable()->unwrapOr(false)) { + return true; + } + + if ($meta->isNil()->unwrapOr(false)) { + return true; + } + + if ($meta->isAttribute()->unwrapOr(false)) { + // If no 'use' is defined, XSD attributes get an implicit default "optional" value + if ($meta->use()->unwrapOr('optional') === 'optional') { + return true; + } + } + + return false; + } +} diff --git a/src/Metadata/Predicate/IsConsideredScalarType.php b/src/Metadata/Predicate/IsConsideredScalarType.php new file mode 100644 index 0000000..91d237d --- /dev/null +++ b/src/Metadata/Predicate/IsConsideredScalarType.php @@ -0,0 +1,15 @@ +isSimple()->unwrapOr(false) + || $meta->isAttribute()->unwrapOr(false); + } +} diff --git a/tests/Unit/Metadata/Predicate/IsConsideredNullableTypeTest.php b/tests/Unit/Metadata/Predicate/IsConsideredNullableTypeTest.php new file mode 100644 index 0000000..0f04141 --- /dev/null +++ b/tests/Unit/Metadata/Predicate/IsConsideredNullableTypeTest.php @@ -0,0 +1,60 @@ + [ + (new TypeMeta()), + false, + ]; + yield 'nullable' => [ + (new TypeMeta())->withIsNullable(true), + true, + ]; + yield 'not-nullable' => [ + (new TypeMeta())->withIsNullable(false), + false, + ]; + yield 'nillable' => [ + (new TypeMeta())->withIsNil(true), + true, + ]; + yield 'not-nillable' => [ + (new TypeMeta())->withIsNil(false), + false, + ]; + yield 'default-attribute' => [ + (new TypeMeta())->withIsAttribute(true), + true, + ]; + yield 'optional-attribute' => [ + (new TypeMeta())->withIsAttribute(true)->withUse('optional'), + true, + ]; + yield 'required-attribute' => [ + (new TypeMeta())->withIsAttribute(true)->withUse('required'), + false, + ]; + yield 'prohibit-attribute' => [ + (new TypeMeta())->withIsAttribute(true)->withUse('prohibit'), + false, + ]; + } +} diff --git a/tests/Unit/Metadata/Predicate/IsConsideredScalarTypeTest.php b/tests/Unit/Metadata/Predicate/IsConsideredScalarTypeTest.php new file mode 100644 index 0000000..e08bac5 --- /dev/null +++ b/tests/Unit/Metadata/Predicate/IsConsideredScalarTypeTest.php @@ -0,0 +1,36 @@ + [ + (new TypeMeta()), + false, + ]; + yield 'simple' => [ + (new TypeMeta())->withIsSimple(true), + true, + ]; + yield 'attribute' => [ + (new TypeMeta())->withIsSimple(true), + true, + ]; + } +}