forked from php-soap/encoding
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathResponseEncoder.php
More file actions
111 lines (95 loc) · 3.53 KB
/
ResponseEncoder.php
File metadata and controls
111 lines (95 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php declare(strict_types=1);
namespace Soap\Encoding\Encoder\Method;
use Closure;
use Generator;
use Soap\Encoding\Xml\Reader\OperationReader;
use Soap\Encoding\Xml\Writer\OperationBuilder;
use Soap\Encoding\Xml\Writer\ParameterBuilder;
use Soap\Encoding\Xml\Writer\SoapEnvelopeWriter;
use Soap\WsdlReader\Model\Definitions\BindingUse;
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
use Soap\WsdlReader\Model\Definitions\SoapVersion;
use VeeWee\Reflecta\Iso\Iso;
use XMLWriter;
use function Psl\invariant;
use function Psl\Vec\map;
/**
* @template-implements SoapMethodEncoder<mixed, string>
*/
final class ResponseEncoder implements SoapMethodEncoder
{
/**
* @return Iso<mixed, string>
*/
public function iso(MethodContext $context): Iso
{
$meta = $context->method->getMeta();
$context = $context->withBindingUse(
$meta->outputBindingUsage()
->map(static fn ($value) => BindingUse::from($value))
->unwrapOr(BindingUse::LITERAL)
);
/** @var Iso<list<mixed>, string> */
return new Iso(
/**
* @param list<mixed> $arguments
*/
fn (array $arguments): string => $this->encode($context, $arguments),
/**
* @return list<mixed>
*/
fn (string $xml): array => $this->decode($context, $xml),
);
}
/**
* @param list<mixed> $arguments
*/
private function encode(MethodContext $context, array $arguments): string
{
$method = $context->method;
$meta = $method->getMeta();
if ($meta->isOneWay()->unwrapOr(false)) {
return '';
}
$soapVersion = $meta->soapVersion()
->map(static fn ($value) => SoapVersion::from($value))
->unwrapOr(SoapVersion::SOAP_12);
$encodingStyle = $meta->outputEncodingStyle()
->map(static fn ($value) => EncodingStyle::from($value));
$returnType = $method->getReturnType();
$typeContext = $context->createXmlEncoderContextForType($returnType);
$responseParams = map(
$arguments,
/**
* @return Closure(XMLWriter): Generator<bool>
*/
static fn (mixed $argument): Closure => (new ParameterBuilder($meta, $typeContext, $argument))(...),
);
$operation = new OperationBuilder($meta, $context->namespaces, $responseParams);
$writeEnvelope = new SoapEnvelopeWriter($soapVersion, $context->bindingUse, $encodingStyle, $operation(...));
return $writeEnvelope() . PHP_EOL;
}
/**
* @return list<mixed>
*/
private function decode(MethodContext $context, string $xml): array
{
$method = $context->method;
$meta = $method->getMeta();
if ($meta->isOneWay()->unwrapOr(false)) {
return [];
}
$returnType = $method->getReturnType();
$typeContext = $context->createXmlEncoderContextForType($returnType);
$decoder = $context->registry->detectEncoderForContext($typeContext);
$iso = $decoder->iso($typeContext);
// The SoapResponse only contains the payload of the response (with no headers).
// It can be parsed directly as XML.
invariant($xml !== '', 'Expected a non-empty response payload. Received an empty HTTP response');
$parts = (new OperationReader($meta))($xml, $context->registry->decoderLibXmlOptions())->elements();
return map(
$parts,
$iso->from(...)
);
}
}