From 43c5d390a5e2bad45c7842b221f02f83528f8315 Mon Sep 17 00:00:00 2001 From: Tim van Dijen Date: Sat, 31 Aug 2024 18:35:54 +0200 Subject: [PATCH] Add wsdl to the library --- .github/workflows/interoperability.yml | 80 ++++++ phpunit-interoperability.xml | 8 + src/XML/wsdl/AbstractBinding.php | 104 +++++++ src/XML/wsdl/AbstractBindingOperation.php | 118 ++++++++ .../wsdl/AbstractBindingOperationFault.php | 69 +++++ .../wsdl/AbstractBindingOperationMessage.php | 71 +++++ src/XML/wsdl/AbstractDefinitions.php | 269 ++++++++++++++++++ src/XML/wsdl/AbstractDocumented.php | 63 ++++ src/XML/wsdl/AbstractExtensibilityElement.php | 54 ++++ ...AbstractExtensibleAttributesDocumented.php | 63 ++++ src/XML/wsdl/AbstractExtensibleDocumented.php | 62 ++++ src/XML/wsdl/AbstractFault.php | 86 ++++++ src/XML/wsdl/AbstractImport.php | 86 ++++++ src/XML/wsdl/AbstractMessage.php | 98 +++++++ src/XML/wsdl/AbstractParam.php | 89 ++++++ src/XML/wsdl/AbstractPart.php | 107 +++++++ src/XML/wsdl/AbstractPort.php | 86 ++++++ src/XML/wsdl/AbstractPortType.php | 89 ++++++ src/XML/wsdl/AbstractPortTypeOperation.php | 132 +++++++++ src/XML/wsdl/AbstractService.php | 99 +++++++ src/XML/wsdl/AbstractTypes.php | 24 ++ src/XML/wsdl/Binding.php | 58 ++++ src/XML/wsdl/BindingOperation.php | 63 ++++ src/XML/wsdl/BindingOperationFault.php | 54 ++++ src/XML/wsdl/BindingOperationInput.php | 54 ++++ src/XML/wsdl/BindingOperationOutput.php | 54 ++++ src/XML/wsdl/Definitions.php | 68 +++++ src/XML/wsdl/Fault.php | 42 +++ src/XML/wsdl/Import.php | 42 +++ src/XML/wsdl/Input.php | 42 +++ src/XML/wsdl/Message.php | 55 ++++ src/XML/wsdl/Output.php | 42 +++ src/XML/wsdl/Part.php | 43 +++ src/XML/wsdl/Port.php | 55 ++++ src/XML/wsdl/PortType.php | 42 +++ src/XML/wsdl/PortTypeOperation.php | 93 ++++++ src/XML/wsdl/Service.php | 55 ++++ src/XML/wsdl/Types.php | 53 ++++ tests/InterOperability/DefinitionsTest.php | 53 ++++ .../XML/wsdl/BindingOperationTest.php | 95 +++++++ tests/WSSecurity/XML/wsdl/BindingTest.php | 107 +++++++ tests/WSSecurity/XML/wsdl/DefinitionsTest.php | 192 +++++++++++++ tests/WSSecurity/XML/wsdl/FaultTest.php | 65 +++++ tests/WSSecurity/XML/wsdl/ImportTest.php | 65 +++++ tests/WSSecurity/XML/wsdl/InputTest.php | 67 +++++ tests/WSSecurity/XML/wsdl/MessageTest.php | 89 ++++++ tests/WSSecurity/XML/wsdl/OutputTest.php | 67 +++++ tests/WSSecurity/XML/wsdl/PartTest.php | 65 +++++ tests/WSSecurity/XML/wsdl/PortTest.php | 66 +++++ .../XML/wsdl/PortTypeOperationInputTest.php | 77 +++++ .../XML/wsdl/PortTypeOperationOutputTest.php | 77 +++++ tests/WSSecurity/XML/wsdl/PortTypeTest.php | 82 ++++++ tests/WSSecurity/XML/wsdl/ServiceTest.php | 77 +++++ tests/WSSecurity/XML/wsdl/TypesTest.php | 67 +++++ tests/resources/interoperability/adfs_mex.xml | 1 + tests/resources/xml/wsdl_Binding.xml | 19 ++ tests/resources/xml/wsdl_BindingOperation.xml | 15 + tests/resources/xml/wsdl_Definitions.xml | 39 +++ tests/resources/xml/wsdl_Fault.xml | 1 + tests/resources/xml/wsdl_Import.xml | 1 + tests/resources/xml/wsdl_Input.xml | 1 + tests/resources/xml/wsdl_Message.xml | 5 + tests/resources/xml/wsdl_Output.xml | 1 + tests/resources/xml/wsdl_Part.xml | 1 + tests/resources/xml/wsdl_Port.xml | 3 + tests/resources/xml/wsdl_PortType.xml | 12 + .../xml/wsdl_PortTypeOperation_Input.xml | 5 + .../xml/wsdl_PortTypeOperation_Output.xml | 5 + tests/resources/xml/wsdl_Service.xml | 9 + tests/resources/xml/wsdl_Types.xml | 3 + 70 files changed, 4204 insertions(+) create mode 100644 .github/workflows/interoperability.yml create mode 100644 phpunit-interoperability.xml create mode 100644 src/XML/wsdl/AbstractBinding.php create mode 100644 src/XML/wsdl/AbstractBindingOperation.php create mode 100644 src/XML/wsdl/AbstractBindingOperationFault.php create mode 100644 src/XML/wsdl/AbstractBindingOperationMessage.php create mode 100644 src/XML/wsdl/AbstractDefinitions.php create mode 100644 src/XML/wsdl/AbstractDocumented.php create mode 100644 src/XML/wsdl/AbstractExtensibilityElement.php create mode 100644 src/XML/wsdl/AbstractExtensibleAttributesDocumented.php create mode 100644 src/XML/wsdl/AbstractExtensibleDocumented.php create mode 100644 src/XML/wsdl/AbstractFault.php create mode 100644 src/XML/wsdl/AbstractImport.php create mode 100644 src/XML/wsdl/AbstractMessage.php create mode 100644 src/XML/wsdl/AbstractParam.php create mode 100644 src/XML/wsdl/AbstractPart.php create mode 100644 src/XML/wsdl/AbstractPort.php create mode 100644 src/XML/wsdl/AbstractPortType.php create mode 100644 src/XML/wsdl/AbstractPortTypeOperation.php create mode 100644 src/XML/wsdl/AbstractService.php create mode 100644 src/XML/wsdl/AbstractTypes.php create mode 100644 src/XML/wsdl/Binding.php create mode 100644 src/XML/wsdl/BindingOperation.php create mode 100644 src/XML/wsdl/BindingOperationFault.php create mode 100644 src/XML/wsdl/BindingOperationInput.php create mode 100644 src/XML/wsdl/BindingOperationOutput.php create mode 100644 src/XML/wsdl/Definitions.php create mode 100644 src/XML/wsdl/Fault.php create mode 100644 src/XML/wsdl/Import.php create mode 100644 src/XML/wsdl/Input.php create mode 100644 src/XML/wsdl/Message.php create mode 100644 src/XML/wsdl/Output.php create mode 100644 src/XML/wsdl/Part.php create mode 100644 src/XML/wsdl/Port.php create mode 100644 src/XML/wsdl/PortType.php create mode 100644 src/XML/wsdl/PortTypeOperation.php create mode 100644 src/XML/wsdl/Service.php create mode 100644 src/XML/wsdl/Types.php create mode 100644 tests/InterOperability/DefinitionsTest.php create mode 100644 tests/WSSecurity/XML/wsdl/BindingOperationTest.php create mode 100644 tests/WSSecurity/XML/wsdl/BindingTest.php create mode 100644 tests/WSSecurity/XML/wsdl/DefinitionsTest.php create mode 100644 tests/WSSecurity/XML/wsdl/FaultTest.php create mode 100644 tests/WSSecurity/XML/wsdl/ImportTest.php create mode 100644 tests/WSSecurity/XML/wsdl/InputTest.php create mode 100644 tests/WSSecurity/XML/wsdl/MessageTest.php create mode 100644 tests/WSSecurity/XML/wsdl/OutputTest.php create mode 100644 tests/WSSecurity/XML/wsdl/PartTest.php create mode 100644 tests/WSSecurity/XML/wsdl/PortTest.php create mode 100644 tests/WSSecurity/XML/wsdl/PortTypeOperationInputTest.php create mode 100644 tests/WSSecurity/XML/wsdl/PortTypeOperationOutputTest.php create mode 100644 tests/WSSecurity/XML/wsdl/PortTypeTest.php create mode 100644 tests/WSSecurity/XML/wsdl/ServiceTest.php create mode 100644 tests/WSSecurity/XML/wsdl/TypesTest.php create mode 100644 tests/resources/interoperability/adfs_mex.xml create mode 100644 tests/resources/xml/wsdl_Binding.xml create mode 100644 tests/resources/xml/wsdl_BindingOperation.xml create mode 100644 tests/resources/xml/wsdl_Definitions.xml create mode 100644 tests/resources/xml/wsdl_Fault.xml create mode 100644 tests/resources/xml/wsdl_Import.xml create mode 100644 tests/resources/xml/wsdl_Input.xml create mode 100644 tests/resources/xml/wsdl_Message.xml create mode 100644 tests/resources/xml/wsdl_Output.xml create mode 100644 tests/resources/xml/wsdl_Part.xml create mode 100644 tests/resources/xml/wsdl_Port.xml create mode 100644 tests/resources/xml/wsdl_PortType.xml create mode 100644 tests/resources/xml/wsdl_PortTypeOperation_Input.xml create mode 100644 tests/resources/xml/wsdl_PortTypeOperation_Output.xml create mode 100644 tests/resources/xml/wsdl_Service.xml create mode 100644 tests/resources/xml/wsdl_Types.xml diff --git a/.github/workflows/interoperability.yml b/.github/workflows/interoperability.yml new file mode 100644 index 00000000..c0d376e3 --- /dev/null +++ b/.github/workflows/interoperability.yml @@ -0,0 +1,80 @@ +--- + +name: Interoperability + +on: # yamllint disable-line rule:truthy + push: + branches: ['**'] + paths-ignore: + - '**.md' + - '**.yml' + pull_request: + branches: [master, release-*] + paths-ignore: + - '**.md' + - '**.yml' + workflow_dispatch: + +jobs: + edugain: + name: "Interoperability tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }}" + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest] + php-versions: ['8.2'] + + steps: + - name: Setup PHP, with composer and extensions + # https://github.com/shivammathur/setup-php + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ctype, date, dom, hash, mbstring, openssl, pcre, spl, xml + tools: composer:v2 + ini-values: error_reporting=E_ALL, memory_limit=-1 + coverage: none + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - uses: actions/checkout@v4 + + - name: Cache composer dependencies + uses: actions/cache@v4 + with: + path: $(composer config cache-files-dir) + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Get current date + id: date + run: | + echo "{date}={$(date +'%Y-%m-%d')}" >> "$GITHUB_STATE" + + - name: Cache metadata + id: cache-metadata + uses: actions/cache@v4 + with: + path: /tmp/metadata + key: ${{ runner.os }}-metadata-${{ env.date }} + restore-keys: ${{ runner.os }}-metadata- + + - name: Run unit tests + run: | + ./vendor/bin/phpunit -c phpunit-interoperability.xml diff --git a/phpunit-interoperability.xml b/phpunit-interoperability.xml new file mode 100644 index 00000000..ebfec763 --- /dev/null +++ b/phpunit-interoperability.xml @@ -0,0 +1,8 @@ + + + + + ./tests/InterOperability + + + diff --git a/src/XML/wsdl/AbstractBinding.php b/src/XML/wsdl/AbstractBinding.php new file mode 100644 index 00000000..77769832 --- /dev/null +++ b/src/XML/wsdl/AbstractBinding.php @@ -0,0 +1,104 @@ +name; + } + + + /** + * Collect the value of the type-property. + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + + /** + * Collect the value of the operation-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\BindingOperation[] + */ + public function getOperation(): array + { + return $this->operation; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tBinding to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tBinding. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + $e->setAttribute('type', $this->getType()); + + foreach ($this->getOperation() as $operation) { + $operation->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractBindingOperation.php b/src/XML/wsdl/AbstractBindingOperation.php new file mode 100644 index 00000000..8ede5a28 --- /dev/null +++ b/src/XML/wsdl/AbstractBindingOperation.php @@ -0,0 +1,118 @@ +name; + } + + + /** + * Collect the value of the input-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\BindingOperationInput|null + */ + public function getInput(): ?BindingOperationInput + { + return $this->input; + } + + + /** + * Collect the value of the output-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\BindingOperationOutput|null + */ + public function getOutput(): ?BindingOperationOutput + { + return $this->output; + } + + + /** + * Collect the value of the fault-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\BindingOperationFault[] + */ + public function getFault(): array + { + return $this->fault; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tBindingOperation to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tBindingOperation. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + + $this->getInput()?->toXML($e); + $this->getOutput()?->toXML($e); + + foreach ($this->getFault() as $fault) { + $fault->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractBindingOperationFault.php b/src/XML/wsdl/AbstractBindingOperationFault.php new file mode 100644 index 00000000..dc26d3b6 --- /dev/null +++ b/src/XML/wsdl/AbstractBindingOperationFault.php @@ -0,0 +1,69 @@ +name; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tBindingOperationFault to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tBindingOperationFault. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + $e->setAttribute('name', $this->getName()); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractBindingOperationMessage.php b/src/XML/wsdl/AbstractBindingOperationMessage.php new file mode 100644 index 00000000..d2fbd6e9 --- /dev/null +++ b/src/XML/wsdl/AbstractBindingOperationMessage.php @@ -0,0 +1,71 @@ +name; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && empty($this->getName()); + } + + + /** + * Convert this tBindingOperationMessage to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tBindingOperationMessage. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + if ($this->getName() !== null) { + $e->setAttribute('name', $this->getName()); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractDefinitions.php b/src/XML/wsdl/AbstractDefinitions.php new file mode 100644 index 00000000..0a6753a0 --- /dev/null +++ b/src/XML/wsdl/AbstractDefinitions.php @@ -0,0 +1,269 @@ +getName(); + }, + $message, + ); + Assert::uniqueValues( + $messageNames, + "Message-elements must have unique names.", + SchemaViolationException::class, + ); + + $portTypeNames = array_map( + function ($x) { + return $x->getName(); + }, + $portType, + ); + Assert::uniqueValues( + $portTypeNames, + "PortType-elements must have unique names.", + SchemaViolationException::class, + ); + + $bindingNames = array_map( + function ($x) { + return $x->getName(); + }, + $binding, + ); + Assert::uniqueValues( + $bindingNames, + "Binding-elements must have unique names.", + SchemaViolationException::class, + ); + + $serviceNames = array_map( + function ($x) { + return $x->getName(); + }, + $service, + ); + Assert::uniqueValues( + $serviceNames, + "Service-elements must have unique names.", + SchemaViolationException::class, + ); + + $importNamespaces = array_map( + function ($x) { + return $x->getNamespace(); + }, + $import, + ); + Assert::uniqueValues( + $importNamespaces, + "Import-elements must have unique namespaces.", + SchemaViolationException::class, + ); + + parent::__construct($elements); + } + + + /** + * Collect the value of the name-property. + * + * @return string|null + */ + public function getName(): ?string + { + return $this->name; + } + + + /** + * Collect the value of the targetNamespace-property. + * + * @return string|null + */ + public function getTargetNamespace(): ?string + { + return $this->targetNamespace; + } + + + /** + * Collect the value of the import-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Import[] + */ + public function getImport(): array + { + return $this->import; + } + + + /** + * Collect the value of the typrd-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Types[] + */ + public function getTypes(): array + { + return $this->types; + } + + + /** + * Collect the value of the message-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Message[] + */ + public function getMessage(): array + { + return $this->message; + } + + + /** + * Collect the value of the portType-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\PortType[] + */ + public function getPortType(): array + { + return $this->portType; + } + + + /** + * Collect the value of the binding-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Binding[] + */ + public function getBinding(): array + { + return $this->binding; + } + + + /** + * Collect the value of the service-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Service[] + */ + public function getService(): array + { + return $this->service; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && + empty($this->getName()) && + empty($this->getTargetNamespace()) && + empty($this->getImport()) && + empty($this->getTypes()) && + empty($this->getMessage()) && + empty($this->getPortType()) && + empty($this->getBinding()) && + empty($this->getService()); + } + + + /** + * Convert this tDefinitions to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tDefinitions. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + if ($this->getTargetNamespace() !== null) { + $e->setAttribute('targetNamespace', $this->getTargetNamespace()); + } + + if ($this->getName() !== null) { + $e->setAttribute('name', $this->getName()); + } + + foreach ($this->getImport() as $import) { + $import->toXML($e); + } + + foreach ($this->getTypes() as $types) { + $types->toXML($e); + } + + foreach ($this->getMessage() as $message) { + $message->toXML($e); + } + + foreach ($this->getPortType() as $portType) { + $portType->toXML($e); + } + + foreach ($this->getBinding() as $binding) { + $binding->toXML($e); + } + + foreach ($this->getService() as $service) { + $service->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractDocumented.php b/src/XML/wsdl/AbstractDocumented.php new file mode 100644 index 00000000..b17eb111 --- /dev/null +++ b/src/XML/wsdl/AbstractDocumented.php @@ -0,0 +1,63 @@ +documentation; + } + */ + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return /*empty($this->documentation)*/ true; + } + + + /** + * Convert this tDocumented to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tDocumented. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + //$this->getDocumentation()?->toXML($e); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractExtensibilityElement.php b/src/XML/wsdl/AbstractExtensibilityElement.php new file mode 100644 index 00000000..b82c3f60 --- /dev/null +++ b/src/XML/wsdl/AbstractExtensibilityElement.php @@ -0,0 +1,54 @@ +required; + } + + + /** + * Convert this tExtensibilityElement to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tExtensibilityElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + if ($this->getRequired() !== null) { + $e->setAttribute('required', $this->getRequired() ? 'true' : 'false'); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractExtensibleAttributesDocumented.php b/src/XML/wsdl/AbstractExtensibleAttributesDocumented.php new file mode 100644 index 00000000..a1bcd889 --- /dev/null +++ b/src/XML/wsdl/AbstractExtensibleAttributesDocumented.php @@ -0,0 +1,63 @@ +setAttributesNS($attributes); + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && empty($this->getAttributesNS()); + } + + + /** + * Convert this tExtensibleAttributesDocumented to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tExtensibleAttributesDocumented. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractExtensibleDocumented.php b/src/XML/wsdl/AbstractExtensibleDocumented.php new file mode 100644 index 00000000..1b26801a --- /dev/null +++ b/src/XML/wsdl/AbstractExtensibleDocumented.php @@ -0,0 +1,62 @@ +setElements($elements); + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && empty($this->elements); + } + + + /** + * Convert this tExtensibleDocumented to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tExtensibleDocumented. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + foreach ($this->getElements() as $elt) { + $elt->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractFault.php b/src/XML/wsdl/AbstractFault.php new file mode 100644 index 00000000..0c3feee2 --- /dev/null +++ b/src/XML/wsdl/AbstractFault.php @@ -0,0 +1,86 @@ +name; + } + + + /** + * Collect the value of the message-property. + * + * @return string + */ + public function getMessage(): string + { + return $this->message; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tParam to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tParam. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + $e->setAttribute('message', $this->getMessage()); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractImport.php b/src/XML/wsdl/AbstractImport.php new file mode 100644 index 00000000..56f0b71b --- /dev/null +++ b/src/XML/wsdl/AbstractImport.php @@ -0,0 +1,86 @@ + $attributes + */ + public function __construct( + protected string $namespace, + protected string $location, + array $attributes = [], + ) { + Assert::validURI($namespace, SchemaViolationException::class); + Assert::validURI($location, SchemaViolationException::class); + + parent::__construct($attributes); + } + + + /** + * Collect the value of the namespace-property. + * + * @return string + */ + public function getNamespace(): string + { + return $this->namespace; + } + + + /** + * Collect the value of the location-property. + * + * @return string + */ + public function getLocation(): string + { + return $this->location; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tImport to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tImport. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('namespace', $this->getNamespace()); + $e->setAttribute('location', $this->getLocation()); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractMessage.php b/src/XML/wsdl/AbstractMessage.php new file mode 100644 index 00000000..87af88e8 --- /dev/null +++ b/src/XML/wsdl/AbstractMessage.php @@ -0,0 +1,98 @@ +getName(); + }, + $parts, + ); + Assert::uniqueValues($partNames, "Part-elements must have unique names.", SchemaViolationException::class); + + parent::__construct($elements); + } + + + /** + * Collect the value of the name-property. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + + /** + * Collect the value of the parts-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Part[] + */ + public function getParts(): array + { + return $this->parts; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tParam to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tParam. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + $e->setAttribute('name', $this->getName()); + + foreach ($this->getParts() as $part) { + $part->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractParam.php b/src/XML/wsdl/AbstractParam.php new file mode 100644 index 00000000..90e4f3e7 --- /dev/null +++ b/src/XML/wsdl/AbstractParam.php @@ -0,0 +1,89 @@ +name; + } + + + /** + * Collect the value of the message-property. + * + * @return string + */ + public function getMessage(): string + { + return $this->message; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tParam to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tParam. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + if ($this->getName() !== null) { + $e->setAttribute('name', $this->getName()); + } + + $e->setAttribute('message', $this->getMessage()); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractPart.php b/src/XML/wsdl/AbstractPart.php new file mode 100644 index 00000000..b2e9c73a --- /dev/null +++ b/src/XML/wsdl/AbstractPart.php @@ -0,0 +1,107 @@ +name; + } + + + /** + * Collect the value of the element-property. + * + * @return string|null + */ + public function getElement(): ?string + { + return $this->element; + } + + + /** + * Collect the value of the type-property. + * + * @return string|null + */ + public function getType(): ?string + { + return $this->type; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tPart to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tPart. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + + if ($this->getElement() !== null) { + $e->setAttribute('element', $this->getElement()); + } + + if ($this->getType() !== null) { + $e->setAttribute('type', $this->getType()); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractPort.php b/src/XML/wsdl/AbstractPort.php new file mode 100644 index 00000000..9de13bea --- /dev/null +++ b/src/XML/wsdl/AbstractPort.php @@ -0,0 +1,86 @@ +name; + } + + + /** + * Collect the value of the binding-property. + * + * @return string + */ + public function getBinding(): string + { + return $this->binding; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tPort to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tPort. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + $e->setAttribute('binding', $this->getBinding()); + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractPortType.php b/src/XML/wsdl/AbstractPortType.php new file mode 100644 index 00000000..4651c3bd --- /dev/null +++ b/src/XML/wsdl/AbstractPortType.php @@ -0,0 +1,89 @@ +name; + } + + + /** + * Collect the value of the operation-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\PortTypeOperation[] + */ + public function getOperation(): array + { + return $this->operation; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tPortType to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tPortType. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + + foreach ($this->getOperation() as $operation) { + $operation->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractPortTypeOperation.php b/src/XML/wsdl/AbstractPortTypeOperation.php new file mode 100644 index 00000000..f443700a --- /dev/null +++ b/src/XML/wsdl/AbstractPortTypeOperation.php @@ -0,0 +1,132 @@ +name; + } + + + /** + * Collect the value of the parameterOrder-property + * + * @return string|null + */ + public function getParameterOrder(): ?string + { + return $this->parameterOrder; + } + + + /** + * Collect the value of the input-property + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\AbstractParam|null + */ + public function getInput(): ?AbstractParam + { + return $this->input; + } + + + /** + * Collect the value of the output-property + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\AbstractParam|null + */ + public function getOutput(): ?AbstractParam + { + return $this->output; + } + + + /** + * Collect the value of the fault-property + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Fault[] + */ + public function getFault(): array + { + return $this->fault; + } + + + /** + * Convert this RequestResponseOrOneWayOperation to XML. + * + * @param \DOMElement|null $parent The element we should add this organization to. + * @return \DOMElement This Organization-element. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + $e->setAttribute('name', $this->getName()); + + if ($this->getParameterOrder() !== null) { + $e->setAttribute('parameterOrder', $this->getParameterOrder()); + } + + $this->getInput()?->toXML($e); + $this->getOutput()?->toXML($e); + + foreach ($this->getFault() as $fault) { + $fault->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractService.php b/src/XML/wsdl/AbstractService.php new file mode 100644 index 00000000..d65cc6ab --- /dev/null +++ b/src/XML/wsdl/AbstractService.php @@ -0,0 +1,99 @@ +getName(); + }, + $ports, + ); + Assert::uniqueValues($portNames, "Port-elements must have unique names.", SchemaViolationException::class); + + parent::__construct($elements); + } + + + /** + * Collect the value of the name-property. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + + /** + * Collect the value of the ports-property. + * + * @return \SimpleSAML\WSSecurity\XML\wsdl\Port[] + */ + public function getPorts(): array + { + return $this->ports; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + // Upstream abstract elements can be empty, but this one cannot + return false; + } + + + /** + * Convert this tService to XML. + * + * @param \DOMElement|null $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this tService. + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + $e->setAttribute('name', $this->getName()); + + foreach ($this->getPorts() as $port) { + $port->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/wsdl/AbstractTypes.php b/src/XML/wsdl/AbstractTypes.php new file mode 100644 index 00000000..694ed419 --- /dev/null +++ b/src/XML/wsdl/AbstractTypes.php @@ -0,0 +1,24 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $operation = BindingOperation::getChildrenOfClass($xml); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + self::getAttribute($xml, 'type'), + $operation, + $children, + ); + } +} diff --git a/src/XML/wsdl/BindingOperation.php b/src/XML/wsdl/BindingOperation.php new file mode 100644 index 00000000..bce4b44f --- /dev/null +++ b/src/XML/wsdl/BindingOperation.php @@ -0,0 +1,63 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $input = BindingOperationInput::getChildrenOfClass($xml); + $output = BindingOperationOutput::getChildrenOfClass($xml); + $faults = BindingOperationFault::getChildrenOfClass($xml); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + array_pop($input), + array_pop($output), + $faults, + $children, + ); + } +} diff --git a/src/XML/wsdl/BindingOperationFault.php b/src/XML/wsdl/BindingOperationFault.php new file mode 100644 index 00000000..73dc2208 --- /dev/null +++ b/src/XML/wsdl/BindingOperationFault.php @@ -0,0 +1,54 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + $children, + ); + } +} diff --git a/src/XML/wsdl/BindingOperationInput.php b/src/XML/wsdl/BindingOperationInput.php new file mode 100644 index 00000000..d4182d19 --- /dev/null +++ b/src/XML/wsdl/BindingOperationInput.php @@ -0,0 +1,54 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getOptionalAttribute($xml, 'name', null), + $children, + ); + } +} diff --git a/src/XML/wsdl/BindingOperationOutput.php b/src/XML/wsdl/BindingOperationOutput.php new file mode 100644 index 00000000..a55e2458 --- /dev/null +++ b/src/XML/wsdl/BindingOperationOutput.php @@ -0,0 +1,54 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getOptionalAttribute($xml, 'name', null), + $children, + ); + } +} diff --git a/src/XML/wsdl/Definitions.php b/src/XML/wsdl/Definitions.php new file mode 100644 index 00000000..a011e3d9 --- /dev/null +++ b/src/XML/wsdl/Definitions.php @@ -0,0 +1,68 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $import = Import::getChildrenOfClass($xml); + $types = Types::getChildrenOfClass($xml); + $message = Message::getChildrenOfClass($xml); + $portType = PortType::getChildrenOfClass($xml); + $binding = Binding::getChildrenOfClass($xml); + $service = Service::getChildrenOfClass($xml); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getOptionalAttribute($xml, 'targetNamespace'), + self::getOptionalAttribute($xml, 'name'), + $import, + $types, + $message, + $portType, + $binding, + $service, + $children, + ); + } +} diff --git a/src/XML/wsdl/Fault.php b/src/XML/wsdl/Fault.php new file mode 100644 index 00000000..ca0b5085 --- /dev/null +++ b/src/XML/wsdl/Fault.php @@ -0,0 +1,42 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'name'), + self::getAttribute($xml, 'message'), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/Import.php b/src/XML/wsdl/Import.php new file mode 100644 index 00000000..20520a45 --- /dev/null +++ b/src/XML/wsdl/Import.php @@ -0,0 +1,42 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'namespace'), + self::getAttribute($xml, 'location'), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/Input.php b/src/XML/wsdl/Input.php new file mode 100644 index 00000000..f136ac30 --- /dev/null +++ b/src/XML/wsdl/Input.php @@ -0,0 +1,42 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'message'), + self::getOptionalAttribute($xml, 'name'), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/Message.php b/src/XML/wsdl/Message.php new file mode 100644 index 00000000..a4a620d0 --- /dev/null +++ b/src/XML/wsdl/Message.php @@ -0,0 +1,55 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + Part::getChildrenOfClass($xml), + $children, + ); + } +} diff --git a/src/XML/wsdl/Output.php b/src/XML/wsdl/Output.php new file mode 100644 index 00000000..02c3f8c9 --- /dev/null +++ b/src/XML/wsdl/Output.php @@ -0,0 +1,42 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'message'), + self::getOptionalAttribute($xml, 'name'), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/Part.php b/src/XML/wsdl/Part.php new file mode 100644 index 00000000..33821e95 --- /dev/null +++ b/src/XML/wsdl/Part.php @@ -0,0 +1,43 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'name'), + self::getOptionalAttribute($xml, 'element'), + self::getOptionalAttribute($xml, 'type'), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/Port.php b/src/XML/wsdl/Port.php new file mode 100644 index 00000000..037e56b9 --- /dev/null +++ b/src/XML/wsdl/Port.php @@ -0,0 +1,55 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + self::getAttribute($xml, 'binding'), + $children, + ); + } +} diff --git a/src/XML/wsdl/PortType.php b/src/XML/wsdl/PortType.php new file mode 100644 index 00000000..4b48d39a --- /dev/null +++ b/src/XML/wsdl/PortType.php @@ -0,0 +1,42 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + self::getAttribute($xml, 'name'), + PortTypeOperation::getChildrenOfClass($xml), + self::getAttributesNSFromXML($xml), + ); + } +} diff --git a/src/XML/wsdl/PortTypeOperation.php b/src/XML/wsdl/PortTypeOperation.php new file mode 100644 index 00000000..d5d6db49 --- /dev/null +++ b/src/XML/wsdl/PortTypeOperation.php @@ -0,0 +1,93 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $first = null; + foreach ($xml->childNodes as $element) { + if (!($element instanceof DOMElement)) { + continue; + } elseif ($element->namespaceURI === static::NS) { + if ($element->localName === 'input') { + $first = Input::class; + break; + } elseif ($element->localName === 'output') { + $first = Output::class; + break; + } + } + } + + Assert::notNull($first, SchemaViolationException::class); + + if ($first === Input::class) { + // xs:group solicit-response-or-notification-operation + $input = Input::getChildrenOfClass($xml); + $input = array_pop($input); + Assert::notNull($input, SchemaViolationException::class); + $output = Output::getChildrenOfClass($xml); + $output = array_pop($output); + } else { + // xs:group request-response-or-one-way-operation + // NOTE: input is really output and vice versa!! + $input = Output::getChildrenOfClass($xml); + $input = array_pop($input); + Assert::notNull($input, SchemaViolationException::class); + $output = Input::getChildrenOfClass($xml); + $output = array_pop($output); + } + + $elements = []; + foreach ($xml->childNodes as $element) { + if (!($element instanceof DOMElement)) { + continue; + } elseif ($element->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $elements[] = new Chunk($element); + } + + return new static( + self::getAttribute($xml, 'name'), + self::getOptionalAttribute($xml, 'parameterOrder'), + $input, + $output, + Fault::getChildrenOfClass($xml), + $elements, + ); + } +} diff --git a/src/XML/wsdl/Service.php b/src/XML/wsdl/Service.php new file mode 100644 index 00000000..c0fe82bd --- /dev/null +++ b/src/XML/wsdl/Service.php @@ -0,0 +1,55 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + self::getAttribute($xml, 'name'), + Port::getChildrenOfClass($xml), + $children, + ); + } +} diff --git a/src/XML/wsdl/Types.php b/src/XML/wsdl/Types.php new file mode 100644 index 00000000..71703334 --- /dev/null +++ b/src/XML/wsdl/Types.php @@ -0,0 +1,53 @@ +localName, static::LOCALNAME, InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $children = []; + foreach ($xml->childNodes as $child) { + if (!($child instanceof DOMElement)) { + continue; + } elseif ($child->namespaceURI === static::NS) { + // Only other namespaces are allowed + continue; + } + + $children[] = new Chunk($child); + } + + return new static( + $children, + ); + } +} diff --git a/tests/InterOperability/DefinitionsTest.php b/tests/InterOperability/DefinitionsTest.php new file mode 100644 index 00000000..a7a511fb --- /dev/null +++ b/tests/InterOperability/DefinitionsTest.php @@ -0,0 +1,53 @@ +assertTrue($shouldPass); + } catch (AssertionFailedException $e) { + fwrite(STDERR, $e->getFile() . '(' . strval($e->getLine()) . '):' . $e->getMessage()); + fwrite(STDERR, $e->getTraceAsString()); + $this->assertFalse($shouldPass); + } + } + + + /** + * @return array + */ + public static function provideMex(): array + { + return [ + 'MicrosoftAdfs' => [ + true, + DOMDocumentFactory::fromFile( + dirname(__FILE__, 2) . '/resources/interoperability/adfs_mex.xml', + )->documentElement, + ], + ]; + } +} diff --git a/tests/WSSecurity/XML/wsdl/BindingOperationTest.php b/tests/WSSecurity/XML/wsdl/BindingOperationTest.php new file mode 100644 index 00000000..5009e106 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/BindingOperationTest.php @@ -0,0 +1,95 @@ +SomeChunk', + ); + $inputChild = DOMDocumentFactory::fromString( + 'InputChunk', + ); + $outputChild = DOMDocumentFactory::fromString( + 'OutputChunk', + ); + $faultOneChild = DOMDocumentFactory::fromString( + 'FaultOneChunk', + ); + $faultTwoChild = DOMDocumentFactory::fromString( + 'FaultTwoChunk', + ); + + $input = new BindingOperationInput('CustomInputName', [new Chunk($inputChild->documentElement)]); + $output = new BindingOperationOutput('CustomOutputName', [new Chunk($outputChild->documentElement)]); + $faultOne = new BindingOperationFault('CustomFaultOne', [new Chunk($faultOneChild->documentElement)]); + $faultTwo = new BindingOperationFault('CustomFaultTwo', [new Chunk($faultTwoChild->documentElement)]); + + $bindingOperation = new BindingOperation( + 'SomeName', + $input, + $output, + [$faultOne, $faultTwo], + [new Chunk($child->documentElement)], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($bindingOperation), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/BindingTest.php b/tests/WSSecurity/XML/wsdl/BindingTest.php new file mode 100644 index 00000000..03517156 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/BindingTest.php @@ -0,0 +1,107 @@ +SomeChunk', + ); + $operationChild = DOMDocumentFactory::fromString( + 'OperationChunk', + ); + $inputChild = DOMDocumentFactory::fromString( + 'InputChunk', + ); + $outputChild = DOMDocumentFactory::fromString( + 'OutputChunk', + ); + $faultOneChild = DOMDocumentFactory::fromString( + 'FaultOneChunk', + ); + $faultTwoChild = DOMDocumentFactory::fromString( + 'FaultTwoChunk', + ); + + $input = new BindingOperationInput('CustomInputName', [new Chunk($inputChild->documentElement)]); + $output = new BindingOperationOutput('CustomOutputName', [new Chunk($outputChild->documentElement)]); + $faultOne = new BindingOperationFault('CustomFaultOne', [new Chunk($faultOneChild->documentElement)]); + $faultTwo = new BindingOperationFault('CustomFaultTwo', [new Chunk($faultTwoChild->documentElement)]); + + $operationOne = new BindingOperation( + 'OperationOne', + $input, + $output, + [$faultOne, $faultTwo], + [new Chunk($operationChild->documentElement)], + ); + $operationTwo = new BindingOperation('OperationTwo'); + + $binding = new Binding( + 'MyBinding', + 'ssp:CustomType', + [$operationOne, $operationTwo], + [new Chunk($child->documentElement)], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($binding), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/DefinitionsTest.php b/tests/WSSecurity/XML/wsdl/DefinitionsTest.php new file mode 100644 index 00000000..9e4f0664 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/DefinitionsTest.php @@ -0,0 +1,192 @@ +TypesChunk', + ); + + $types = new Types([new Chunk($typesChild->documentElement)]); + + // Message + $messageChild = DOMDocumentFactory::fromString( + 'MessageChunk', + ); + + $messageAttr1 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $messageAttr2 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr2', 'value2'); + $part1 = new Part('CustomName', 'ssp:CustomElement', 'wsdl:part', [$messageAttr1]); + + $message = new Message('SomeName', [$part1], [new Chunk($messageChild->documentElement)]); + + // PortType + $port = new XMLAttribute(C::NAMESPACE, 'ssp', 'port', '1234'); + $portAttr1 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $portAttr2 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr2', 'value2'); + $portAttr3 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr3', 'value3'); + + $input = new Input('ssp:CustomInputMessage', 'CustomInputName', [$portAttr1]); + $output = new Output('ssp:CustomOutputMessage', 'CustomOutputName', [$portAttr2]); + $fault = new Fault('CustomFaultName', 'ssp:CustomFaultMessage', [$portAttr3]); + + $inputOperation = new Operation('Input', '0836217462 0836217463', $input, $output, [$fault]); + + $portType = new PortType('MyPort', [$inputOperation], [$port]); + + // Binding + $bindingChild = DOMDocumentFactory::fromString( + 'BindingChunk', + ); + $operationChild = DOMDocumentFactory::fromString( + 'OperationChunk', + ); + $inputChild = DOMDocumentFactory::fromString( + 'InputChunk', + ); + $outputChild = DOMDocumentFactory::fromString( + 'OutputChunk', + ); + $faultOneChild = DOMDocumentFactory::fromString( + 'FaultOneChunk', + ); + $faultTwoChild = DOMDocumentFactory::fromString( + 'FaultTwoChunk', + ); + + $input = new BindingOperationInput('CustomInputName', [new Chunk($inputChild->documentElement)]); + $output = new BindingOperationOutput('CustomOutputName', [new Chunk($outputChild->documentElement)]); + $faultOne = new BindingOperationFault('CustomFaultOne', [new Chunk($faultOneChild->documentElement)]); + + $operationOne = new BindingOperation( + 'OperationOne', + $input, + $output, + [$faultOne], + [new Chunk($operationChild->documentElement)], + ); + + $binding = new Binding( + 'MyBinding', + 'wsdl:binding', + [$operationOne], + [new Chunk($bindingChild->documentElement)], + ); + + // Service + $serviceChild = DOMDocumentFactory::fromString( + 'ServiceChunk', + ); + $chunkOne = DOMDocumentFactory::fromString( + 'ChunkOne', + ); + $chunkTwo = DOMDocumentFactory::fromString( + 'ChunkTwo', + ); + + $portOne = new Port('PortOne', 'wsdl:binding', [new Chunk($chunkOne->documentElement)]); + + $service = new Service('MyService', [$portOne], [new Chunk($serviceChild->documentElement)]); + + // Child + $child = DOMDocumentFactory::fromString( + 'SomeChunk', + ); + + $definitions = new Definitions( + 'urn:x-simplesamlphp:namespace', + 'MyDefinitions', + [$import], + [$types], + [$message], + [$portType], + [$binding], + [$service], + [new Chunk($child->documentElement)], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($definitions), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/FaultTest.php b/tests/WSSecurity/XML/wsdl/FaultTest.php new file mode 100644 index 00000000..860b5f6f --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/FaultTest.php @@ -0,0 +1,65 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($fault), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/ImportTest.php b/tests/WSSecurity/XML/wsdl/ImportTest.php new file mode 100644 index 00000000..b665002c --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/ImportTest.php @@ -0,0 +1,65 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($import), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/InputTest.php b/tests/WSSecurity/XML/wsdl/InputTest.php new file mode 100644 index 00000000..e93dd8df --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/InputTest.php @@ -0,0 +1,67 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($input), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/MessageTest.php b/tests/WSSecurity/XML/wsdl/MessageTest.php new file mode 100644 index 00000000..6db278a6 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/MessageTest.php @@ -0,0 +1,89 @@ +SomeChunk', + ); + + $attr1 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr1', 'value1'); + $attr2 = new XMLAttribute(C::NAMESPACE, 'ssp', 'attr2', 'value2'); + $part1 = new Part('CustomName', 'ssp:CustomElement', 'ssp:CustomType', [$attr1]); + $part2 = new Part('CustomOtherName', 'ssp:CustomElement', 'ssp:CustomType', [$attr2]); + + $message = new Message('SomeName', [$part1, $part2], [new Chunk($child->documentElement)]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($message), + ); + } + + + /** + * Test creating an Message object with multiple parts with the same name fails. + */ + public function testMarshallingMultiplePartsSameName(): void + { + $part1 = new Part('CustomSameName', 'ssp:CustomElement', 'ssp:CustomType'); + $part2 = new Part('CustomSameName', 'ssp:CustomElement', 'ssp:CustomType'); + + $this->expectException(SchemaViolationException::class); + new Message('SomeName', [$part1, $part2]); + } +} diff --git a/tests/WSSecurity/XML/wsdl/OutputTest.php b/tests/WSSecurity/XML/wsdl/OutputTest.php new file mode 100644 index 00000000..47fe19ef --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/OutputTest.php @@ -0,0 +1,67 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($Output), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/PartTest.php b/tests/WSSecurity/XML/wsdl/PartTest.php new file mode 100644 index 00000000..89c1a480 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/PartTest.php @@ -0,0 +1,65 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($part), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/PortTest.php b/tests/WSSecurity/XML/wsdl/PortTest.php new file mode 100644 index 00000000..5b0e0951 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/PortTest.php @@ -0,0 +1,66 @@ +SomeChunk', + ); + $port = new Port('CustomName', 'ssp:CustomBinding', [new Chunk($child->documentElement)]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($port), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/PortTypeOperationInputTest.php b/tests/WSSecurity/XML/wsdl/PortTypeOperationInputTest.php new file mode 100644 index 00000000..92efc240 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/PortTypeOperationInputTest.php @@ -0,0 +1,77 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($operation), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/PortTypeOperationOutputTest.php b/tests/WSSecurity/XML/wsdl/PortTypeOperationOutputTest.php new file mode 100644 index 00000000..460ef785 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/PortTypeOperationOutputTest.php @@ -0,0 +1,77 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($operation), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/PortTypeTest.php b/tests/WSSecurity/XML/wsdl/PortTypeTest.php new file mode 100644 index 00000000..5655aa77 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/PortTypeTest.php @@ -0,0 +1,82 @@ +assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($portType), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/ServiceTest.php b/tests/WSSecurity/XML/wsdl/ServiceTest.php new file mode 100644 index 00000000..0909d004 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/ServiceTest.php @@ -0,0 +1,77 @@ +SomeChunk', + ); + $chunkOne = DOMDocumentFactory::fromString( + 'ChunkOne', + ); + $chunkTwo = DOMDocumentFactory::fromString( + 'ChunkTwo', + ); + + $portOne = new Port('PortOne', 'ssp:CustomBinding', [new Chunk($chunkOne->documentElement)]); + $portTwo = new Port('PortTwo', 'ssp:CustomBinding', [new Chunk($chunkTwo->documentElement)]); + + $service = new Service('MyService', [$portOne, $portTwo], [new Chunk($child->documentElement)]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($service), + ); + } +} diff --git a/tests/WSSecurity/XML/wsdl/TypesTest.php b/tests/WSSecurity/XML/wsdl/TypesTest.php new file mode 100644 index 00000000..efef7b49 --- /dev/null +++ b/tests/WSSecurity/XML/wsdl/TypesTest.php @@ -0,0 +1,67 @@ +SomeChunk', + ); + + $types = new Types([new Chunk($child->documentElement)]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($types), + ); + } +} diff --git a/tests/resources/interoperability/adfs_mex.xml b/tests/resources/interoperability/adfs_mex.xml new file mode 100644 index 00000000..425e90f8 --- /dev/null +++ b/tests/resources/interoperability/adfs_mex.xml @@ -0,0 +1 @@ +http://schemas.xmlsoap.org/ws/2005/02/trust/PublicKeyhttp://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1phttp://www.w3.org/2000/09/xmldsig#rsa-sha1http://www.w3.org/2001/10/xml-exc-c14n#http://www.w3.org/2001/04/xmlenc#aes256-cbchttp://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey256http://www.w3.org/2001/04/xmlenc#aes256-cbchttp://www.w3.org/2000/09/xmldsig#hmac-sha1http://www.w3.org/2001/10/xml-exc-c14n#http://www.w3.org/2001/04/xmlenc#aes256-cbchttp://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKeyhttp://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1phttp://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1phttp://www.w3.org/2000/09/xmldsig#rsa-sha1http://www.w3.org/2001/10/xml-exc-c14n#http://www.w3.org/2001/04/xmlenc#aes256-cbchttp://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey256http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1phttp://www.w3.org/2001/04/xmlenc#aes256-cbchttp://www.w3.org/2000/09/xmldsig#hmac-sha1http://www.w3.org/2001/10/xml-exc-c14n#http://www.w3.org/2001/04/xmlenc#aes256-cbchttps://adfs.example.org/adfs/services/trust/2005/certificatemixedhttps://certauth.adfs.example.org/adfs/services/trust/2005/certificatetransporthttps://adfs.example.org/adfs/services/trust/2005/usernamemixedhttps://adfs.example.org/adfs/services/trust/2005/issuedtokenmixedasymmetricbasic256https://adfs.example.org/adfs/services/trust/2005/issuedtokenmixedsymmetricbasic256https://adfs.example.org/adfs/services/trust/13/certificatemixedhttps://adfs.example.org/adfs/services/trust/13/usernamemixedhttps://adfs.example.org/adfs/services/trust/13/issuedtokenmixedasymmetricbasic256https://adfs.example.org/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256 diff --git a/tests/resources/xml/wsdl_Binding.xml b/tests/resources/xml/wsdl_Binding.xml new file mode 100644 index 00000000..c23ad288 --- /dev/null +++ b/tests/resources/xml/wsdl_Binding.xml @@ -0,0 +1,19 @@ + + SomeChunk + + OperationChunk + + InputChunk + + + OutputChunk + + + FaultOneChunk + + + FaultTwoChunk + + + + diff --git a/tests/resources/xml/wsdl_BindingOperation.xml b/tests/resources/xml/wsdl_BindingOperation.xml new file mode 100644 index 00000000..9fe87f56 --- /dev/null +++ b/tests/resources/xml/wsdl_BindingOperation.xml @@ -0,0 +1,15 @@ + + SomeChunk + + InputChunk + + + OutputChunk + + + FaultOneChunk + + + FaultTwoChunk + + diff --git a/tests/resources/xml/wsdl_Definitions.xml b/tests/resources/xml/wsdl_Definitions.xml new file mode 100644 index 00000000..3a997ccf --- /dev/null +++ b/tests/resources/xml/wsdl_Definitions.xml @@ -0,0 +1,39 @@ + + SomeChunk + + + TypesChunk + + + MessageChunk + + + + + + + + + + + BindingChunk + + OperationChunk + + InputChunk + + + OutputChunk + + + FaultOneChunk + + + + + ServiceChunk + + ChunkOne + + + diff --git a/tests/resources/xml/wsdl_Fault.xml b/tests/resources/xml/wsdl_Fault.xml new file mode 100644 index 00000000..cbd29c39 --- /dev/null +++ b/tests/resources/xml/wsdl_Fault.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/wsdl_Import.xml b/tests/resources/xml/wsdl_Import.xml new file mode 100644 index 00000000..34c29e1c --- /dev/null +++ b/tests/resources/xml/wsdl_Import.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/wsdl_Input.xml b/tests/resources/xml/wsdl_Input.xml new file mode 100644 index 00000000..8b31f6ca --- /dev/null +++ b/tests/resources/xml/wsdl_Input.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/wsdl_Message.xml b/tests/resources/xml/wsdl_Message.xml new file mode 100644 index 00000000..388f296d --- /dev/null +++ b/tests/resources/xml/wsdl_Message.xml @@ -0,0 +1,5 @@ + + SomeChunk + + + diff --git a/tests/resources/xml/wsdl_Output.xml b/tests/resources/xml/wsdl_Output.xml new file mode 100644 index 00000000..57adaa16 --- /dev/null +++ b/tests/resources/xml/wsdl_Output.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/wsdl_Part.xml b/tests/resources/xml/wsdl_Part.xml new file mode 100644 index 00000000..2bc83e39 --- /dev/null +++ b/tests/resources/xml/wsdl_Part.xml @@ -0,0 +1 @@ + diff --git a/tests/resources/xml/wsdl_Port.xml b/tests/resources/xml/wsdl_Port.xml new file mode 100644 index 00000000..bc94f21c --- /dev/null +++ b/tests/resources/xml/wsdl_Port.xml @@ -0,0 +1,3 @@ + + SomeChunk + diff --git a/tests/resources/xml/wsdl_PortType.xml b/tests/resources/xml/wsdl_PortType.xml new file mode 100644 index 00000000..9392e7a1 --- /dev/null +++ b/tests/resources/xml/wsdl_PortType.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/resources/xml/wsdl_PortTypeOperation_Input.xml b/tests/resources/xml/wsdl_PortTypeOperation_Input.xml new file mode 100644 index 00000000..40e29eb5 --- /dev/null +++ b/tests/resources/xml/wsdl_PortTypeOperation_Input.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/resources/xml/wsdl_PortTypeOperation_Output.xml b/tests/resources/xml/wsdl_PortTypeOperation_Output.xml new file mode 100644 index 00000000..058211d3 --- /dev/null +++ b/tests/resources/xml/wsdl_PortTypeOperation_Output.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/resources/xml/wsdl_Service.xml b/tests/resources/xml/wsdl_Service.xml new file mode 100644 index 00000000..09bd0045 --- /dev/null +++ b/tests/resources/xml/wsdl_Service.xml @@ -0,0 +1,9 @@ + + SomeChunk + + ChunkOne + + + ChunkTwo + + diff --git a/tests/resources/xml/wsdl_Types.xml b/tests/resources/xml/wsdl_Types.xml new file mode 100644 index 00000000..4497ff21 --- /dev/null +++ b/tests/resources/xml/wsdl_Types.xml @@ -0,0 +1,3 @@ + + SomeChunk +