XMLProvider::bindingElement()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 8
cts 8
cp 1
rs 9.7666
c 0
b 0
f 0
cc 2
nc 2
nop 6
crap 2
1
<?php
2
/**
3
 * Copyright (C) 2013-2020
4
 * Piotr Olaszewski <[email protected]>
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24
namespace WSDL\XML;
25
26
use DOMDocument;
27
use DOMElement;
28
use Ouzo\Utilities\Arrays;
29
use WSDL\Builder\Parameter;
30
use WSDL\Builder\WSDLBuilder;
31
use WSDL\Parser\Node;
32
use WSDL\XML\XMLSoapVersion\XMLSoapVersion;
33
use WSDL\XML\XMLStyle\XMLStyle;
34
use WSDL\XML\XMLStyle\XMLStyleFactory;
35
use WSDL\XML\XMLUse\XMLUse;
36
use WSDL\XML\XMLUse\XMLUseFactory;
37
38
/**
39
 * XMLProvider
40
 *
41
 * @author Piotr Olaszewski <[email protected]>
42
 */
43
class XMLProvider
44
{
45
    /**
46
     * @var WSDLBuilder
47
     */
48
    private $builder;
49
    /**
50
     * @var XMLStyle
51
     */
52
    private $XMLStyle;
53
    /**
54
     * @var XMLUse
55
     */
56
    private $XMLUse;
57
    /**
58
     * @var string
59
     */
60
    private $XMLSoapVersion;
61
    /**
62
     * @var DOMDocument
63
     */
64
    private $DOMDocument;
65
    /**
66
     * @var string
67
     */
68
    private $xml;
69
    /**
70
     * @var DOMElement
71
     */
72
    private $definitionsRootNode;
73
74
    public function __construct(WSDLBuilder $builder)
75
    {
76
        $this->builder = $builder;
77 1
        $this->XMLStyle = XMLStyleFactory::create($builder->getStyle(), $builder->getParameterStyle());
78
        $this->XMLUse = XMLUseFactory::create($builder->getUse());
79 1
        $this->XMLSoapVersion = XMLSoapVersion::getTagFor($builder->getSoapVersion());
80 1
        $this->DOMDocument = new DOMDocument("1.0", "UTF-8");
81 1
        $this->DOMDocument->formatOutput = true;
82 1
    }
83 1
84 1
    public function getXml(): string
85 1
    {
86
        $this->xml = $this->DOMDocument->saveXML();
87
88
        return $this->xml;
89
    }
90 1
91
    public function generate(): void
92 1
    {
93 1
        $this->definitions()
94
            ->types()
95
            ->message()
96
            ->portType()
97
            ->binding()
98
            ->service();
99 1
    }
100
101 1
    private function definitions(): XMLProvider
102 1
    {
103 1
        $targetNamespace = $this->builder->getTargetNamespace();
104 1
        $definitionsElement = $this->createElementWithAttributes('definitions', [
105 1
            'name' => $this->builder->getName(),
106 1
            'targetNamespace' => $targetNamespace,
107 1
            'xmlns:tns' => $targetNamespace,
108
            'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
109
            'xmlns:' . $this->XMLSoapVersion => 'http://schemas.xmlsoap.org/wsdl/' . $this->XMLSoapVersion . '/',
110
            'xmlns:soapenc' => "http://schemas.xmlsoap.org/soap/encoding/",
111
            'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
112 1
            'xmlns:ns' => $this->builder->getNs()
113
        ]);
114 1
        $this->DOMDocument->appendChild($definitionsElement);
115 1
        $this->definitionsRootNode = $definitionsElement;
116 1
117 1
        return $this;
118 1
    }
119 1
120 1
    private function service(): XMLProvider
121 1
    {
122 1
        $name = $this->builder->getName();
123 1
        $serviceElement = $this->createElementWithAttributes('service', ['name' => $name . 'Service']);
124 1
125 1
        $portName = $this->builder->getPortName();
126 1
        $portElement = $this->createElementWithAttributes('port', ['name' => $portName . 'Port', 'binding' => 'tns:' . $name . 'Binding']);
127 1
128
        $soapAddressElement = $this
129
            ->createElementWithAttributes($this->XMLSoapVersion . ':address', ['location' => $this->builder->getLocation()]);
130
        $portElement->appendChild($soapAddressElement);
131
132
        $serviceElement->appendChild($portElement);
133 1
        $this->definitionsRootNode->appendChild($serviceElement);
134
135 1
        return $this;
136 1
    }
137
138 1
    private function binding(): XMLProvider
139
    {
140 1
        $name = $this->builder->getName();
141 1
        $targetNamespace = $this->builder->getTargetNamespace();
142 1
        $bindingElement = $this->createElementWithAttributes('binding', ['name' => $name . 'Binding', 'type' => 'tns:' . $name . 'PortType']);
143
144 1
        $soapBindingElement = $this->XMLStyle->generateBinding($this->DOMDocument, $this->XMLSoapVersion);
145 1
        $bindingElement->appendChild($soapBindingElement);
146 1
147
        foreach ($this->builder->getMethods() as $method) {
148
            $methodName = $method->getName();
149
            $operationElement = $this->createElementWithAttributes('operation', ['name' => $methodName]);
150
            $soapOperationElement = $this->createElementWithAttributes($this->XMLSoapVersion . ':operation', [
151
                'soapAction' => $targetNamespace . '/#' . $methodName
152 1
            ]);
153
            $operationElement->appendChild($soapOperationElement);
154 1
155 1
            $soapBodyElement = $this->XMLUse->generateSoapBody($this->DOMDocument, $targetNamespace, $this->XMLSoapVersion);
156 1
            $this->bindingElement($methodName, $soapBodyElement, $operationElement, 'input', 'RequestHeader', $method->getHeaderParameter());
157
            $this->bindingElement($methodName, $soapBodyElement, $operationElement, 'output', 'ResponseHeader', $method->getHeaderReturn());
158 1
159 1
            $bindingElement->appendChild($operationElement);
160
        }
161 1
162 1
        $this->definitionsRootNode->appendChild($bindingElement);
163 1
164 1
        return $this;
165 1
    }
166 1
167 1
    private function bindingElement(string $methodName, DOMElement $soapBodyElement, DOMElement $element, string $elementName, string $headerName, Parameter $header = null): void
168
    {
169 1
        $targetNamespace = $this->builder->getTargetNamespace();
170 1
        $inputElement = $this->createElement($elementName);
171 1
        $inputElement->appendChild($soapBodyElement->cloneNode());
172
173 1
        $soapHeaderMessage = 'tns:' . $methodName . $headerName;
174 1
        $soapHeaderElement = $this->XMLUse
175
            ->generateSoapHeaderIfNeeded($this->DOMDocument, $targetNamespace, $this->XMLSoapVersion, $soapHeaderMessage, $header);
176 1
        if ($soapHeaderElement) {
177 1
            $inputElement->appendChild($soapHeaderElement);
178
        }
179
180
        $element->appendChild($inputElement);
181
    }
182
183
    private function portType(): XMLProvider
184
    {
185
        $name = $this->builder->getName();
186
        $portTypeElement = $this->createElementWithAttributes('portType', ['name' => $name . 'PortType']);
187
188 1
        foreach ($this->builder->getMethods() as $method) {
189
            $methodName = $method->getName();
190 1
            $operationElement = $this->createElementWithAttributes('operation', ['name' => $methodName]);
191 1
192 1
            $inputElement = $this->createElementWithAttributes('input', ['message' => 'tns:' . $methodName . 'Request']);
193
            $operationElement->appendChild($inputElement);
194 1
195 1
            $outputElement = $this->createElementWithAttributes('output', ['message' => 'tns:' . $methodName . 'Response']);
196 1
            $operationElement->appendChild($outputElement);
197 1
198 1
            $portTypeElement->appendChild($operationElement);
199 1
        }
200
201 1
        $this->definitionsRootNode->appendChild($portTypeElement);
202 1
203
        return $this;
204
    }
205
206
    private function message(): XMLProvider
207 1
    {
208
        foreach ($this->builder->getMethods() as $method) {
209 1
            $name = $method->getName();
210 1
211
            $this->messageHeaderIfNeeded($name, 'RequestHeader', $method->getHeaderParameter());
212 1
            $messageInputElement = $this->messageParts($name . 'Request', $method->getNoHeaderParametersNodes());
213 1
            $this->definitionsRootNode->appendChild($messageInputElement);
214 1
215
            $this->messageHeaderIfNeeded($name, 'ResponseHeader', $method->getHeaderReturn());
216 1
            $messageOutputElement = $this->messageParts($name . 'Response', $method->getReturnNode());
217 1
            $this->definitionsRootNode->appendChild($messageOutputElement);
218
        }
219 1
220 1
        return $this;
221
    }
222 1
223 1
    private function messageHeaderIfNeeded(string $methodName, string $headerSuffix, Parameter $parameter = null): void
224
    {
225 1
        if ($parameter) {
226 1
            $messageHeaderElement = $this->messageParts($methodName . $headerSuffix, $parameter->getNode());
227
            $this->definitionsRootNode->appendChild($messageHeaderElement);
228
        }
229
    }
230
231
    /**
232 1
     * @param string $methodName
233
     * @param Node|Node[]|null $nodes
234 1
     * @return DOMElement
235 1
     */
236
    private function messageParts(string $methodName, $nodes): DOMElement
237 1
    {
238 1
        $messageElement = $this->createElementWithAttributes('message', ['name' => $methodName]);
239 1
        if ($nodes !== null) {
240
            $nodes = Arrays::toArray($nodes);
241 1
            $parts = $this->XMLStyle->generateMessagePart($this->DOMDocument, $nodes);
242 1
            foreach ($parts as $part) {
243 1
                $messageElement->appendChild($part);
244 1
            }
245 1
        }
246
247
        return $messageElement;
248
    }
249
250
    private function types(): XMLProvider
251
    {
252
        $ns = $this->builder->getNs();
253 1
        $typesElement = $this->createElement('types');
254
255 1
        $schemaElement = $this->createElementWithAttributes('xsd:schema', ['targetNamespace' => $ns, 'xmlns' => $ns]);
256 1
        foreach ($this->builder->getMethods() as $method) {
257 1
            $typesForParameters = $this->XMLStyle->generateTypes($this->DOMDocument, $method->getParameters(), $this->XMLSoapVersion);
258 1
            $typesForReturn = $this->XMLStyle->generateTypes($this->DOMDocument, Arrays::toArray($method->getReturn()), $this->XMLSoapVersion);
259 1
            $types = array_merge($typesForParameters, $typesForReturn);
260
            foreach ($types as $type) {
261
                $schemaElement->appendChild($type);
262
            }
263
        }
264
        $typesElement->appendChild($schemaElement);
265
266 1
        $this->definitionsRootNode->appendChild($typesElement);
267
268 1
        return $this;
269 1
    }
270 1
271 1
    private function createElementWithAttributes(string $elementName, array $attributes, string $value = ''): DOMElement
272 1
    {
273 1
        return XMLAttributeHelper::forDOM($this->DOMDocument)->createElementWithAttributes($elementName, $attributes, $value);
274 1
    }
275 1
276 1
    private function createElement(string $elementName, string $value = ''): DOMElement
277
    {
278
        return XMLAttributeHelper::forDOM($this->DOMDocument)->createElement($elementName, $value);
279
    }
280
}
281