Completed
Push — master ( 086e6a...91f838 )
by Asmir
02:28
created

SchemaReader::loadImport()   C

Complexity

Conditions 11
Paths 7

Size

Total Lines 46
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 11.8766

Importance

Changes 0
Metric Value
dl 0
loc 46
ccs 25
cts 31
cp 0.8065
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 27
nc 7
nop 2
crap 11.8766

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace GoetasWebservices\XML\XSDReader;
3
4
use DOMDocument;
5
use DOMElement;
6
use DOMNode;
7
use GoetasWebservices\XML\XSDReader\Exception\IOException;
8
use GoetasWebservices\XML\XSDReader\Exception\TypeException;
9
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Attribute;
10
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeDef;
11
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeRef;
12
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
13
use GoetasWebservices\XML\XSDReader\Schema\Element\Element;
14
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementContainer;
15
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
16
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
17
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementRef;
18
use GoetasWebservices\XML\XSDReader\Schema\Element\Group;
19
use GoetasWebservices\XML\XSDReader\Schema\Element\GroupRef;
20
use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException;
21
use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Extension;
22
use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Restriction;
23
use GoetasWebservices\XML\XSDReader\Schema\Item;
24
use GoetasWebservices\XML\XSDReader\Schema\Schema;
25
use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType;
26
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
27
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexTypeSimpleContent;
28
use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType;
29
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
30
use GoetasWebservices\XML\XSDReader\Utils\UrlUtils;
31
32
class SchemaReader
33
{
34
35
    const XSD_NS = "http://www.w3.org/2001/XMLSchema";
36
37
    const XML_NS = "http://www.w3.org/XML/1998/namespace";
38
39
    private $loadedFiles = array();
40
41
    private $knownLocationSchemas = array();
42
43
    private static $globalSchemaInfo = array(
44
        self::XML_NS => 'http://www.w3.org/2001/xml.xsd',
45
        self::XSD_NS => 'http://www.w3.org/2001/XMLSchema.xsd'
46
    );
47
48 53
    public function __construct()
49
    {
50 53
        $this->addKnownSchemaLocation('http://www.w3.org/2001/xml.xsd', __DIR__ . '/Resources/xml.xsd');
51 53
        $this->addKnownSchemaLocation('http://www.w3.org/2001/XMLSchema.xsd', __DIR__ . '/Resources/XMLSchema.xsd');
52 53
        $this->addKnownSchemaLocation('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd', __DIR__ . '/Resources/oasis-200401-wss-wssecurity-secext-1.0.xsd');
53 53
        $this->addKnownSchemaLocation('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd', __DIR__ . '/Resources/oasis-200401-wss-wssecurity-utility-1.0.xsd');
54 53
        $this->addKnownSchemaLocation('https://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd', __DIR__ . '/Resources/xmldsig-core-schema.xsd');
55 53
        $this->addKnownSchemaLocation('http://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd', __DIR__ . '/Resources/xmldsig-core-schema.xsd');
56 53
    }
57
58 53
    public function addKnownSchemaLocation($remote, $local)
59
    {
60 53
        $this->knownLocationSchemas[$remote] = $local;
61 53
    }
62
63 44
    private function loadAttributeGroup(Schema $schema, DOMElement $node)
64
    {
65 44
        $attGroup = new AttributeGroup($schema, $node->getAttribute("name"));
66 44
        $attGroup->setDoc($this->getDocumentation($node));
67 44
        $schema->addAttributeGroup($attGroup);
68
69
        return function () use ($schema, $node, $attGroup) {
70 44
            foreach ($node->childNodes as $childNode) {
71 44
                switch ($childNode->localName) {
72 44 View Code Duplication
                    case 'attribute':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
73 44
                        if ($childNode->hasAttribute("ref")) {
74 44
                            $attribute = $this->findSomething('findAttribute', $schema, $node, $childNode->getAttribute("ref"));
75 44
                        } else {
76 44
                            $attribute = $this->loadAttribute($schema, $childNode);
77
                        }
78 44
                        $attGroup->addAttribute($attribute);
0 ignored issues
show
Bug introduced by
It seems like $attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 74 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...e\Group::addAttribute() does only seem to accept object<GoetasWebservices...ttribute\AttributeItem>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
79 44
                        break;
80 44 View Code Duplication
                    case 'attributeGroup':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
82 1
                        $attribute = $this->findSomething('findAttributeGroup', $schema, $node, $childNode->getAttribute("ref"));
83 1
                        $attGroup->addAttribute($attribute);
0 ignored issues
show
Bug introduced by
It seems like $attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 82 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...e\Group::addAttribute() does only seem to accept object<GoetasWebservices...ttribute\AttributeItem>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
84 1
                        break;
85 44
                }
86 44
            }
87 44
        };
88
    }
89
90 44
    private function loadAttribute(Schema $schema, DOMElement $node)
91
    {
92 44
        $attribute = new Attribute($schema, $node->getAttribute("name"));
93 44
        $attribute->setDoc($this->getDocumentation($node));
94 44
        $this->fillItem($attribute, $node);
95
96 44
        if ($node->hasAttribute("nillable")) {
97 1
            $attribute->setNil($node->getAttribute("nillable") == "true");
98 1
        }
99 44
        if ($node->hasAttribute("form")) {
100 1
            $attribute->setQualified($node->getAttribute("form") == "qualified");
101 1
        }
102 44
        if ($node->hasAttribute("use")) {
103 44
            $attribute->setUse($node->getAttribute("use"));
104 44
        }
105 44
        return $attribute;
106
    }
107
108
109 44 View Code Duplication
    private function loadAttributeDef(Schema $schema, DOMElement $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
    {
111 44
        $attribute = new AttributeDef($schema, $node->getAttribute("name"));
112
113 44
        $schema->addAttribute($attribute);
114
115
        return function () use ($attribute, $schema, $node) {
116 44
            $this->fillItem($attribute, $node);
117 44
        };
118
    }
119
120
    /**
121
     * @param DOMElement $node
122
     * @return string
123
     */
124 44
    private function getDocumentation(DOMElement $node)
125
    {
126 44
        $doc = '';
127 44
        foreach ($node->childNodes as $childNode) {
128 44
            if ($childNode->localName == "annotation") {
129 44
                foreach ($childNode->childNodes as $subChildNode) {
130 44
                    if ($subChildNode->localName == "documentation") {
131 44
                        $doc .= ($subChildNode->nodeValue);
132 44
                    }
133 44
                }
134 44
            }
135 44
        }
136 44
        $doc = preg_replace('/[\t ]+/', ' ', $doc);
137 44
        return trim($doc);
138
    }
139
140
    /**
141
     *
142
     * @param Schema $schema
143
     * @param DOMElement $node
144
     * @param Schema $parent
145
     * @return array
146
     */
147 44
    private function schemaNode(Schema $schema, DOMElement $node, Schema $parent = null)
148
    {
149 44
        $schema->setDoc($this->getDocumentation($node));
150
151 44
        if ($node->hasAttribute("targetNamespace")) {
152 44
            $schema->setTargetNamespace($node->getAttribute("targetNamespace"));
153 44
        } elseif ($parent) {
154
            $schema->setTargetNamespace($parent->getTargetNamespace());
155
        }
156 44
        $schema->setElementsQualification($node->getAttribute("elementFormDefault") == "qualified");
157 44
        $schema->setAttributesQualification($node->getAttribute("attributeFormDefault") == "qualified");
158 44
        $schema->setDoc($this->getDocumentation($node));
159 44
        $functions = array();
160
161 44
        foreach ($node->childNodes as $childNode) {
162 44
            switch ($childNode->localName) {
163 44
                case 'include':
164 44
                case 'import':
165 44
                    $functions[] = $this->loadImport($schema, $childNode);
166 44
                    break;
167 44
                case 'element':
168 44
                    $functions[] = $this->loadElementDef($schema, $childNode);
169 44
                    break;
170 44
                case 'attribute':
171 44
                    $functions[] = $this->loadAttributeDef($schema, $childNode);
172 44
                    break;
173 44
                case 'attributeGroup':
174 44
                    $functions[] = $this->loadAttributeGroup($schema, $childNode);
175 44
                    break;
176 44
                case 'group':
177 44
                    $functions[] = $this->loadGroup($schema, $childNode);
178 44
                    break;
179 44
                case 'complexType':
180 44
                    $functions[] = $this->loadComplexType($schema, $childNode);
181 44
                    break;
182 44
                case 'simpleType':
183 44
                    $functions[] = $this->loadSimpleType($schema, $childNode);
184 44
                    break;
185 44
            }
186 44
        }
187
188 44
        return $functions;
189
    }
190
191 44
    private function loadElement(Schema $schema, DOMElement $node)
192
    {
193 44
        $element = new Element($schema, $node->getAttribute("name"));
194 44
        $element->setDoc($this->getDocumentation($node));
195
196 44
        $this->fillItem($element, $node);
197
198 44
        if ($node->hasAttribute("maxOccurs")) {
199 44
            $element->setMax($node->getAttribute("maxOccurs") == "unbounded" ? -1 : (int)$node->getAttribute("maxOccurs"));
200 44
        }
201 44
        if ($node->hasAttribute("minOccurs")) {
202 44
            $element->setMin((int)$node->getAttribute("minOccurs"));
203 44
        }
204
205 44
        $xp = new \DOMXPath($node->ownerDocument);
206 44
        $xp->registerNamespace('xs', 'http://www.w3.org/2001/XMLSchema');
207
        
208 44
        if ($xp->query('ancestor::xs:choice', $node)->length) {
209 44
            $element->setMin(0);
210 44
        }
211
212 44
        if ($node->hasAttribute("nillable")) {
213 3
            $element->setNil($node->getAttribute("nillable") == "true");
214 3
        }
215 44
        if ($node->hasAttribute("form")) {
216 3
            $element->setQualified($node->getAttribute("form") == "qualified");
217 3
        }
218 44
        return $element;
219
    }
220
221 44
    private function loadGroupRef(Group $referenced, DOMElement $node)
222
    {
223 44
        $ref = new GroupRef($referenced);
224 44
        $ref->setDoc($this->getDocumentation($node));
225
226 44 View Code Duplication
        if ($node->hasAttribute("maxOccurs")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
227 44
            $ref->setMax($node->getAttribute("maxOccurs") == "unbounded" ? -1 : (int)$node->getAttribute("maxOccurs"));
228 44
        }
229 44
        if ($node->hasAttribute("minOccurs")) {
230 44
            $ref->setMin((int)$node->getAttribute("minOccurs"));
231 44
        }
232
233 44
        return $ref;
234
    }
235
236 44
    private function loadElementRef(ElementDef $referenced, DOMElement $node)
237
    {
238 44
        $ref = new ElementRef($referenced);
239 44
        $ref->setDoc($this->getDocumentation($node));
240
241 44 View Code Duplication
        if ($node->hasAttribute("maxOccurs")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242 44
            $ref->setMax($node->getAttribute("maxOccurs") == "unbounded" ? -1 : (int)$node->getAttribute("maxOccurs"));
243 44
        }
244 44
        if ($node->hasAttribute("minOccurs")) {
245 44
            $ref->setMin((int)$node->getAttribute("minOccurs"));
246 44
        }
247 44
        if ($node->hasAttribute("nillable")) {
248
            $ref->setNil($node->getAttribute("nillable") == "true");
249
        }
250 44
        if ($node->hasAttribute("form")) {
251
            $ref->setQualified($node->getAttribute("form") == "qualified");
252
        }
253
254 44
        return $ref;
255
    }
256
257
258 44
    private function loadAttributeRef(AttributeDef $referencedAttribiute, DOMElement $node)
259
    {
260 44
        $attribute = new AttributeRef($referencedAttribiute);
261 44
        $attribute->setDoc($this->getDocumentation($node));
262
263 44
        if ($node->hasAttribute("nillable")) {
264
            $attribute->setNil($node->getAttribute("nillable") == "true");
265
        }
266 44
        if ($node->hasAttribute("form")) {
267
            $attribute->setQualified($node->getAttribute("form") == "qualified");
268
        }
269 44
        if ($node->hasAttribute("use")) {
270
            $attribute->setUse($node->getAttribute("use"));
271
        }
272 44
        return $attribute;
273
    }
274
275 44
    private function loadSequence(ElementContainer $elementContainer, DOMElement $node, $max = null)
276
    {
277 44
        $max = $max || $node->getAttribute("maxOccurs") == "unbounded" || $node->getAttribute("maxOccurs") > 1 ? 2 : null;
278
279 44
        foreach ($node->childNodes as $childNode) {
280
281 44
            switch ($childNode->localName) {
282 44
                case 'choice':
283 44
                case 'sequence':
284 44
                case 'all':
285 44
                    $this->loadSequence($elementContainer, $childNode, $max);
286 44
                    break;
287 44
                case 'element':
288 44
                    if ($childNode->hasAttribute("ref")) {
289 44
                        $referencedElement = $this->findSomething('findElement', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref"));
290 44
                        $element = $this->loadElementRef($referencedElement, $childNode);
0 ignored issues
show
Bug introduced by
It seems like $referencedElement defined by $this->findSomething('fi...e->getAttribute('ref')) on line 289 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...eader::loadElementRef() does only seem to accept object<GoetasWebservices...ema\Element\ElementDef>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
291 44
                    } else {
292 44
                        $element = $this->loadElement($elementContainer->getSchema(), $childNode);
293
                    }
294 44
                    if ($max) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $max of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
295 44
                        $element->setMax($max);
296 44
                    }
297 44
                    $elementContainer->addElement($element);
298 44
                    break;
299 44
                case 'group':
300 44
                    $referencedGroup = $this->findSomething('findGroup', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref"));
301
302 44
                    $group = $this->loadGroupRef($referencedGroup, $childNode);
0 ignored issues
show
Bug introduced by
It seems like $referencedGroup defined by $this->findSomething('fi...e->getAttribute('ref')) on line 300 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...aReader::loadGroupRef() does only seem to accept object<GoetasWebservices...r\Schema\Element\Group>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
303 44
                    $elementContainer->addElement($group);
304 44
                    break;
305 44
            }
306 44
        }
307 44
    }
308
309 44
    private function loadGroup(Schema $schema, DOMElement $node)
310
    {
311 44
        $group = new Group($schema, $node->getAttribute("name"));
312 44
        $group->setDoc($this->getDocumentation($node));
313
314 44 View Code Duplication
        if ($node->hasAttribute("maxOccurs")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
315
            $group->setMax($node->getAttribute("maxOccurs") == "unbounded" ? -1 : (int)$node->getAttribute("maxOccurs"));
316
        }
317 44
        if ($node->hasAttribute("minOccurs")) {
318
            $group->setMin((int)$node->getAttribute("minOccurs"));
319
        }
320
321 44
        $schema->addGroup($group);
322
323
        return function () use ($group, $node) {
324 44
            foreach ($node->childNodes as $childNode) {
325 44
                switch ($childNode->localName) {
326 44
                    case 'sequence':
327 44
                    case 'choice':
328 44
                    case 'all':
329 44
                        $this->loadSequence($group, $childNode);
330 44
                        break;
331 44
                }
332 44
            }
333 44
        };
334
    }
335
336 44
    private function loadComplexType(Schema $schema, DOMElement $node, $callback = null)
337
    {
338 44
        $isSimple = false;
339
340 44
        foreach ($node->childNodes as $childNode) {
341 44
            if ($childNode->localName === "simpleContent") {
342 2
                $isSimple = true;
343 2
                break;
344
            }
345 44
        }
346
347 44
        $type = $isSimple ? new ComplexTypeSimpleContent($schema, $node->getAttribute("name")) : new ComplexType($schema, $node->getAttribute("name"));
348
349 44
        $type->setDoc($this->getDocumentation($node));
350 44
        if ($node->getAttribute("name")) {
351 44
            $schema->addType($type);
352 44
        }
353
354
        return function () use ($type, $node, $schema, $callback) {
355
356 44
            $this->fillTypeNode($type, $node);
357
358 44
            foreach ($node->childNodes as $childNode) {
359 44
                switch ($childNode->localName) {
360 44
                    case 'sequence':
361 44
                    case 'choice':
362 44
                    case 'all':
363 44
                        $this->loadSequence($type, $childNode);
0 ignored issues
show
Bug introduced by
It seems like $type defined by $isSimple ? new \GoetasW...->getAttribute('name')) on line 347 can also be of type object<GoetasWebservices...mplexTypeSimpleContent>; however, GoetasWebservices\XML\XS...aReader::loadSequence() does only seem to accept object<GoetasWebservices...ement\ElementContainer>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
364 44
                        break;
365 44
                    case 'attribute':
366 44
                        if ($childNode->hasAttribute("ref")) {
367 44
                            $referencedAttribute = $this->findSomething('findAttribute', $schema, $node, $childNode->getAttribute("ref"));
368 44
                            $attribute = $this->loadAttributeRef($referencedAttribute, $childNode);
0 ignored issues
show
Bug introduced by
It seems like $referencedAttribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 367 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...der::loadAttributeRef() does only seem to accept object<GoetasWebservices...Attribute\AttributeDef>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
369 44
                        } else {
370 44
                            $attribute = $this->loadAttribute($schema, $childNode);
371
                        }
372
373 44
                        $type->addAttribute($attribute);
374 44
                        break;
375 44 View Code Duplication
                    case 'attributeGroup':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
376 2
                        $attribute = $this->findSomething('findAttributeGroup', $schema, $node, $childNode->getAttribute("ref"));
377 2
                        $type->addAttribute($attribute);
0 ignored issues
show
Bug introduced by
It seems like $attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 376 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...lexType::addAttribute() does only seem to accept object<GoetasWebservices...ttribute\AttributeItem>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
378 2
                        break;
379 44
                }
380 44
            }
381
382 44
            if ($callback) {
383 44
                call_user_func($callback, $type);
384 44
            }
385 44
        };
386
    }
387
388 44
    private function loadSimpleType(Schema $schema, DOMElement $node, $callback = null)
389
    {
390 44
        $type = new SimpleType($schema, $node->getAttribute("name"));
391 44
        $type->setDoc($this->getDocumentation($node));
392 44
        if ($node->getAttribute("name")) {
393 44
            $schema->addType($type);
394 44
        }
395
396
        return function () use ($type, $node, $callback) {
397 44
            $this->fillTypeNode($type, $node);
398
399 44
            foreach ($node->childNodes as $childNode) {
400 44
                switch ($childNode->localName) {
401 44
                    case 'union':
402 44
                        $this->loadUnion($type, $childNode);
403 44
                        break;
404 44
                    case 'list':
405 44
                        $this->loadList($type, $childNode);
406 44
                        break;
407 44
                }
408 44
            }
409
410 44
            if ($callback) {
411 44
                call_user_func($callback, $type);
412 44
            }
413 44
        };
414
    }
415
416 44
    private function loadList(SimpleType $type, DOMElement $node)
417
    {
418 44 View Code Duplication
        if ($node->hasAttribute("itemType")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
419 44
            $type->setList($this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("itemType")));
0 ignored issues
show
Bug introduced by
It seems like $this->findSomething('fi...tAttribute('itemType')) targeting GoetasWebservices\XML\XS...Reader::findSomething() can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...e\SimpleType::setList() does only seem to accept object<GoetasWebservices...Schema\Type\SimpleType>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
420 44
        } else {
421
            $addCallback = function ($list) use ($type) {
422 44
                $type->setList($list);
423 44
            };
424
425 44
            foreach ($node->childNodes as $childNode) {
426 44
                switch ($childNode->localName) {
427 44
                    case 'simpleType':
428 44
                        call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback));
429 44
                        break;
430 44
                }
431 44
            }
432
        }
433 44
    }
434
435 44
    private function loadUnion(SimpleType $type, DOMElement $node)
436
    {
437 44
        if ($node->hasAttribute("memberTypes")) {
438 44
            $types = preg_split('/\s+/', $node->getAttribute("memberTypes"));
439 44
            foreach ($types as $typeName) {
440 44
                $type->addUnion($this->findSomething('findType', $type->getSchema(), $node, $typeName));
0 ignored issues
show
Bug introduced by
It seems like $this->findSomething('fi...ma(), $node, $typeName) targeting GoetasWebservices\XML\XS...Reader::findSomething() can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...\SimpleType::addUnion() does only seem to accept object<GoetasWebservices...Schema\Type\SimpleType>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
441 44
            }
442 44
        }
443
        $addCallback = function ($unType) use ($type) {
444 44
            $type->addUnion($unType);
445 44
        };
446
447 44
        foreach ($node->childNodes as $childNode) {
448 44
            switch ($childNode->localName) {
449 44
                case 'simpleType':
450 44
                    call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback));
451 44
                    break;
452 44
            }
453 44
        }
454 44
    }
455
456 44
    private function fillTypeNode(Type $type, DOMElement $node, $checkAbstract = true)
457
    {
458
459 44
        if ($checkAbstract) {
460 44
            $type->setAbstract($node->getAttribute("abstract") === "true" || $node->getAttribute("abstract") === "1");
461 44
        }
462
463 44
        foreach ($node->childNodes as $childNode) {
464 44
            switch ($childNode->localName) {
465 44
                case 'restriction':
466 44
                    $this->loadRestriction($type, $childNode);
467 44
                    break;
468 44
                case 'extension':
469 44
                    $this->loadExtension($type, $childNode);
0 ignored issues
show
Compatibility introduced by
$type of type object<GoetasWebservices...eader\Schema\Type\Type> is not a sub-type of object<GoetasWebservices...a\Type\BaseComplexType>. It seems like you assume a child class of the class GoetasWebservices\XML\XSDReader\Schema\Type\Type to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
470 44
                    break;
471 44
                case 'simpleContent':
472 44
                case 'complexContent':
473 44
                    $this->fillTypeNode($type, $childNode, false);
474 44
                    break;
475 44
            }
476 44
        }
477 44
    }
478
479 44
    private function loadExtension(BaseComplexType $type, DOMElement $node)
480
    {
481 44
        $extension = new Extension();
482 44
        $type->setExtension($extension);
483
484 44
        if ($node->hasAttribute("base")) {
485 44
            $parent = $this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("base"));
486 44
            $extension->setBase($parent);
0 ignored issues
show
Bug introduced by
It seems like $parent defined by $this->findSomething('fi...->getAttribute('base')) on line 485 can also be of type object<GoetasWebservices...ma\Element\ElementItem>; however, GoetasWebservices\XML\XS...ritance\Base::setBase() does only seem to accept object<GoetasWebservices...eader\Schema\Type\Type>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
487 44
        }
488
489 44
        foreach ($node->childNodes as $childNode) {
490 44
            switch ($childNode->localName) {
491 44
                case 'sequence':
492 44
                case 'choice':
493 44
                case 'all':
494 44
                    $this->loadSequence($type, $childNode);
0 ignored issues
show
Documentation introduced by
$type is of type object<GoetasWebservices...a\Type\BaseComplexType>, but the function expects a object<GoetasWebservices...ement\ElementContainer>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
495 44
                    break;
496 44 View Code Duplication
                case 'attribute':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
497 44
                    if ($childNode->hasAttribute("ref")) {
498 44
                        $attribute = $this->findSomething('findAttribute', $type->getSchema(), $node, $childNode->getAttribute("ref"));
499 44
                    } else {
500 44
                        $attribute = $this->loadAttribute($type->getSchema(), $childNode);
501
                    }
502 44
                    $type->addAttribute($attribute);
0 ignored issues
show
Bug introduced by
It seems like $attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 498 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...lexType::addAttribute() does only seem to accept object<GoetasWebservices...ttribute\AttributeItem>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
503 44
                    break;
504 44
                case 'attributeGroup':
505 44
                    $attribute = $this->findSomething('findAttributeGroup', $type->getSchema(), $node, $childNode->getAttribute("ref"));
506 44
                    $type->addAttribute($attribute);
0 ignored issues
show
Bug introduced by
It seems like $attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 505 can also be of type object<GoetasWebservices...ma\Element\ElementItem> or object<GoetasWebservices...eader\Schema\Type\Type>; however, GoetasWebservices\XML\XS...lexType::addAttribute() does only seem to accept object<GoetasWebservices...ttribute\AttributeItem>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
507 44
                    break;
508 44
            }
509 44
        }
510 44
    }
511
512 44
    private function loadRestriction(Type $type, DOMElement $node)
513
    {
514 44
        $restriction = new Restriction();
515 44
        $type->setRestriction($restriction);
516 44 View Code Duplication
        if ($node->hasAttribute("base")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
517 44
            $restrictedType = $this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("base"));
518 44
            $restriction->setBase($restrictedType);
0 ignored issues
show
Bug introduced by
It seems like $restrictedType defined by $this->findSomething('fi...->getAttribute('base')) on line 517 can also be of type object<GoetasWebservices...ma\Element\ElementItem>; however, GoetasWebservices\XML\XS...ritance\Base::setBase() does only seem to accept object<GoetasWebservices...eader\Schema\Type\Type>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
519 44
        } else {
520
            $addCallback = function ($restType) use ($restriction) {
521 44
                $restriction->setBase($restType);
522 44
            };
523
524 44
            foreach ($node->childNodes as $childNode) {
525 44
                switch ($childNode->localName) {
526 44
                    case 'simpleType':
527 44
                        call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback));
528 44
                        break;
529 44
                }
530 44
            }
531
        }
532 44
        foreach ($node->childNodes as $childNode) {
533 44
            if (in_array($childNode->localName,
534
                [
535 44
                    'enumeration',
536 44
                    'pattern',
537 44
                    'length',
538 44
                    'minLength',
539 44
                    'maxLength',
540 44
                    'minInclusive',
541 44
                    'maxInclusive',
542 44
                    'minExclusive',
543 44
                    'maxExclusive',
544 44
                    'fractionDigits',
545 44
                    'totalDigits',
546
                    'whiteSpace'
547 44
                ], true)) {
548 44
                $restriction->addCheck($childNode->localName,
549
                    [
550 44
                        'value' => $childNode->getAttribute("value"),
551 44
                        'doc' => $this->getDocumentation($childNode)
552 44
                    ]);
553 44
            }
554 44
        }
555 44
    }
556
557 44
    private static function splitParts(DOMElement $node, $typeName)
558
    {
559 44
        $namespace = null;
0 ignored issues
show
Unused Code introduced by
$namespace is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
560 44
        $prefix = null;
561 44
        $name = $typeName;
562 44
        if (strpos($typeName, ':') !== false) {
563 44
            list ($prefix, $name) = explode(':', $typeName);
564 44
        }
565
566 44
        $namespace = $node->lookupNamespaceURI($prefix ?: null);
567
        return array(
568 44
            $name,
569 44
            $namespace,
570
            $prefix
571 44
        );
572
    }
573
574
    /**
575
     *
576
     * @param string $finder
577
     * @param Schema $schema
578
     * @param DOMElement $node
579
     * @param string $typeName
580
     * @throws TypeException
581
     * @return ElementItem|Group|AttributeItem|AttribiuteGroup|Type
582
     */
583 44
    private function findSomething($finder, Schema $schema, DOMElement $node, $typeName)
584
    {
585 44
        list ($name, $namespace) = self::splitParts($node, $typeName);
586
587 44
        $namespace = $namespace ?: $schema->getTargetNamespace();
588
589
        try {
590 44
            return $schema->$finder($name, $namespace);
591
        } catch (TypeNotFoundException $e) {
592
            throw new TypeException(sprintf("Can't find %s named {%s}#%s, at line %d in %s ", strtolower(substr($finder, 4)), $namespace, $name, $node->getLineNo(), $node->ownerDocument->documentURI), 0, $e);
593
        }
594
    }
595
596 44 View Code Duplication
    private function loadElementDef(Schema $schema, DOMElement $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
597
    {
598 44
        $element = new ElementDef($schema, $node->getAttribute("name"));
599 44
        $schema->addElement($element);
600
601
        return function () use ($element, $node) {
602 44
            $this->fillItem($element, $node);
603 44
        };
604
    }
605
606 44
    private function fillItem(Item $element, DOMElement $node)
607
    {
608 44
        $localType = null;
609 44
        foreach ($node->childNodes as $childNode) {
610 44
            switch ($childNode->localName) {
611 44
                case 'complexType':
612 44
                case 'simpleType':
613 44
                    $localType = $childNode;
614 44
                    break 2;
615 44
            }
616 44
        }
617
618 44
        if ($localType) {
619
            $addCallback = function ($type) use ($element) {
620 44
                $element->setType($type);
621 44
            };
622 44
            switch ($localType->localName) {
623 44
                case 'complexType':
624 44
                    call_user_func($this->loadComplexType($element->getSchema(), $localType, $addCallback));
625 44
                    break;
626 44
                case 'simpleType':
627 44
                    call_user_func($this->loadSimpleType($element->getSchema(), $localType, $addCallback));
628 44
                    break;
629 44
            }
630 44
        } else {
631
632 44
            if ($node->getAttribute("type")) {
633 44
                $type = $this->findSomething('findType', $element->getSchema(), $node, $node->getAttribute("type"));
634 44
            } else {
635 44
                $type = $this->findSomething('findType', $element->getSchema(), $node, ($node->lookupPrefix(self::XSD_NS) . ":anyType"));
636
            }
637
638 44
            $element->setType($type);
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type object<GoetasWebservices...ma\Element\ElementItem>; however, GoetasWebservices\XML\XS...\Schema\Item::setType() does only seem to accept object<GoetasWebservices...eader\Schema\Type\Type>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
639
        }
640 44
    }
641
642 44
    private function loadImport(Schema $schema, DOMElement $node)
643
    {
644 44
        $base = urldecode($node->ownerDocument->documentURI);
645 44
        $file = UrlUtils::resolveRelativeUrl($base, $node->getAttribute("schemaLocation"));
646 44
        if ($node->hasAttribute("namespace")
647 44
            && isset(self::$globalSchemaInfo[$node->getAttribute("namespace")])
648 44
            && isset($this->loadedFiles[self::$globalSchemaInfo[$node->getAttribute("namespace")]])
649 44
        ) {
650
651 44
            $schema->addSchema($this->loadedFiles[self::$globalSchemaInfo[$node->getAttribute("namespace")]]);
652
653
            return function () {
654 44
            };
655 3
        } elseif ($node->hasAttribute("namespace")
656 3
            && isset($this->loadedFiles[$this->getNamespaceSpecificFileIndex($file, $node->getAttribute("namespace"))])) {
657 2
            $schema->addSchema($this->loadedFiles[$this->getNamespaceSpecificFileIndex($file, $node->getAttribute("namespace"))]);
658
            return function () {
659 2
            };
660 1
        } elseif (isset($this->loadedFiles[$file])) {
661
            $schema->addSchema($this->loadedFiles[$file]);
662
            return function () {
663
            };
664
        }
665
666 1
        if (!$node->getAttribute("namespace")) {
667 1
            $this->loadedFiles[$file] = $newSchema = $schema;
668 1
        } else {
669
            $this->loadedFiles[$file] = $newSchema = new Schema();
670
            $newSchema->addSchema($this->getGlobalSchema());
671
        }
672
673 1
        $xml = $this->getDOM(isset($this->knownLocationSchemas[$file]) ? $this->knownLocationSchemas[$file] : $file);
674
675 1
        $callbacks = $this->schemaNode($newSchema, $xml->documentElement, $schema);
676
677 1
        if ($node->getAttribute("namespace")) {
678
            $schema->addSchema($newSchema);
679
        }
680
681
682 1
        return function () use ($callbacks) {
683 1
            foreach ($callbacks as $callback) {
684 1
                call_user_func($callback);
685 1
            }
686 1
        };
687
    }
688
689
    private $globalSchema;
690
691
    /**
692
     *
693
     * @return Schema
694
     */
695 44
    public function getGlobalSchema()
696
    {
697 44
        if (!$this->globalSchema) {
698 44
            $callbacks = array();
699 44
            $globalSchemas = array();
700 44
            foreach (self::$globalSchemaInfo as $namespace => $uri) {
701 44
                $this->loadedFiles[$uri] = $globalSchemas [$namespace] = $schema = new Schema();
702 44
                if ($namespace === self::XSD_NS) {
703 44
                    $this->globalSchema = $schema;
704 44
                }
705 44
                $xml = $this->getDOM($this->knownLocationSchemas[$uri]);
706 44
                $callbacks = array_merge($callbacks, $this->schemaNode($schema, $xml->documentElement));
707 44
            }
708
709 44
            $globalSchemas[self::XSD_NS]->addType(new SimpleType($globalSchemas[self::XSD_NS], "anySimpleType"));
710 44
            $globalSchemas[self::XSD_NS]->addType(new SimpleType($globalSchemas[self::XSD_NS], "anyType"));
711
712 44
            $globalSchemas[self::XML_NS]->addSchema($globalSchemas[self::XSD_NS], self::XSD_NS);
713 44
            $globalSchemas[self::XSD_NS]->addSchema($globalSchemas[self::XML_NS], self::XML_NS);
714
715 44
            foreach ($callbacks as $callback) {
716 44
                $callback();
717 44
            }
718 44
        }
719 44
        return $this->globalSchema;
720
    }
721
722
    /**
723
     * @param DOMNode $node
724
     * @param string  $file
725
     * 
726
     * @return Schema
727
     */
728 44
    public function readNode(DOMNode $node, $file = 'schema.xsd')
729
    {
730 44
        $fileKey = $node instanceof DOMElement && $node->hasAttribute('targetNamespace') ? $this->getNamespaceSpecificFileIndex($file, $node->getAttribute('targetNamespace')) : $file;
731 44
        $this->loadedFiles[$fileKey] = $rootSchema = new Schema();
732
733 44
        $rootSchema->addSchema($this->getGlobalSchema());
734 44
        $callbacks = $this->schemaNode($rootSchema, $node);
0 ignored issues
show
Compatibility introduced by
$node of type object<DOMNode> is not a sub-type of object<DOMElement>. It seems like you assume a child class of the class DOMNode to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
735
736 44
        foreach ($callbacks as $callback) {
737 38
            call_user_func($callback);
738 44
        }
739
740 44
        return $rootSchema;
741
    }
742
743
    /**
744
     * It is possible that a single file contains multiple <xsd:schema/> nodes, for instance in a WSDL file.
745
     *
746
     * Each of these  <xsd:schema/> nodes typically target a specific namespace. Append the target namespace to the
747
     * file to distinguish between multiple schemas in a single file.
748
     *
749
     * @param string $file
750
     * @param string $targetNamespace
751
     *
752
     * @return string
753
     */
754 44
    private function getNamespaceSpecificFileIndex($file, $targetNamespace)
755
    {
756 44
        return $file . '#' . $targetNamespace;
757
    }
758
759
    /**
760
     * @param string $content
761
     * @param string $file
762
     *
763
     * @return Schema
764
     *
765
     * @throws IOException
766
     */
767 43
    public function readString($content, $file = 'schema.xsd')
768
    {
769 43
        $xml = new DOMDocument('1.0', 'UTF-8');
770 43
        if (!$xml->loadXML($content)) {
771
            throw new IOException("Can't load the schema");
772
        }
773 43
        $xml->documentURI = $file;
774
775 43
        return $this->readNode($xml->documentElement, $file);
776
    }
777
778
    /**
779
     * @param string $file
780
     *
781
     * @return Schema
782
     */
783 1
    public function readFile($file)
784
    {
785 1
        $xml = $this->getDOM($file);
786 1
        return $this->readNode($xml->documentElement, $file);
787
    }
788
789
    /**
790
     * @param string $file
791
     *
792
     * @return DOMDocument
793
     *
794
     * @throws IOException
795
     */
796 44
    private function getDOM($file)
797
    {
798 44
        $xml = new DOMDocument('1.0', 'UTF-8');
799 44
        if (!$xml->load($file)) {
800
            throw new IOException("Can't load the file $file");
801
        }
802 44
        return $xml;
803
    }
804
}
805