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 ( 155582...e79d5b )
by Tomas
11s
created

XMLGenerator::generate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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