Skip to content

Commit

Permalink
Merge pull request #16 from veewee/fix-operation-message-names
Browse files Browse the repository at this point in the history
Improve operation and param element generation
  • Loading branch information
veewee authored Jul 20, 2024
2 parents f2f7de2 + 21772ef commit 39e438c
Show file tree
Hide file tree
Showing 12 changed files with 261 additions and 156 deletions.
15 changes: 6 additions & 9 deletions src/Encoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Soap\Encoding\Encoder\Context;
use Soap\Encoding\Xml\Writer\OperationBuilder;
use Soap\Encoding\Xml\Writer\ParameterBuilder;
use Soap\Encoding\Xml\Writer\SoapEnvelopeWriter;
use Soap\Engine\Encoder as SoapEncoder;
use Soap\Engine\HttpBinding\SoapRequest;
Expand All @@ -13,8 +14,6 @@
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
use Soap\WsdlReader\Model\Definitions\Namespaces;
use Soap\WsdlReader\Model\Definitions\SoapVersion;
use function Psl\Type\mixed;
use function Psl\Type\non_empty_string;
use function VeeWee\Reflecta\Lens\index;

final class Encoder implements SoapEncoder
Expand All @@ -35,19 +34,17 @@ public function encode(string $method, array $arguments): SoapRequest
$bindingUse = $meta->inputBindingUsage()->map(BindingUse::from(...))->unwrapOr(BindingUse::LITERAL);
$encodingStyle = $meta->inputEncodingStyle()->map(EncodingStyle::from(...));

$request = [];
$requestParams = [];
foreach ($methodInfo->getParameters() as $index => $parameter) {
$type = $parameter->getType();
$context = new Context($type, $this->metadata, $this->registry, $this->namespaces, $bindingUse);
/** @var mixed $argument */
$argument = index($index)->get($arguments);
/** @var mixed $value */
$value = index($index)->get($arguments);

$request[] = non_empty_string()->assert(
$this->registry->detectEncoderForContext($context)->iso($context)->to($argument)
);
$requestParams[] = (new ParameterBuilder($meta, $context, $value))(...);
}

$operation = new OperationBuilder($meta, $this->namespaces, $request);
$operation = new OperationBuilder($meta, $this->namespaces, $requestParams);
$writeEnvelope = new SoapEnvelopeWriter($soapVersion, $bindingUse, $encodingStyle, $operation(...));

return new SoapRequest(
Expand Down
28 changes: 0 additions & 28 deletions src/Xml/Reader/ChildrenReader.php

This file was deleted.

37 changes: 13 additions & 24 deletions src/Xml/Writer/OperationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@

namespace Soap\Encoding\Xml\Writer;

use Closure;
use Generator;
use Soap\Encoding\Xml\Reader\ChildrenReader;
use Soap\Engine\Metadata\Model\MethodMeta;
use Soap\WsdlReader\Model\Definitions\BindingStyle;
use Soap\WsdlReader\Model\Definitions\Namespaces;
use XMLWriter;
use function Psl\Vec\map;
use function VeeWee\Xml\Writer\Builder\children;
use function VeeWee\Xml\Writer\Builder\namespaced_element;
use function VeeWee\Xml\Writer\Builder\raw;

final class OperationBuilder
{
/**
* @param list<non-empty-string> $parameters
* @param list<Closure(XMLWriter): Generator<bool>> $parameters
*/
public function __construct(
private readonly MethodMeta $meta,
Expand All @@ -29,22 +28,6 @@ public function __construct(
* @return Generator<bool>
*/
public function __invoke(XMLWriter $writer): Generator
{
$operationName = $this->meta->operationName()->unwrap();
$namespace = $this->meta->inputNamespace()->or($this->meta->targetNamespace())->unwrap();

yield from namespaced_element(
$namespace,
$this->namespaces->lookupNameFromNamespace($namespace)->unwrapOr('tns'),
$operationName,
$this->buildChildren(...)
)($writer);
}

/**
* @return Generator<bool>
*/
private function buildChildren(XMLWriter $writer): Generator
{
$bindingStyle = BindingStyle::tryFrom($this->meta->bindingStyle()->unwrapOr(BindingStyle::DOCUMENT->value));

Expand All @@ -59,16 +42,22 @@ private function buildChildren(XMLWriter $writer): Generator
*/
private function buildDocument(XMLWriter $writer): Generator
{
$documentParts = map($this->parameters, (new ChildrenReader())(...));

yield from raw(implode('', $documentParts))($writer);
yield from children($this->parameters)($writer);
}

/**
* @return Generator<bool>
*/
private function buildRpc(XMLWriter $writer): Generator
{
yield from raw(implode('', $this->parameters))($writer);
$operationName = $this->meta->operationName()->unwrap();
$namespace = $this->meta->inputNamespace()->or($this->meta->targetNamespace())->unwrap();

yield from namespaced_element(
$namespace,
$this->namespaces->lookupNameFromNamespace($namespace)->unwrapOr('tns'),
$operationName,
children($this->parameters),
)($writer);
}
}
71 changes: 71 additions & 0 deletions src/Xml/Writer/ParameterBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);

namespace Soap\Encoding\Xml\Writer;

use Generator;
use Soap\Encoding\Encoder\Context;
use Soap\Engine\Metadata\Model\MethodMeta;
use Soap\Engine\Metadata\Model\TypeMeta;
use Soap\WsdlReader\Model\Definitions\BindingStyle;
use XMLWriter;
use function Psl\Type\non_empty_string;
use function VeeWee\Xml\Writer\Builder\raw;

final class ParameterBuilder
{
public function __construct(
private readonly MethodMeta $meta,
private readonly Context $context,
private readonly mixed $value
) {
}

/**
* @return Generator<bool>
*/
public function __invoke(XMLWriter $writer): Generator
{
$bindingStyle = BindingStyle::tryFrom($this->meta->bindingStyle()->unwrapOr(BindingStyle::DOCUMENT->value));

yield from match($bindingStyle) {
BindingStyle::DOCUMENT => $this->buildDocument($writer),
BindingStyle::RPC => $this->buildRpc($writer),
};
}

/**
* @return Generator<bool>
*/
private function buildDocument(XMLWriter $writer): Generator
{
$type = $this->context->type;
$context = $this->context->withType(
$type
->withXmlTargetNodeName($type->getName())
->withMeta(
static fn (TypeMeta $meta) => $meta->withIsQualified(true)
)
);

yield from raw($this->encode($context))($writer);
}

/**
* @return Generator<bool>
*/
private function buildRpc(XMLWriter $writer): Generator
{
yield from raw($this->encode($this->context))($writer);
}

/**
* @return non-empty-string
*/
private function encode(Context $context): string
{
return non_empty_string()->assert(
$context->registry->detectEncoderForContext($context)->iso($context)->to($this->value)
);
}
}
72 changes: 39 additions & 33 deletions src/Xml/Writer/SoapEnvelopeWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
use Closure;
use Generator;
use Psl\Option\Option;
use Soap\Encoding\Exception\ExceptionInterface as EncodingExceptionInterface;
use Soap\WsdlReader\Model\Definitions\BindingUse;
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
use Soap\WsdlReader\Model\Definitions\SoapVersion;
use Soap\Xml\Xmlns;
use VeeWee\Xml\Exception\RuntimeException as XmlRuntimeException;
use VeeWee\Xml\Writer\Writer;
use XMLWriter;
use function Psl\Vec\filter_nulls;
Expand Down Expand Up @@ -42,44 +44,48 @@ public function __invoke(): string
SoapVersion::SOAP_12 => rtrim(Xmlns::soap12Envelope()->value(), '/'),
};

return Writer::inMemory()
->write(
namespaced_element(
$envelopeNamespace,
'SOAP-ENV',
'Envelope',
try {
return Writer::inMemory()
->write(
namespaced_element(
$envelopeNamespace,
'SOAP-ENV',
'Body',
children(
filter_nulls([
// In SOAP 1.2 the position of the encoding attributes is limited:
// See: https://www.w3.org/TR/soap12-part1/#soapencattr
// For SOAP 1.1 it can be everywhere:
// See: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383495
$this->encodingStyle
->filter(fn (): bool => $this->bindingUse === BindingUse::ENCODED)
->map(
static fn (EncodingStyle $encodingStyle) => children([
namespace_attribute(
$encodingStyle->value,
'SOAP-ENC'
),
namespaced_attribute(
$envelopeNamespace,
'SOAP-ENV',
'encodingStyle',
$encodingStyle->value
)
])
)->unwrapOr(null),
$this->children
])
'Envelope',
namespaced_element(
$envelopeNamespace,
'SOAP-ENV',
'Body',
children(
filter_nulls([
// In SOAP 1.2 the position of the encoding attributes is limited:
// See: https://www.w3.org/TR/soap12-part1/#soapencattr
// For SOAP 1.1 it can be everywhere:
// See: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383495
$this->encodingStyle
->filter(fn (): bool => $this->bindingUse === BindingUse::ENCODED)
->map(
static fn (EncodingStyle $encodingStyle) => children([
namespace_attribute(
$encodingStyle->value,
'SOAP-ENC'
),
namespaced_attribute(
$envelopeNamespace,
'SOAP-ENV',
'encodingStyle',
$encodingStyle->value
)
])
)->unwrapOr(null),
$this->children
])
)
)
)
)
)
->map(memory_output());
->map(memory_output());
} catch (XmlRuntimeException $e) {
throw ($e->getPrevious() instanceof EncodingExceptionInterface) ? $e->getPrevious() : $e;
}
}
}
2 changes: 1 addition & 1 deletion tests/PhpCompatibility/Schema071Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected function calculateParam(): mixed
#[Test]
public function it_is_compatible_with_phps_encoding()
{
static::markTestSkipped('Literal document seems about right - yet php soap uses the type instead of the part name. Not sure what to do here yet.');
static::markTestSkipped('Literal document seems about right - it seems to be taking the param name instead of the complextype name though. Not sure what to do here yet.');
}

protected function expectXml(): string
Expand Down
7 changes: 0 additions & 7 deletions tests/PhpCompatibility/Schema072Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
namespace Soap\Encoding\Test\PhpCompatibility;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Soap\Encoding\Decoder;
use Soap\Encoding\Driver;
use Soap\Encoding\Encoder;
Expand Down Expand Up @@ -37,12 +36,6 @@ protected function calculateParam(): mixed
];
}

#[Test]
public function it_is_compatible_with_phps_encoding()
{
static::markTestSkipped('Literal document seems about right - yet php soap uses the type instead of the part name. Not sure what to do here yet.');
}

protected function expectXml(): string
{
return <<<XML
Expand Down
7 changes: 0 additions & 7 deletions tests/PhpCompatibility/Schema073Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
namespace Soap\Encoding\Test\PhpCompatibility;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Soap\Encoding\Decoder;
use Soap\Encoding\Driver;
use Soap\Encoding\Encoder;
Expand Down Expand Up @@ -36,12 +35,6 @@ protected function calculateParam(): mixed
];
}

#[Test]
public function it_is_compatible_with_phps_encoding()
{
static::markTestSkipped('Literal document seems about right - yet php soap uses the type instead of the part name. Not sure what to do here yet.');
}

protected function expectXml(): string
{
return <<<XML
Expand Down
Loading

0 comments on commit 39e438c

Please sign in to comment.