GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( fa9233...7f89d9 )
by Tomas
06:55
created

XMLGenerator::_saveXML()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Copyright (C) 2013-2015
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 ReflectionClass;
28
use WSDL\Parser\MethodParser;
29
use WSDL\Utilities\Strings;
30
use WSDL\XML\Styles\DocumentLiteralWrapped;
31
use WSDL\XML\Styles\Style;
32
use WSDL\XML\Styles\TypesComplex;
33
use WSDL\XML\Styles\TypesElement;
34
35
/**
36
 * XMLGenerator
37
 *
38
 * @author Piotr Olaszewski <[email protected]>
39
 * @see http://www.xfront.com/GlobalVersusLocal.html
40
 */
41
class XMLGenerator
42
{
43
    private $_name;
44
    private $_location;
45
    private $_targetNamespace;
46
    private $_targetNamespaceTypes;
47
    /**
48
     * @var DOMDocument
49
     */
50
    private $_DOMDocument;
51
    /**
52
     * @var DOMDocument
53
     */
54
    private $_definitionsRootNode;
55
    /**
56
     * @var DOMDocument
57
     */
58
    private $_generatedXML;
59
    /**
60
     * @var MethodParser[]
61
     */
62
    private $_WSDLMethods;
63
    /**
64
     * @var Style
65
     */
66
    private $_bindingStyle;
67
68
    public static $alreadyGeneratedComplexTypes = array();
69
70 7
    public function __construct($name, $namespace, $location)
71
    {
72 7
        $this->_name = $this->extractClassName($name);
73 7
        $this->_location = $location;
74
75 7
        $this->_targetNamespace = $this->sanitizeClassName($namespace, $name);
76 7
        $this->_targetNamespaceTypes = $this->_targetNamespace . '/types';
77
78 7
        $this->_DOMDocument = new DOMDocument("1.0", "UTF-8");
79 7
        $this->_DOMDocument->formatOutput = true;
80 7
        $this->_saveXML();
81 7
    }
82
83 7
    public function sanitizeClassName($namespace, $class)
84
    {
85 7
        return Strings::sanitizedNamespaceWithClass($namespace, $class);
86
    }
87
88 7
    public function extractClassName($name)
89
    {
90 7
        $reflectedClass = new ReflectionClass($name);
91 7
        return $reflectedClass->getShortName();
92
    }
93
94 7
    public function setWSDLMethods($WSDLMethods)
95
    {
96 7
        $this->_WSDLMethods = $WSDLMethods;
97 7
        return $this;
98
    }
99
100 7
    public function setBindingStyle(Style $_bindingStyle)
101
    {
102 7
        $this->_bindingStyle = $_bindingStyle;
103 7
        return $this;
104
    }
105
106 7
    public function generate()
107
    {
108 7
        $this->_definitions()
109 7
            ->_types()
110 7
            ->_message()->_portType()->_binding()->_service();
111 7
    }
112
113
    /**
114
     * @return XMLGenerator
115
     */
116 7
    private function _definitions()
117
    {
118 7
        $definitionsElement = $this->createElementWithAttributes('definitions', array(
119 7
            'name' => $this->_name,
120 7
            'targetNamespace' => $this->_targetNamespace,
121 7
            'xmlns:tns' => $this->_targetNamespace,
122 7
            'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
123 7
            'xmlns:soap' => 'http://schemas.xmlsoap.org/wsdl/soap/',
124 7
            'xmlns:soapenc' => "http://schemas.xmlsoap.org/soap/encoding/",
125 7
            'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
126 7
            'xmlns:ns' => $this->_targetNamespaceTypes
127 7
        ));
128 7
        $this->_DOMDocument->appendChild($definitionsElement);
129 7
        $this->_definitionsRootNode = $definitionsElement;
0 ignored issues
show
Documentation Bug introduced by
It seems like $definitionsElement of type object<DOMElement> is incompatible with the declared type object<DOMDocument> of property $_definitionsRootNode.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
130 7
        $this->_saveXML();
131 7
        return $this;
132
    }
133
134
    /**
135
     * @return XMLGenerator
136
     */
137 7
    private function _types()
138
    {
139 7
        $typesElement = $this->_createElement('types');
140
141 7
        $schemaElement = $this->createElementWithAttributes('xsd:schema', array(
142 7
            'targetNamespace' => $this->_targetNamespaceTypes,
143 7
            'xmlns' => $this->_targetNamespaceTypes
144 7
        ));
145
146 7
        foreach ($this->_WSDLMethods as $method) {
147 7
            $typeParameters = $this->_bindingStyle->typeParameters($method);
148 7
            if ($typeParameters) {
149 7
                $this->_typesParameters($typeParameters, $schemaElement);
150 7
            }
151
152 7
            $typeReturning = $this->_bindingStyle->typeReturning($method);
153 7
            $this->_generateComplexType($typeReturning, $schemaElement);
154 7
        }
155
156 7
        $typesElement->appendChild($schemaElement);
157 7
        $this->_definitionsRootNode->appendChild($typesElement);
158 7
        $this->_saveXML();
159 7
        return $this;
160
    }
161
162 7
    private function _typesParameters($parameters, $schemaElement)
163
    {
164 7
        foreach ($parameters as $parameter) {
165 7
            $this->_generateComplexType($parameter, $schemaElement);
166 7
        }
167 7
    }
168
169 7
    private function _generateComplexType($parameter, $schemaElement)
170
    {
171 7
        if ($parameter instanceof TypesComplex) {
172 7
            if (!$this->_bindingStyle instanceof DocumentLiteralWrapped) {
173 7
                $this->_generateArray($parameter, $schemaElement);
174 7
            } else {
175
                $this->_generateTypedArray($parameter, $schemaElement);
176
            }
177 7
        }
178 7
        if ($parameter instanceof TypesElement) {
179 7
            $this->_generateObject($parameter, $schemaElement);
180 7
        }
181 7
    }
182
183 7
    private function _generateObject(TypesElement $parameter, $schemaElement)
184
    {
185 7
        $name = $parameter->getName();
186
187 7
        if (self::isAlreadyGenerated($name)) {
188 7
            return;
189
        }
190
191 7
        $element = $this->createElementWithAttributes('xsd:element', array(
192 7
            'name' => $name,
193 7
            'nillable' => 'true',
194
            'type' => 'ns:' . $name
195 7
        ));
196 7
        $complexTypeElement = $this->createElementWithAttributes('xsd:complexType', array(
197
            'name' => $name
198 7
        ));
199 7
        $sequenceElement = $this->_createElement('xsd:sequence');
200
201 7
        $types = $parameter->getElementAttributes();
202 7
        foreach ($types as $complexType) {
203 7
            $elementPartElement = $this->createElementWithAttributes('xsd:element', array(
204 7
                'name' => $complexType['name'],
205 7
                'type' => $complexType['value']
206 7
            ));
207 7
            $sequenceElement->appendChild($elementPartElement);
208 7
        }
209
210 7
        $complex = $parameter->getComplex();
211 7
        if ($complex) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $complex of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
212 1
            foreach ($complex as $complexElement) {
213 1
                $this->_generateComplexType($complexElement, $schemaElement);
214 1
            }
215 1
        }
216
217 7
        $complexTypeElement->appendChild($sequenceElement);
218
219 7
        $schemaElement->appendChild($complexTypeElement);
220 7
        $schemaElement->appendChild($element);
221 7
    }
222
223 7
    private function _generateArray(TypesComplex $parameter, $schemaElement)
224
    {
225 7
        $name = $parameter->getName();
226 7
        $type = $parameter->getArrayType();
227
228 7
        if (self::isAlreadyGenerated($name)) {
229
            return;
230
        }
231
232 7
        $complexTypeElement = $this->createElementWithAttributes('xsd:complexType', array('name' => $name));
233 7
        $complexContentElement = $this->_createElement('xsd:complexContent');
234 7
        $restrictionElement = $this->createElementWithAttributes('xsd:restriction', array('base' => 'soapenc:Array'));
235 7
        $attributeElement = $this->createElementWithAttributes('xsd:attribute', array(
236 7
            'ref' => 'soapenc:arrayType',
237
            'soap:arrayType' => $type
238 7
        ));
239 7
        $restrictionElement->appendChild($attributeElement);
240 7
        $complexContentElement->appendChild($restrictionElement);
241 7
        $complexTypeElement->appendChild($complexContentElement);
242 7
        $schemaElement->appendChild($complexTypeElement);
243
244 7
        if ($parameter->getComplex()) {
245 7
            $this->_generateComplexType($parameter->getComplex(), $schemaElement);
246 7
        }
247 7
    }
248
249
    private function _generateTypedArray(TypesComplex $parameter, $schemaElement)
250
    {
251
        $name = $parameter->getName();
252
        $type = $parameter->getArrayType();
253
        $typeName = $parameter->getArrayTypeName();
254
255
        if (self::isAlreadyGenerated($name)) {
256
            return;
257
        }
258
259
        $complexTypeElement = $this->createElementWithAttributes('xsd:complexType', array('name' => $name));
260
        $sequence = $this->_createElement('xsd:sequence');
261
        $element = $this->createElementWithAttributes('xsd:element', array(
262
            'minOccurs' => 0,
263
            'maxOccurs' => 'unbounded',
264
            'name' => $typeName,
265
            'nillable' => 'true',
266
            'type' => str_replace('[]', '', $type)
267
        ));
268
        $sequence->appendChild($element);
269
        $complexTypeElement->appendChild($sequence);
270
        $schemaElement->appendChild($complexTypeElement);
271
272
        if ($parameter->getComplex()) {
273
            $this->_generateComplexType($parameter->getComplex(), $schemaElement);
274
        }
275
    }
276
277 7
    public static function isAlreadyGenerated($name)
278
    {
279 7
        if (in_array($name, self::$alreadyGeneratedComplexTypes)) {
280 7
            return true;
281
        } else {
282 7
            self::$alreadyGeneratedComplexTypes[] = $name;
283 7
            return false;
284
        }
285
    }
286
287
    /**
288
     * @return XMLGenerator
289
     */
290 7
    private function _message()
291
    {
292 7
        foreach ($this->_WSDLMethods as $method) {
293 7
            $messageInputElement = $this->_messageInput($method);
294 7
            $this->_definitionsRootNode->appendChild($messageInputElement);
295
296 7
            $messageOutputElement = $this->_messageOutput($method);
297 7
            $this->_definitionsRootNode->appendChild($messageOutputElement);
298 7
        }
299 7
        return $this;
300
    }
301
302 7
    private function _messageInput(MethodParser $method)
303
    {
304 7
        $messageInputElement = $this->createElementWithAttributes('message', array(
305 7
            'name' => $method->getName() . 'Request'
306 7
        ));
307 7
        $partsInput = $this->_bindingStyle->methodInput($method);
308 7
        $obj = $this;
309 7
        $partsInput = array_map(function ($attributes) use ($obj) {
310 7
            return $obj->createElementWithAttributes('part', $attributes);
311 7
        }, $partsInput);
312 7
        foreach ($partsInput as $part) {
313 7
            $messageInputElement->appendChild($part);
314 7
        }
315 7
        return $messageInputElement;
316
    }
317
318 7
    private function _messageOutput(MethodParser $method)
319
    {
320 7
        $messageOutputElement = $this->createElementWithAttributes('message', array(
321 7
            'name' => $method->getName() . 'Response'
322 7
        ));
323 7
        $partsOutput = $this->_bindingStyle->methodOutput($method);
324 7
        $partsOutput = $this->createElementWithAttributes('part', $partsOutput);
325 7
        $messageOutputElement->appendChild($partsOutput);
326 7
        return $messageOutputElement;
327
    }
328
329
    /**
330
     * @return XMLGenerator
331
     */
332 7
    private function _portType()
333
    {
334 7
        $portTypeElement = $this->createElementWithAttributes('portType', array(
335 7
            'name' => $this->_name . 'PortType'
336 7
        ));
337
338 7
        foreach ($this->_WSDLMethods as $method) {
339 7
            $operationElement = $this->createElementWithAttributes('operation', array('name' => $method->getName()));
340
341 7
            if ($method->description()) {
342 7
                $documentationElement = $this->_createElement('documentation', $method->description());
343 7
                $operationElement->appendChild($documentationElement);
344 7
            }
345
346 7
            $inputElement = $this->createElementWithAttributes('input', array('message' => 'tns:' . $method->getName() . 'Request'));
347 7
            $operationElement->appendChild($inputElement);
348
349 7
            $outputElement = $this->createElementWithAttributes('output', array('message' => 'tns:' . $method->getName() . 'Response'));
350 7
            $operationElement->appendChild($outputElement);
351
352 7
            $portTypeElement->appendChild($operationElement);
353 7
        }
354 7
        $this->_definitionsRootNode->appendChild($portTypeElement);
355 7
        $this->_saveXML();
356 7
        return $this;
357
    }
358
359
    /**
360
     * @return XMLGenerator
361
     */
362 7
    private function _binding()
363
    {
364 7
        $bindingElement = $this->createElementWithAttributes('binding', array(
365 7
            'name' => $this->_name . 'Binding',
366 7
            'type' => 'tns:' . $this->_name . 'PortType'
367 7
        ));
368
369 7
        $soapBindingElement = $this->createElementWithAttributes('soap:binding', array(
370 7
            'style' => $this->_bindingStyle->bindingStyle(),
371
            'transport' => 'http://schemas.xmlsoap.org/soap/http'
372 7
        ));
373 7
        $bindingElement->appendChild($soapBindingElement);
374
375 7
        foreach ($this->_WSDLMethods as $method) {
376 7
            $soapBodyElement = $this->createElementWithAttributes('soap:body', array(
377 7
                'use' => $this->_bindingStyle->bindingUse(),
378 7
                'namespace' => $this->_targetNamespace
379 7
            ));
380
381 7
            if ($this->_bindingStyle instanceof \WSDL\XML\Styles\RpcEncoded) {
382 1
                $encodingUri = $this->_createAttributeWithValue('encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/');
383 1
                $soapBodyElement->appendChild($encodingUri);
384 1
            }
385
386 7
            $operationElement = $this->createElementWithAttributes('operation', array(
387 7
                'name' => $method->getName()
388 7
            ));
389
390 7
            $soapOperationElement = $this->createElementWithAttributes('soap:operation', array(
391 7
                'soapAction' => $this->_targetNamespace . '/#' . $method->getName()
392 7
            ));
393 7
            $operationElement->appendChild($soapOperationElement);
394
395 7
            $inputElement = $this->_createElement('input');
396 7
            $inputElement->appendChild($soapBodyElement);
397 7
            $operationElement->appendChild($inputElement);
398
399 7
            $outputElement = $this->_createElement('output');
400 7
            $outputElement->appendChild($soapBodyElement->cloneNode());
401 7
            $operationElement->appendChild($outputElement);
402
403 7
            $bindingElement->appendChild($operationElement);
404 7
        }
405 7
        $this->_definitionsRootNode->appendChild($bindingElement);
406 7
        $this->_saveXML();
407 7
        return $this;
408
    }
409
410
    /**
411
     * @return XMLGenerator
412
     */
413 7
    private function _service()
414
    {
415 7
        $serviceElement = $this->createElementWithAttributes('service', array('name' => $this->_name . 'Service'));
416
417 7
        $portElement = $this->createElementWithAttributes('port', array(
418 7
            'name' => $this->_name . 'Port',
419 7
            'binding' => 'tns:' . $this->_name . 'Binding'
420 7
        ));
421
422 7
        $soapAddressElement = $this->createElementWithAttributes('soap:address', array('location' => $this->_location));
423 7
        $portElement->appendChild($soapAddressElement);
424
425 7
        $serviceElement->appendChild($portElement);
426 7
        $this->_definitionsRootNode->appendChild($serviceElement);
427 7
        $this->_saveXML();
428 7
    }
429
430 7
    private function _createElement($elementName, $value = '')
431
    {
432 7
        return $this->_DOMDocument->createElement($elementName, $value);
433
    }
434
435 7
    private function _createAttributeWithValue($attributeName, $value)
436
    {
437 7
        $attribute = $this->_DOMDocument->createAttribute($attributeName);
438 7
        $attribute->value = $value;
439 7
        return $attribute;
440
    }
441
442 7
    public function createElementWithAttributes($elementName, $attributes, $value = '')
443
    {
444 7
        $element = $this->_createElement($elementName, $value);
445 7
        foreach ($attributes as $attributeName => $attributeValue) {
446 7
            $tmpAttr = $this->_createAttributeWithValue($attributeName, $attributeValue);
447 7
            $element->appendChild($tmpAttr);
448 7
        }
449 7
        return $element;
450
    }
451
452 7
    private function _saveXML()
453
    {
454 7
        $this->_generatedXML = $this->_DOMDocument->saveXML();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->_DOMDocument->saveXML() of type string is incompatible with the declared type object<DOMDocument> of property $_generatedXML.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
455 7
    }
456
457 7
    public function getGeneratedXML()
458
    {
459 7
        return $this->_generatedXML;
460
    }
461
462 1
    public function render()
463
    {
464 1
        echo $this->_generatedXML;
465 1
    }
466
}
467