Skip to content

Commit 7c84a2a

Browse files
authored
Merge pull request #43 from veewee/http-binding
Parse HTTP binding information
2 parents ffb4e82 + 8340fda commit 7c84a2a

15 files changed

+229
-28
lines changed

src/Formatter/MetaTableFormatter.php

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace Soap\WsdlReader\Formatter;
55

6+
use Psl\Option\Option;
67
use ReflectionClass;
78
use ReflectionProperty;
89
use Symfony\Component\Console\Helper\Table;
@@ -58,6 +59,7 @@ private function tryStringifyValue(mixed $value): ?string
5859
is_array($value) => json_encode($value, JSON_PRETTY_PRINT),
5960
is_bool($value) => $value ? 'true' : 'false',
6061
is_scalar($value) => (string)$value,
62+
$value instanceof Option => $value->map($this->tryStringifyValue(...))->unwrapOr(null),
6163
default => null,
6264
};
6365
} catch (Throwable) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;
5+
6+
use Soap\Engine\Metadata\Model\Method;
7+
use Soap\WsdlReader\Model\Definitions\Binding;
8+
use function Psl\Fun\pipe;
9+
10+
final class BindingConfigurator
11+
{
12+
public function __invoke(Method $method, Binding $binding): Method
13+
{
14+
return pipe(
15+
static fn (Method $method) => (new HttpBindingConfigurator())($method, $binding),
16+
static fn (Method $method) => (new SoapBindingConfigurator())($method, $binding),
17+
)($method);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;
5+
6+
use Soap\Engine\Metadata\Model\Method;
7+
use Soap\Engine\Metadata\Model\MethodMeta;
8+
use Soap\WsdlReader\Model\Definitions\Binding;
9+
use Soap\WsdlReader\Model\Definitions\Implementation\Binding\HttpBinding;
10+
11+
final class HttpBindingConfigurator
12+
{
13+
public function __invoke(Method $method, Binding $binding): Method
14+
{
15+
$implementation = $binding->implementation;
16+
if (!$implementation instanceof HttpBinding) {
17+
return $method;
18+
}
19+
20+
return $method->withMeta(
21+
static fn (MethodMeta $meta): MethodMeta => $meta
22+
->withTransport($implementation->transport->value)
23+
);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<?php
22
declare(strict_types=1);
33

4-
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;
4+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding;
55

66
use Soap\Engine\Metadata\Model\Method;
77
use Soap\Engine\Metadata\Model\MethodMeta;
88
use Soap\WsdlReader\Model\Definitions\Binding;
99
use Soap\WsdlReader\Model\Definitions\Implementation\Binding\SoapBinding;
1010

11-
final class BindingConfigurator
11+
final class SoapBindingConfigurator
1212
{
1313
public function __invoke(Method $method, Binding $binding): Method
1414
{
@@ -19,7 +19,7 @@ public function __invoke(Method $method, Binding $binding): Method
1919

2020
return $method->withMeta(
2121
static fn (MethodMeta $meta): MethodMeta => $meta
22-
->withTransport($implementation->transport->value)
22+
->withTransport($implementation->transport->value)
2323
);
2424
}
2525
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;
5+
6+
use Soap\Engine\Metadata\Model\Method;
7+
use Soap\Engine\Metadata\Model\MethodMeta;
8+
use Soap\WsdlReader\Model\Definitions\BindingOperation;
9+
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\HttpOperation;
10+
11+
final class HttpBindingOperationConfigurator
12+
{
13+
public function __invoke(Method $method, BindingOperation $operation): Method
14+
{
15+
$implementation = $operation->implementation;
16+
if (!$implementation instanceof HttpOperation) {
17+
return $method;
18+
}
19+
20+
return $method->withMeta(
21+
static fn (MethodMeta $meta): MethodMeta => $meta
22+
->withOperationName($operation->name)
23+
);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;
4+
5+
use Soap\Engine\Metadata\Model\Method;
6+
use Soap\WsdlReader\Model\Definitions\BindingOperation;
7+
use function Psl\Fun\pipe;
8+
9+
final readonly class OperationConfigurator
10+
{
11+
public function __invoke(Method $method, BindingOperation $operation): Method
12+
{
13+
return pipe(
14+
static fn (Method $method) => (new HttpBindingOperationConfigurator())($method, $operation),
15+
static fn (Method $method) => (new SoapBindingOperationConfigurator())($method, $operation),
16+
)($method);
17+
}
18+
}

src/Metadata/Converter/Methods/Configurator/BindingOperationConfigurator.php renamed to src/Metadata/Converter/Methods/Configurator/Operation/SoapBindingOperationConfigurator.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
declare(strict_types=1);
33

4-
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;
4+
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation;
55

66
use Soap\Engine\Metadata\Model\Method;
77
use Soap\Engine\Metadata\Model\MethodMeta;
@@ -10,7 +10,7 @@
1010
use Soap\WsdlReader\Model\Definitions\Implementation\Message\SoapMessage;
1111
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\SoapOperation;
1212

13-
final class BindingOperationConfigurator
13+
final class SoapBindingOperationConfigurator
1414
{
1515
public function __invoke(Method $method, BindingOperation $operation): Method
1616
{

src/Metadata/Converter/Methods/Configurator/Wsdl1Configurator.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ final class Wsdl1Configurator
1111
{
1212
public function __invoke(Method $method, Wsdl1 $wsdl): Method
1313
{
14+
$targetNamespace = $wsdl->targetNamespace?->value();
15+
1416
return $method->withMeta(
1517
static fn (MethodMeta $meta): MethodMeta => $meta
16-
->withTargetNamespace($wsdl->targetNamespace?->value())
18+
->withTargetNamespace($targetNamespace)
19+
->withInputNamespace($targetNamespace)
20+
->withOutputNamespace($targetNamespace)
1721
);
1822
}
1923
}

src/Metadata/Converter/Methods/Configurator/Wsdl1SelectedServiceConfigurator.php

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Soap\WsdlReader\Metadata\Converter\Methods\Configurator;
55

66
use Soap\Engine\Metadata\Model\Method;
7+
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Binding\BindingConfigurator;
78
use Soap\WsdlReader\Model\Service\Wsdl1SelectedService;
89
use function Psl\Fun\pipe;
910

src/Metadata/Converter/Wsdl1ToMethodsConverter.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use Soap\Engine\Metadata\Model\Parameter;
1010
use Soap\Engine\Metadata\Model\XsdType;
1111
use Soap\WsdlReader\Locator\Wsdl1SelectedServiceLocator;
12-
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\BindingOperationConfigurator;
12+
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Operation\OperationConfigurator;
1313
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\PortTypeOperationConfigurator;
1414
use Soap\WsdlReader\Metadata\Converter\Methods\Configurator\Wsdl1SelectedServiceConfigurator;
1515
use Soap\WsdlReader\Metadata\Converter\Methods\Converter\MessageToMetadataTypesConverter;
@@ -66,7 +66,7 @@ private function parseMethod(Wsdl1SelectedService $service, BindingOperation $bi
6666

6767
$configure = pipe(
6868
static fn (Method $method) => (new Wsdl1SelectedServiceConfigurator())($method, $service),
69-
static fn (Method $method) => (new BindingOperationConfigurator())($method, $bindingOperation),
69+
static fn (Method $method) => (new OperationConfigurator())($method, $bindingOperation),
7070
static fn (Method $method) => (new PortTypeOperationConfigurator())($method, $portTypeOperation),
7171
);
7272

src/Model/Definitions/AddressBindingType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ enum AddressBindingType : string
99
case SOAP_12 = 'http://schemas.xmlsoap.org/wsdl/soap12/';
1010
case RPC = 'http://www.w3.org/2003/05/soap-rpc"';
1111
case HTTP_11 = 'http://schemas.xmlsoap.org/wsdl/http/';
12-
case HTTP_12 = 'http://www.w3.org/2003/05/soap/bindings/HTTP/"';
12+
case HTTP_12 = 'http://www.w3.org/2003/05/soap/bindings/HTTP/';
1313

1414
public function isSoap(): bool
1515
{

src/Model/Definitions/Implementation/Binding/HttpBinding.php

+3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
namespace Soap\WsdlReader\Model\Definitions\Implementation\Binding;
55

6+
use Soap\WsdlReader\Model\Definitions\TransportType;
7+
68
final class HttpBinding implements BindingImplementation
79
{
810
public function __construct(
911
public readonly string $verb,
12+
public readonly TransportType $transport,
1013
) {
1114
}
1215
}

src/Model/Definitions/Implementation/Message/HttpMessage.php

+5-16
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,9 @@
55

66
final class HttpMessage implements MessageImplementation
77
{
8-
// TODO ...
9-
/*
10-
* <wsdl:input>
11-
<mime:content type="application/x-www-form-urlencoded"/>
12-
</wsdl:input>
13-
<wsdl:output>
14-
<mime:mimeXml part="getServiceTicketResponsePart"/>
15-
</wsdl:output>
16-
17-
<wsdl:input>
18-
<http:urlEncoded/>
19-
</wsdl:input>
20-
<wsdl:output>
21-
<mime:content part="ticket" type="text/plain"/>
22-
</wsdl:output>
23-
*/
8+
public function __construct(
9+
public readonly string $contentType,
10+
public readonly ?string $part,
11+
) {
12+
}
2413
}

src/Parser/Strategy/HttpStrategy.php

+34-3
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,57 @@
1010
use Soap\WsdlReader\Model\Definitions\Implementation\Message\MessageImplementation;
1111
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\HttpOperation;
1212
use Soap\WsdlReader\Model\Definitions\Implementation\Operation\OperationImplementation;
13+
use Soap\WsdlReader\Model\Definitions\TransportType;
1314
use VeeWee\Xml\Dom\Document;
15+
use function VeeWee\Xml\Dom\Locator\Element\children;
1416

1517
final class HttpStrategy implements StrategyInterface
1618
{
19+
private const HTTP_NAMESPACE = 'http://schemas.xmlsoap.org/wsdl/http/';
20+
private const MIME_NAMESPACE = 'http://schemas.xmlsoap.org/wsdl/mime/';
21+
1722
public function parseBindingImplementation(Document $wsdl, DOMElement $binding): BindingImplementation
1823
{
1924
return new HttpBinding(
20-
verb: $binding->getAttribute('verb')
25+
verb: $binding->getAttribute('verb'),
26+
transport: TransportType::tryFrom((string) $binding->namespaceURI) ?? TransportType::HTTP,
2127
);
2228
}
2329

2430
public function parseOperationImplementation(Document $wsdl, DOMElement $operation): OperationImplementation
2531
{
2632
return new HttpOperation(
27-
location: $operation->getAttribute('location')
33+
location: $operation->getAttribute('location'),
2834
);
2935
}
3036

3137
public function parseMessageImplementation(Document $wsdl, DOMElement $message): MessageImplementation
3238
{
33-
return new HttpMessage();
39+
$info = children($message)->first();
40+
$fallbackImplementation = new HttpMessage(
41+
contentType: 'application/xml',
42+
part: null
43+
);
44+
45+
if (!$info) {
46+
return $fallbackImplementation;
47+
}
48+
49+
return match ($info->namespaceURI) {
50+
self::HTTP_NAMESPACE => new HttpMessage(
51+
contentType: 'text/plain',
52+
part: null
53+
),
54+
self::MIME_NAMESPACE => new HttpMessage(
55+
contentType: match($info->localName) {
56+
'content' => $info->hasAttribute('type') ? $info->getAttribute('type'): 'application/xml',
57+
'mimeXml' => 'application/xml',
58+
'multipartRelated' => 'Multipart/Related',
59+
default => 'application/xml'
60+
},
61+
part: $info->hasAttribute('part') ? $info->getAttribute('part') : null,
62+
),
63+
default => $fallbackImplementation,
64+
};
3465
}
3566
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Soap\WsdlReader\Test\Unit\Paser\Strategy;
4+
5+
use PHPUnit\Framework\Attributes\DataProvider;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use PHPUnit\Framework\TestCase;
8+
use Soap\WsdlReader\Model\Definitions\Implementation\Message\HttpMessage;
9+
use Soap\WsdlReader\Parser\Strategy\HttpStrategy;
10+
use VeeWee\Xml\Dom\Document;
11+
12+
final class HttpStrategyTest extends TestCase
13+
{
14+
15+
#[Test]
16+
#[DataProvider('provideMessages')]
17+
public function it_can_parse_message_implementations(string $xml, HttpMessage $expected): void
18+
{
19+
$doc = Document::fromXmlString($xml);
20+
$element = $doc->locateDocumentElement();
21+
22+
$strategy = new HttpStrategy();
23+
$actual = $strategy->parseMessageImplementation($doc, $element);
24+
25+
static::assertEquals($expected, $actual);
26+
}
27+
28+
public static function provideMessages(): iterable
29+
{
30+
yield 'no-info' => [
31+
<<<EOXML
32+
<wsdl:input
33+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" />
34+
EOXML,
35+
new HttpMessage(
36+
contentType: 'application/xml',
37+
part: null
38+
)
39+
];
40+
41+
yield 'mime-content-info' => [
42+
<<<EOXML
43+
<wsdl:input
44+
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
45+
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
46+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
47+
<mime:content part="CancelBookingRequest" type="application/soap+xml"/>
48+
</wsdl:input>
49+
EOXML,
50+
new HttpMessage(
51+
contentType: 'application/soap+xml',
52+
part: 'CancelBookingRequest'
53+
)
54+
];
55+
56+
yield 'mime-xml' => [
57+
<<<EOXML
58+
<wsdl:input
59+
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
60+
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
61+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
62+
<mime:mimeXml part="getServiceTicketResponsePart"/>
63+
</wsdl:input>
64+
EOXML,
65+
new HttpMessage(
66+
contentType: 'application/xml',
67+
part: 'getServiceTicketResponsePart'
68+
)
69+
];
70+
yield 'http-url-encoded' => [
71+
<<<EOXML
72+
<wsdl:input
73+
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
74+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
75+
<http:urlEncoded/>
76+
</wsdl:input>
77+
EOXML,
78+
new HttpMessage(
79+
contentType: 'text/plain',
80+
part: null
81+
)
82+
];
83+
}
84+
}

0 commit comments

Comments
 (0)