Skip to content

Commit a4adb09

Browse files
author
Michal Mičko
committed
added WSDL document-wrapped support and more...
1 parent f2a8a7e commit a4adb09

File tree

14 files changed

+330
-49
lines changed

14 files changed

+330
-49
lines changed

src/BeSimple/SoapBundle/DependencyInjection/BeSimpleSoapExtension.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2323
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2424

25+
if (!defined('SOAP_LITERAL_WRAPPED')) {
26+
define('SOAP_LITERAL_WRAPPED', 3);
27+
}
2528
/**
2629
* BeSimpleSoapExtension.
2730
*
@@ -35,6 +38,15 @@ class BeSimpleSoapExtension extends Extension
3538
'rpc-literal' => 'rpcliteral',
3639
'document-wrapped' => 'documentwrapped',
3740
);
41+
private $styleMap = [
42+
'rpc' => \SOAP_RPC,
43+
'document' => \SOAP_DOCUMENT,
44+
];
45+
private $useMap = [
46+
'encoded' => \SOAP_ENCODED,
47+
'literal' => \SOAP_LITERAL,
48+
'wrapped' => \SOAP_LITERAL_WRAPPED,
49+
];
3850

3951
public function load(array $configs, ContainerBuilder $container)
4052
{
@@ -152,7 +164,10 @@ private function createClient($client, ContainerBuilder $container)
152164

153165
private function createWebServiceContext(array $config, ContainerBuilder $container)
154166
{
155-
$bindingSuffix = $this->bindingConfigToServiceSuffixMap[$config['binding']];
167+
$bindingSuffix = $this->bindingConfigToServiceSuffixMap[$config['binding']];
168+
list($style, $use) = explode('-', $config['binding']);
169+
$config['style'] = $this->styleMap[$style];
170+
$config['use'] = $this->useMap[$use];
156171
unset($config['binding']);
157172

158173
$contextId = 'besimple.soap.context.'.$config['name'];

src/BeSimple/SoapBundle/DependencyInjection/Configuration.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,15 @@ private function addServicesSection(ArrayNodeDefinition $rootNode)
135135
->scalarNode('binding')
136136
->defaultValue('document-wrapped')
137137
->validate()
138-
->ifNotInArray(array('rpc-literal', 'document-wrapped'))
139-
->thenInvalid("Service binding style has to be either 'rpc-literal' or 'document-wrapped'")
138+
->ifNotInArray([ 'rpc-literal', 'document-wrapped' /*, 'rpc-encoded', , 'document-literal'*/ ])
139+
->thenInvalid("Service binding style has to be either 'rpc-literal' or 'document-wrapped'!"/* or 'rpc-encoded' or 'document-literal' */)
140+
->end()
141+
->end()
142+
->scalarNode('version')
143+
->defaultValue(2)
144+
->validate()
145+
->ifNotInArray([ 1, 2 ])
146+
->thenInvalid("Service protocol version has to be either 1 or 2")
140147
->end()
141148
->end()
142149
->scalarNode('cache_type')
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace BeSimple\SoapBundle\ServiceBinding;
4+
5+
use BeSimple\SoapBundle\ServiceDefinition\Method;
6+
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
7+
/**
8+
* Description of DocumentLiteralWrappedRequestHeaderBinder
9+
*
10+
* @author Michal Mičko <michal.micko@mediaaction.cz>
11+
*/
12+
class DocumentLiteralWrappedRequestHeaderMessageBinder extends DocumentLiteralWrappedRequestMessageBinder
13+
{
14+
private $header;
15+
16+
public function setHeader($header)
17+
{
18+
$this->header = $header;
19+
}
20+
21+
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
22+
{
23+
$this->typeRepository = $typeRepository;
24+
$headerDefinition = $messageDefinition->getHeaders()->get($this->header);
25+
26+
return $this->processType($headerDefinition->getType(), $message);
27+
}
28+
}

src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedRequestMessageBinder.php

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,108 @@
1111
namespace BeSimple\SoapBundle\ServiceBinding;
1212

1313
use BeSimple\SoapBundle\ServiceDefinition\Method;
14+
use BeSimple\SoapCommon\Definition\Type\ArrayOfType;
15+
use BeSimple\SoapCommon\Definition\Type\ComplexType;
16+
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
17+
use BeSimple\SoapCommon\Util\MessageBinder;
1418

1519
/**
1620
* @author Christian Kerl <christian-kerl@web.de>
1721
*/
1822
class DocumentLiteralWrappedRequestMessageBinder implements MessageBinderInterface
1923
{
20-
public function processMessage(Method $messageDefinition, $message)
24+
protected $typeRepository;
25+
26+
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
2127
{
28+
$this->typeRepository = $typeRepository;
29+
2230
if(count($message) > 1) {
2331
throw new \InvalidArgumentException();
2432
}
2533

2634
$result = array();
2735
$message = $message[0];
2836

29-
foreach($messageDefinition->getArguments() as $argument) {
30-
$result[$argument->getName()] = $message->{$argument->getName()};
37+
foreach($messageDefinition->getInput()->all() as $argument) {
38+
$result[$argument->getName()] = $this->processType($argument->getType(), $message->{$argument->getName()});
3139
}
3240

3341
return $result;
3442
}
43+
44+
protected function processType($phpType, $message)
45+
{
46+
$isArray = false;
47+
48+
$type = $this->typeRepository->getType($phpType);
49+
if ($type instanceof ArrayOfType) {
50+
$isArray = true;
51+
$array = array();
52+
53+
$type = $this->typeRepository->getType($type->get('item')->getType());
54+
}
55+
56+
// @TODO Fix array reference
57+
if ($type instanceof ComplexType) {
58+
$phpType = $type->getPhpType();
59+
60+
if ($isArray) {
61+
if (isset($message->item)) {
62+
foreach ($message->item as $complexType) {
63+
$array[] = $this->checkComplexType($phpType, $complexType);
64+
}
65+
66+
// See https://github.com/BeSimple/BeSimpleSoapBundle/issues/29
67+
if (in_array('BeSimple\SoapCommon\Type\AbstractKeyValue', class_parents($phpType))) {
68+
$assocArray = array();
69+
foreach ($array as $keyValue) {
70+
$assocArray[$keyValue->getKey()] = $keyValue->getValue();
71+
}
72+
73+
$array = $assocArray;
74+
}
75+
}
76+
77+
$message = $array;
78+
} else {
79+
$message = $this->checkComplexType($phpType, $message);
80+
}
81+
} elseif ($isArray) {
82+
if (isset($message->item)) {
83+
$message = $message->item;
84+
} else {
85+
$message = $array;
86+
}
87+
}
88+
89+
return $message;
90+
}
91+
92+
protected function checkComplexType($phpType, $message)
93+
{
94+
$hash = spl_object_hash($message);
95+
if (isset($this->messageRefs[$hash])) {
96+
return $this->messageRefs[$hash];
97+
}
98+
99+
$this->messageRefs[$hash] = $message;
100+
101+
$messageBinder = new MessageBinder($message);
102+
foreach ($this->typeRepository->getType($phpType)->all() as $type) {
103+
$property = $type->getName();
104+
$value = $messageBinder->readProperty($property);
105+
106+
if (null !== $value) {
107+
$value = $this->processType($type->getType(), $value);
108+
109+
$messageBinder->writeProperty($property, $value);
110+
} elseif (!$type->isNillable()) {
111+
// @TODO use xmlType instead of phpType
112+
throw new \SoapFault('SOAP_ERROR_COMPLEX_TYPE', sprintf('"%s:%s" cannot be null.', ucfirst($phpType), $type->getName()));
113+
}
114+
}
115+
116+
return $message;
117+
}
35118
}

src/BeSimple/SoapBundle/ServiceBinding/DocumentLiteralWrappedResponseMessageBinder.php

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,100 @@
1111
namespace BeSimple\SoapBundle\ServiceBinding;
1212

1313
use BeSimple\SoapBundle\ServiceDefinition\Method;
14+
use BeSimple\SoapCommon\Definition\Type\ArrayOfType;
15+
use BeSimple\SoapCommon\Definition\Type\ComplexType;
16+
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
17+
use BeSimple\SoapCommon\Util\MessageBinder;
1418

1519
/**
1620
* @author Christian Kerl <christian-kerl@web.de>
1721
*/
1822
class DocumentLiteralWrappedResponseMessageBinder implements MessageBinderInterface
1923
{
20-
public function processMessage(Method $messageDefinition, $message)
24+
public function processMessage(Method $messageDefinition, $message, TypeRepository $typeRepository)
2125
{
26+
$this->typeRepository = $typeRepository;
27+
2228
$result = new \stdClass();
23-
$result->{$messageDefinition->getName().'Result'} = $message;
29+
//$result->{$messageDefinition->getName().'Result'} = $message;
30+
foreach ($messageDefinition->getOutput()->all() as $name => $part) {
31+
//$result->{$name} = $message;
32+
$result->{$name} = $this->processType($part->getType(), $message);
33+
break; // only one iteration
34+
}
2435

2536
return $result;
2637
}
38+
39+
private function processType($phpType, $message)
40+
{
41+
$isArray = false;
42+
43+
$type = $this->typeRepository->getType($phpType);
44+
if ($type instanceof ArrayOfType) {
45+
$isArray = true;
46+
47+
$type = $this->typeRepository->getType($type->get('item')->getType());
48+
}
49+
50+
if ($type instanceof ComplexType) {
51+
$phpType = $type->getPhpType();
52+
53+
if ($isArray) {
54+
$array = array();
55+
56+
// See https://github.com/BeSimple/BeSimpleSoapBundle/issues/29
57+
if (is_array($message) && in_array('BeSimple\SoapCommon\Type\AbstractKeyValue', class_parents($phpType))) {
58+
$keyValue = array();
59+
foreach ($message as $key => $value) {
60+
$keyValue[] = new $phpType($key, $value);
61+
}
62+
63+
$message = $keyValue;
64+
}
65+
66+
foreach ($message as $complexType) {
67+
$array[] = $this->checkComplexType($phpType, $complexType);
68+
}
69+
70+
$message = $array;
71+
} else {
72+
$message = $this->checkComplexType($phpType, $message);
73+
}
74+
}
75+
76+
return $message;
77+
}
78+
79+
private function checkComplexType($phpType, $message)
80+
{
81+
$hash = spl_object_hash($message);
82+
if (isset($this->messageRefs[$hash])) {
83+
return $this->messageRefs[$hash];
84+
}
85+
86+
$this->messageRefs[$hash] = $message;
87+
88+
if (!$message instanceof $phpType) {
89+
throw new \InvalidArgumentException(sprintf('The instance class must be "%s", "%s" given.', $phpType, get_class($message)));
90+
}
91+
92+
$messageBinder = new MessageBinder($message);
93+
foreach ($this->typeRepository->getType($phpType)->all() as $type) {
94+
$property = $type->getName();
95+
$value = $messageBinder->readProperty($property);
96+
97+
if (null !== $value) {
98+
$value = $this->processType($type->getType(), $value);
99+
100+
$messageBinder->writeProperty($property, $value);
101+
}
102+
103+
if (!$type->isNillable() && null === $value) {
104+
throw new \InvalidArgumentException(sprintf('"%s::%s" cannot be null.', $phpType, $type->getName()));
105+
}
106+
}
107+
108+
return $message;
109+
}
27110
}

src/BeSimple/SoapBundle/ServiceBinding/RpcLiteralResponseMessageBinder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public function processMessage(Method $messageDefinition, $message, TypeReposito
3232
{
3333
$this->typeRepository = $typeRepository;
3434

35-
return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message);
35+
//return $this->processType($messageDefinition->getOutput()->get('return')->getType(), $message);
36+
return $this->processType(current($messageDefinition->getOutput()->all())->getType(), $message);
3637
}
3738

3839
private function processType($phpType, $message)

src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Param.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class Param extends Configuration implements TypedElementInterface
1818
private $value;
1919
private $phpType;
2020
private $xmlType;
21+
private $isNillable = false;
2122

2223
public function getValue()
2324
{
@@ -34,6 +35,11 @@ public function getXmlType()
3435
return $this->xmlType;
3536
}
3637

38+
public function isNillable()
39+
{
40+
return $this->isNillable;
41+
}
42+
3743
public function setValue($value)
3844
{
3945
$this->value = $value;
@@ -49,6 +55,11 @@ public function setXmlType($xmlType)
4955
$this->xmlType = $xmlType;
5056
}
5157

58+
public function setNillable($isNillable)
59+
{
60+
$this->isNillable = (bool) $isNillable;
61+
}
62+
5263
public function getAliasName()
5364
{
5465
return 'param';

src/BeSimple/SoapBundle/ServiceDefinition/Annotation/Result.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515
*/
1616
class Result extends Configuration implements TypedElementInterface
1717
{
18+
private $value = 'return';
1819
private $phpType;
1920
private $xmlType;
2021

22+
public function getValue()
23+
{
24+
return $this->value;
25+
}
26+
2127
public function getPhpType()
2228
{
2329
return $this->phpType;
@@ -28,6 +34,11 @@ public function getXmlType()
2834
return $this->xmlType;
2935
}
3036

37+
public function setValue($value)
38+
{
39+
$this->value = $value;
40+
}
41+
3142
public function setPhpType($phpType)
3243
{
3344
$this->phpType = $phpType;

0 commit comments

Comments
 (0)