Skip to content

Commit 39e438c

Browse files
authored
Merge pull request #16 from veewee/fix-operation-message-names
Improve operation and param element generation
2 parents f2f7de2 + 21772ef commit 39e438c

12 files changed

+261
-156
lines changed

src/Encoder.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use Soap\Encoding\Encoder\Context;
77
use Soap\Encoding\Xml\Writer\OperationBuilder;
8+
use Soap\Encoding\Xml\Writer\ParameterBuilder;
89
use Soap\Encoding\Xml\Writer\SoapEnvelopeWriter;
910
use Soap\Engine\Encoder as SoapEncoder;
1011
use Soap\Engine\HttpBinding\SoapRequest;
@@ -13,8 +14,6 @@
1314
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
1415
use Soap\WsdlReader\Model\Definitions\Namespaces;
1516
use Soap\WsdlReader\Model\Definitions\SoapVersion;
16-
use function Psl\Type\mixed;
17-
use function Psl\Type\non_empty_string;
1817
use function VeeWee\Reflecta\Lens\index;
1918

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

38-
$request = [];
37+
$requestParams = [];
3938
foreach ($methodInfo->getParameters() as $index => $parameter) {
4039
$type = $parameter->getType();
4140
$context = new Context($type, $this->metadata, $this->registry, $this->namespaces, $bindingUse);
42-
/** @var mixed $argument */
43-
$argument = index($index)->get($arguments);
41+
/** @var mixed $value */
42+
$value = index($index)->get($arguments);
4443

45-
$request[] = non_empty_string()->assert(
46-
$this->registry->detectEncoderForContext($context)->iso($context)->to($argument)
47-
);
44+
$requestParams[] = (new ParameterBuilder($meta, $context, $value))(...);
4845
}
4946

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

5350
return new SoapRequest(

src/Xml/Reader/ChildrenReader.php

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/Xml/Writer/OperationBuilder.php

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@
33

44
namespace Soap\Encoding\Xml\Writer;
55

6+
use Closure;
67
use Generator;
7-
use Soap\Encoding\Xml\Reader\ChildrenReader;
88
use Soap\Engine\Metadata\Model\MethodMeta;
99
use Soap\WsdlReader\Model\Definitions\BindingStyle;
1010
use Soap\WsdlReader\Model\Definitions\Namespaces;
1111
use XMLWriter;
12-
use function Psl\Vec\map;
12+
use function VeeWee\Xml\Writer\Builder\children;
1313
use function VeeWee\Xml\Writer\Builder\namespaced_element;
14-
use function VeeWee\Xml\Writer\Builder\raw;
1514

1615
final class OperationBuilder
1716
{
1817
/**
19-
* @param list<non-empty-string> $parameters
18+
* @param list<Closure(XMLWriter): Generator<bool>> $parameters
2019
*/
2120
public function __construct(
2221
private readonly MethodMeta $meta,
@@ -29,22 +28,6 @@ public function __construct(
2928
* @return Generator<bool>
3029
*/
3130
public function __invoke(XMLWriter $writer): Generator
32-
{
33-
$operationName = $this->meta->operationName()->unwrap();
34-
$namespace = $this->meta->inputNamespace()->or($this->meta->targetNamespace())->unwrap();
35-
36-
yield from namespaced_element(
37-
$namespace,
38-
$this->namespaces->lookupNameFromNamespace($namespace)->unwrapOr('tns'),
39-
$operationName,
40-
$this->buildChildren(...)
41-
)($writer);
42-
}
43-
44-
/**
45-
* @return Generator<bool>
46-
*/
47-
private function buildChildren(XMLWriter $writer): Generator
4831
{
4932
$bindingStyle = BindingStyle::tryFrom($this->meta->bindingStyle()->unwrapOr(BindingStyle::DOCUMENT->value));
5033

@@ -59,16 +42,22 @@ private function buildChildren(XMLWriter $writer): Generator
5942
*/
6043
private function buildDocument(XMLWriter $writer): Generator
6144
{
62-
$documentParts = map($this->parameters, (new ChildrenReader())(...));
63-
64-
yield from raw(implode('', $documentParts))($writer);
45+
yield from children($this->parameters)($writer);
6546
}
6647

6748
/**
6849
* @return Generator<bool>
6950
*/
7051
private function buildRpc(XMLWriter $writer): Generator
7152
{
72-
yield from raw(implode('', $this->parameters))($writer);
53+
$operationName = $this->meta->operationName()->unwrap();
54+
$namespace = $this->meta->inputNamespace()->or($this->meta->targetNamespace())->unwrap();
55+
56+
yield from namespaced_element(
57+
$namespace,
58+
$this->namespaces->lookupNameFromNamespace($namespace)->unwrapOr('tns'),
59+
$operationName,
60+
children($this->parameters),
61+
)($writer);
7362
}
7463
}

src/Xml/Writer/ParameterBuilder.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Soap\Encoding\Xml\Writer;
5+
6+
use Generator;
7+
use Soap\Encoding\Encoder\Context;
8+
use Soap\Engine\Metadata\Model\MethodMeta;
9+
use Soap\Engine\Metadata\Model\TypeMeta;
10+
use Soap\WsdlReader\Model\Definitions\BindingStyle;
11+
use XMLWriter;
12+
use function Psl\Type\non_empty_string;
13+
use function VeeWee\Xml\Writer\Builder\raw;
14+
15+
final class ParameterBuilder
16+
{
17+
public function __construct(
18+
private readonly MethodMeta $meta,
19+
private readonly Context $context,
20+
private readonly mixed $value
21+
) {
22+
}
23+
24+
/**
25+
* @return Generator<bool>
26+
*/
27+
public function __invoke(XMLWriter $writer): Generator
28+
{
29+
$bindingStyle = BindingStyle::tryFrom($this->meta->bindingStyle()->unwrapOr(BindingStyle::DOCUMENT->value));
30+
31+
yield from match($bindingStyle) {
32+
BindingStyle::DOCUMENT => $this->buildDocument($writer),
33+
BindingStyle::RPC => $this->buildRpc($writer),
34+
};
35+
}
36+
37+
/**
38+
* @return Generator<bool>
39+
*/
40+
private function buildDocument(XMLWriter $writer): Generator
41+
{
42+
$type = $this->context->type;
43+
$context = $this->context->withType(
44+
$type
45+
->withXmlTargetNodeName($type->getName())
46+
->withMeta(
47+
static fn (TypeMeta $meta) => $meta->withIsQualified(true)
48+
)
49+
);
50+
51+
yield from raw($this->encode($context))($writer);
52+
}
53+
54+
/**
55+
* @return Generator<bool>
56+
*/
57+
private function buildRpc(XMLWriter $writer): Generator
58+
{
59+
yield from raw($this->encode($this->context))($writer);
60+
}
61+
62+
/**
63+
* @return non-empty-string
64+
*/
65+
private function encode(Context $context): string
66+
{
67+
return non_empty_string()->assert(
68+
$context->registry->detectEncoderForContext($context)->iso($context)->to($this->value)
69+
);
70+
}
71+
}

src/Xml/Writer/SoapEnvelopeWriter.php

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
use Closure;
77
use Generator;
88
use Psl\Option\Option;
9+
use Soap\Encoding\Exception\ExceptionInterface as EncodingExceptionInterface;
910
use Soap\WsdlReader\Model\Definitions\BindingUse;
1011
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
1112
use Soap\WsdlReader\Model\Definitions\SoapVersion;
1213
use Soap\Xml\Xmlns;
14+
use VeeWee\Xml\Exception\RuntimeException as XmlRuntimeException;
1315
use VeeWee\Xml\Writer\Writer;
1416
use XMLWriter;
1517
use function Psl\Vec\filter_nulls;
@@ -42,44 +44,48 @@ public function __invoke(): string
4244
SoapVersion::SOAP_12 => rtrim(Xmlns::soap12Envelope()->value(), '/'),
4345
};
4446

45-
return Writer::inMemory()
46-
->write(
47-
namespaced_element(
48-
$envelopeNamespace,
49-
'SOAP-ENV',
50-
'Envelope',
47+
try {
48+
return Writer::inMemory()
49+
->write(
5150
namespaced_element(
5251
$envelopeNamespace,
5352
'SOAP-ENV',
54-
'Body',
55-
children(
56-
filter_nulls([
57-
// In SOAP 1.2 the position of the encoding attributes is limited:
58-
// See: https://www.w3.org/TR/soap12-part1/#soapencattr
59-
// For SOAP 1.1 it can be everywhere:
60-
// See: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383495
61-
$this->encodingStyle
62-
->filter(fn (): bool => $this->bindingUse === BindingUse::ENCODED)
63-
->map(
64-
static fn (EncodingStyle $encodingStyle) => children([
65-
namespace_attribute(
66-
$encodingStyle->value,
67-
'SOAP-ENC'
68-
),
69-
namespaced_attribute(
70-
$envelopeNamespace,
71-
'SOAP-ENV',
72-
'encodingStyle',
73-
$encodingStyle->value
74-
)
75-
])
76-
)->unwrapOr(null),
77-
$this->children
78-
])
53+
'Envelope',
54+
namespaced_element(
55+
$envelopeNamespace,
56+
'SOAP-ENV',
57+
'Body',
58+
children(
59+
filter_nulls([
60+
// In SOAP 1.2 the position of the encoding attributes is limited:
61+
// See: https://www.w3.org/TR/soap12-part1/#soapencattr
62+
// For SOAP 1.1 it can be everywhere:
63+
// See: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383495
64+
$this->encodingStyle
65+
->filter(fn (): bool => $this->bindingUse === BindingUse::ENCODED)
66+
->map(
67+
static fn (EncodingStyle $encodingStyle) => children([
68+
namespace_attribute(
69+
$encodingStyle->value,
70+
'SOAP-ENC'
71+
),
72+
namespaced_attribute(
73+
$envelopeNamespace,
74+
'SOAP-ENV',
75+
'encodingStyle',
76+
$encodingStyle->value
77+
)
78+
])
79+
)->unwrapOr(null),
80+
$this->children
81+
])
82+
)
7983
)
8084
)
8185
)
82-
)
83-
->map(memory_output());
86+
->map(memory_output());
87+
} catch (XmlRuntimeException $e) {
88+
throw ($e->getPrevious() instanceof EncodingExceptionInterface) ? $e->getPrevious() : $e;
89+
}
8490
}
8591
}

tests/PhpCompatibility/Schema071Test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ protected function calculateParam(): mixed
3838
#[Test]
3939
public function it_is_compatible_with_phps_encoding()
4040
{
41-
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.');
41+
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.');
4242
}
4343

4444
protected function expectXml(): string

tests/PhpCompatibility/Schema072Test.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
namespace Soap\Encoding\Test\PhpCompatibility;
55

66
use PHPUnit\Framework\Attributes\CoversClass;
7-
use PHPUnit\Framework\Attributes\Test;
87
use Soap\Encoding\Decoder;
98
use Soap\Encoding\Driver;
109
use Soap\Encoding\Encoder;
@@ -37,12 +36,6 @@ protected function calculateParam(): mixed
3736
];
3837
}
3938

40-
#[Test]
41-
public function it_is_compatible_with_phps_encoding()
42-
{
43-
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.');
44-
}
45-
4639
protected function expectXml(): string
4740
{
4841
return <<<XML

tests/PhpCompatibility/Schema073Test.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
namespace Soap\Encoding\Test\PhpCompatibility;
55

66
use PHPUnit\Framework\Attributes\CoversClass;
7-
use PHPUnit\Framework\Attributes\Test;
87
use Soap\Encoding\Decoder;
98
use Soap\Encoding\Driver;
109
use Soap\Encoding\Encoder;
@@ -36,12 +35,6 @@ protected function calculateParam(): mixed
3635
];
3736
}
3837

39-
#[Test]
40-
public function it_is_compatible_with_phps_encoding()
41-
{
42-
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.');
43-
}
44-
4538
protected function expectXml(): string
4639
{
4740
return <<<XML

0 commit comments

Comments
 (0)