This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace Goetas\XML\XSDReader; |
||
3 | |||
4 | use DOMDocument; |
||
5 | use DOMElement; |
||
6 | use Goetas\XML\XSDReader\Utils\UrlUtils; |
||
7 | use Goetas\XML\XSDReader\Schema\Schema; |
||
8 | use Goetas\XML\XSDReader\Schema\Element\Element; |
||
9 | use Goetas\XML\XSDReader\Schema\Attribute\Attribute; |
||
10 | use Goetas\XML\XSDReader\Schema\Type\ComplexType; |
||
11 | use Goetas\XML\XSDReader\Schema\Type\SimpleType; |
||
12 | use Goetas\XML\XSDReader\Schema\Type\Type; |
||
13 | use Goetas\XML\XSDReader\Schema\Type\BaseComplexType; |
||
14 | use Goetas\XML\XSDReader\Schema\Item; |
||
15 | use Goetas\XML\XSDReader\Exception\TypeException; |
||
16 | use Goetas\XML\XSDReader\Exception\IOException; |
||
17 | use Goetas\XML\XSDReader\Schema\Attribute\Group as AttributeGroup; |
||
18 | use Goetas\XML\XSDReader\Schema\Element\Group; |
||
19 | use Goetas\XML\XSDReader\Schema\Element\ElementContainer; |
||
20 | use Goetas\XML\XSDReader\Schema\Type\ComplexTypeSimpleContent; |
||
21 | use Goetas\XML\XSDReader\Schema\Element\ElementDef; |
||
22 | use Goetas\XML\XSDReader\Schema\Inheritance\Restriction; |
||
23 | use Goetas\XML\XSDReader\Schema\Inheritance\Extension; |
||
24 | use Goetas\XML\XSDReader\Schema\Exception\TypeNotFoundException; |
||
25 | use Goetas\XML\XSDReader\Schema\Element\ElementRef; |
||
26 | use Goetas\XML\XSDReader\Schema\Attribute\AttributeRef; |
||
27 | use Goetas\XML\XSDReader\Schema\Element\ElementItem; |
||
28 | use Goetas\XML\XSDReader\Schema\Attribute\AttributeDef; |
||
29 | use Goetas\XML\XSDReader\Schema\Element\GroupRef; |
||
30 | |||
31 | class SchemaReader |
||
32 | { |
||
33 | |||
34 | const XSD_NS = "http://www.w3.org/2001/XMLSchema"; |
||
35 | |||
36 | const XML_NS = "http://www.w3.org/XML/1998/namespace"; |
||
37 | |||
38 | private $loadedFiles = array(); |
||
39 | |||
40 | private $knowLocationSchemas = array(); |
||
41 | |||
42 | private static $globalSchemaInfo = array( |
||
43 | self::XML_NS => 'http://www.w3.org/2001/xml.xsd', |
||
44 | self::XSD_NS => 'http://www.w3.org/2001/XMLSchema.xsd' |
||
45 | ); |
||
46 | |||
47 | public function __construct() |
||
48 | { |
||
49 | $this->addKnownSchemaLocation('http://www.w3.org/2001/xml.xsd', __DIR__ . '/Resources/xml.xsd'); |
||
50 | $this->addKnownSchemaLocation('http://www.w3.org/2001/XMLSchema.xsd', __DIR__ . '/Resources/XMLSchema.xsd'); |
||
51 | } |
||
52 | |||
53 | public function addKnownSchemaLocation($remote, $local) |
||
54 | { |
||
55 | $this->knowLocationSchemas[$remote] = $local; |
||
56 | } |
||
57 | |||
58 | private function loadAttributeGroup(Schema $schema, DOMElement $node) |
||
59 | { |
||
60 | $attGroup = new AttributeGroup($schema, $node->getAttribute("name")); |
||
61 | $attGroup->setDoc($this->getDocumentation($node)); |
||
62 | $schema->addAttributeGroup($attGroup); |
||
63 | |||
64 | return function () use($schema, $node, $attGroup) |
||
65 | { |
||
66 | foreach ($node->childNodes as $childNode) { |
||
67 | switch ($childNode->localName) { |
||
68 | case 'attribute': |
||
69 | if ($childNode->hasAttribute("ref")) { |
||
70 | $attribute = $this->findSomething('findAttribute', $schema, $node, $childNode->getAttribute("ref")); |
||
71 | } else { |
||
72 | $attribute = $this->loadAttribute($schema, $childNode); |
||
73 | } |
||
74 | $attGroup->addAttribute($attribute); |
||
75 | break; |
||
76 | case 'attributeGroup': |
||
77 | |||
78 | $attribute = $this->findSomething('findAttributeGroup', $schema, $node, $childNode->getAttribute("ref")); |
||
79 | $attGroup->addAttribute($attribute); |
||
80 | break; |
||
81 | } |
||
82 | } |
||
83 | }; |
||
84 | } |
||
85 | |||
86 | private function loadAttribute(Schema $schema, DOMElement $node) |
||
87 | { |
||
88 | $attribute = new Attribute($schema, $node->getAttribute("name")); |
||
89 | $attribute->setDoc($this->getDocumentation($node)); |
||
90 | $this->fillItem($attribute, $node); |
||
91 | |||
92 | if ($node->hasAttribute("nillable")) { |
||
93 | $attribute->setNil($node->getAttribute("nillable") == "true"); |
||
94 | } |
||
95 | if ($node->hasAttribute("form")) { |
||
96 | $attribute->setQualified($node->getAttribute("form") == "qualified"); |
||
97 | } |
||
98 | if ($node->hasAttribute("use")) { |
||
99 | $attribute->setUse($node->getAttribute("use")); |
||
100 | } |
||
101 | return $attribute; |
||
102 | } |
||
103 | |||
104 | |||
105 | private function loadAttributeDef(Schema $schema, DOMElement $node) |
||
106 | { |
||
107 | $attribute = new AttributeDef($schema, $node->getAttribute("name")); |
||
108 | |||
109 | $schema->addAttribute($attribute); |
||
110 | |||
111 | return function () use($attribute, $schema, $node) |
||
112 | { |
||
113 | $this->fillItem($attribute, $node); |
||
114 | }; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * @param DOMElement $node |
||
119 | * @return string |
||
120 | */ |
||
121 | private function getDocumentation(DOMElement $node) |
||
122 | { |
||
123 | $doc = ''; |
||
124 | foreach ($node->childNodes as $childNode) { |
||
125 | if ($childNode->localName == "annotation") { |
||
126 | foreach ($childNode->childNodes as $subChildNode) { |
||
127 | if ($subChildNode->localName == "documentation") { |
||
128 | $doc .= ($subChildNode->nodeValue); |
||
129 | } |
||
130 | } |
||
131 | } |
||
132 | } |
||
133 | $doc = preg_replace('/[\t ]+/', ' ', $doc); |
||
134 | return trim($doc); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * |
||
139 | * @param Schema $schema |
||
140 | * @param DOMElement $node |
||
141 | * @param Schema $parent |
||
142 | * @return array |
||
143 | */ |
||
144 | private function schemaNode(Schema $schema, DOMElement $node, Schema $parent = null) |
||
145 | { |
||
146 | $schema->setDoc($this->getDocumentation($node)); |
||
147 | |||
148 | if ($node->hasAttribute("targetNamespace")) { |
||
149 | $schema->setTargetNamespace($node->getAttribute("targetNamespace")); |
||
150 | } elseif ($parent) { |
||
151 | $schema->setTargetNamespace($parent->getTargetNamespace()); |
||
152 | } |
||
153 | $schema->setElementsQualification(! $node->hasAttribute("elementFormDefault") || $node->getAttribute("elementFormDefault") == "qualified"); |
||
154 | $schema->setAttributesQualification(! $node->hasAttribute("attributeFormDefault") || $node->getAttribute("attributeFormDefault") == "qualified"); |
||
155 | $schema->setDoc($this->getDocumentation($node)); |
||
156 | $functions = array(); |
||
157 | |||
158 | foreach ($node->childNodes as $childNode) { |
||
159 | switch ($childNode->localName) { |
||
160 | case 'include': |
||
161 | case 'import': |
||
162 | $functions[] = $this->loadImport($schema, $childNode); |
||
163 | break; |
||
164 | case 'element': |
||
165 | $functions[] = $this->loadElementDef($schema, $childNode); |
||
166 | break; |
||
167 | case 'attribute': |
||
168 | $functions[] = $this->loadAttributeDef($schema, $childNode); |
||
169 | break; |
||
170 | case 'attributeGroup': |
||
171 | $functions[] = $this->loadAttributeGroup($schema, $childNode); |
||
172 | break; |
||
173 | case 'group': |
||
174 | $functions[] = $this->loadGroup($schema, $childNode); |
||
175 | break; |
||
176 | case 'complexType': |
||
177 | $functions[] = $this->loadComplexType($schema, $childNode); |
||
178 | break; |
||
179 | case 'simpleType': |
||
180 | $functions[] = $this->loadSimpleType($schema, $childNode); |
||
181 | break; |
||
182 | } |
||
183 | } |
||
184 | |||
185 | return $functions; |
||
186 | } |
||
187 | |||
188 | private function loadElement(Schema $schema, DOMElement $node) |
||
189 | { |
||
190 | $element = new Element($schema, $node->getAttribute("name")); |
||
191 | $element->setDoc($this->getDocumentation($node)); |
||
192 | |||
193 | $this->fillItem($element, $node); |
||
194 | |||
195 | if ($node->hasAttribute("maxOccurs")) { |
||
196 | $element->setMax($node->getAttribute("maxOccurs") == "unbounded" ? - 1 : (int)$node->getAttribute("maxOccurs")); |
||
197 | } |
||
198 | if ($node->hasAttribute("minOccurs")) { |
||
199 | $element->setMin((int)$node->getAttribute("minOccurs")); |
||
200 | } |
||
201 | if ($node->hasAttribute("nillable")) { |
||
202 | $element->setNil($node->getAttribute("nillable") == "true"); |
||
203 | } |
||
204 | if ($node->hasAttribute("form")) { |
||
205 | $element->setQualified($node->getAttribute("form") == "qualified"); |
||
206 | } |
||
207 | return $element; |
||
208 | } |
||
209 | |||
210 | private function loadGroupRef(Group $referenced, DOMElement $node) |
||
211 | { |
||
212 | $ref = new GroupRef($referenced); |
||
213 | $ref->setDoc($this->getDocumentation($node)); |
||
214 | |||
215 | if ($node->hasAttribute("maxOccurs")) { |
||
216 | $ref->setMax($node->getAttribute("maxOccurs") == "unbounded" ? - 1 : (int)$node->getAttribute("maxOccurs")); |
||
217 | } |
||
218 | if ($node->hasAttribute("minOccurs")) { |
||
219 | $ref->setMin((int)$node->getAttribute("minOccurs")); |
||
220 | } |
||
221 | |||
222 | return $ref; |
||
223 | } |
||
224 | |||
225 | private function loadElementRef(ElementDef $referenced, DOMElement $node) |
||
226 | { |
||
227 | $ref = new ElementRef($referenced); |
||
228 | $ref->setDoc($this->getDocumentation($node)); |
||
229 | |||
230 | if ($node->hasAttribute("maxOccurs")) { |
||
231 | $ref->setMax($node->getAttribute("maxOccurs") == "unbounded" ? - 1 : (int)$node->getAttribute("maxOccurs")); |
||
232 | } |
||
233 | if ($node->hasAttribute("minOccurs")) { |
||
234 | $ref->setMin((int)$node->getAttribute("minOccurs")); |
||
235 | } |
||
236 | if ($node->hasAttribute("nillable")) { |
||
237 | $ref->setNil($node->getAttribute("nillable") == "true"); |
||
238 | } |
||
239 | if ($node->hasAttribute("form")) { |
||
240 | $ref->setQualified($node->getAttribute("form") == "qualified"); |
||
241 | } |
||
242 | |||
243 | return $ref; |
||
244 | } |
||
245 | |||
246 | |||
247 | private function loadAttributeRef(AttributeDef $referencedAttribiute, DOMElement $node) |
||
248 | { |
||
249 | $attribute = new AttributeRef($referencedAttribiute); |
||
250 | $attribute->setDoc($this->getDocumentation($node)); |
||
251 | |||
252 | if ($node->hasAttribute("nillable")) { |
||
253 | $attribute->setNil($node->getAttribute("nillable") == "true"); |
||
254 | } |
||
255 | if ($node->hasAttribute("form")) { |
||
256 | $attribute->setQualified($node->getAttribute("form") == "qualified"); |
||
257 | } |
||
258 | if ($node->hasAttribute("use")) { |
||
259 | $attribute->setUse($node->getAttribute("use")); |
||
260 | } |
||
261 | return $attribute; |
||
262 | } |
||
263 | |||
264 | private function loadSequence(ElementContainer $elementContainer, DOMElement $node, $max = null) |
||
265 | { |
||
266 | $max = $max || $node->getAttribute("maxOccurs")=="unbounded" || $node->getAttribute("maxOccurs")>1 ? 2 :null; |
||
267 | |||
268 | foreach ($node->childNodes as $childNode) { |
||
269 | |||
270 | switch ($childNode->localName) { |
||
271 | case 'choice': |
||
272 | case 'sequence': |
||
273 | case 'all': |
||
274 | $this->loadSequence($elementContainer, $childNode, $max); |
||
275 | break; |
||
276 | case 'element': |
||
277 | if ($childNode->hasAttribute("ref")) { |
||
278 | $referencedElement = $this->findSomething('findElement', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref")); |
||
279 | $element = $this->loadElementRef($referencedElement, $childNode); |
||
280 | } else { |
||
281 | $element = $this->loadElement($elementContainer->getSchema(), $childNode); |
||
282 | } |
||
283 | if ($max) { |
||
284 | $element->setMax($max); |
||
285 | } |
||
286 | $elementContainer->addElement($element); |
||
287 | break; |
||
288 | case 'group': |
||
289 | $referencedGroup = $this->findSomething('findGroup', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref")); |
||
290 | |||
291 | $group = $this->loadGroupRef($referencedGroup, $childNode); |
||
292 | $elementContainer->addElement($group); |
||
293 | break; |
||
294 | } |
||
295 | } |
||
296 | } |
||
297 | |||
298 | private function loadGroup(Schema $schema, DOMElement $node) |
||
299 | { |
||
300 | $group = new Group($schema, $node->getAttribute("name")); |
||
301 | $group->setDoc($this->getDocumentation($node)); |
||
302 | |||
303 | if ($node->hasAttribute("maxOccurs")) { |
||
304 | $group->setMax($node->getAttribute("maxOccurs") == "unbounded" ? - 1 : (int)$node->getAttribute("maxOccurs")); |
||
305 | } |
||
306 | if ($node->hasAttribute("minOccurs")) { |
||
307 | $group->setMin((int)$node->getAttribute("minOccurs")); |
||
308 | } |
||
309 | |||
310 | $schema->addGroup($group); |
||
311 | |||
312 | return function () use($group, $node) |
||
313 | { |
||
314 | foreach ($node->childNodes as $childNode) { |
||
315 | switch ($childNode->localName) { |
||
316 | case 'sequence': |
||
317 | case 'choice': |
||
318 | case 'all': |
||
319 | $this->loadSequence($group, $childNode); |
||
320 | break; |
||
321 | } |
||
322 | } |
||
323 | }; |
||
324 | } |
||
325 | |||
326 | private function loadComplexType(Schema $schema, DOMElement $node, $callback = null) |
||
327 | { |
||
328 | $isSimple = false; |
||
329 | |||
330 | foreach ($node->childNodes as $childNode) { |
||
331 | if ($childNode->localName === "simpleContent") { |
||
332 | $isSimple = true; |
||
333 | break; |
||
334 | } |
||
335 | } |
||
336 | |||
337 | $type = $isSimple ? new ComplexTypeSimpleContent($schema, $node->getAttribute("name")) : new ComplexType($schema, $node->getAttribute("name")); |
||
338 | |||
339 | $type->setDoc($this->getDocumentation($node)); |
||
340 | if ($node->getAttribute("name")) { |
||
341 | $schema->addType($type); |
||
342 | } |
||
343 | |||
344 | return function () use($type, $node, $schema, $callback) |
||
345 | { |
||
346 | |||
347 | $this->fillTypeNode($type, $node); |
||
348 | |||
349 | foreach ($node->childNodes as $childNode) { |
||
350 | switch ($childNode->localName) { |
||
351 | case 'sequence': |
||
352 | case 'choice': |
||
353 | case 'all': |
||
354 | $this->loadSequence($type, $childNode); |
||
355 | break; |
||
356 | case 'attribute': |
||
357 | if ($childNode->hasAttribute("ref")) { |
||
358 | $referencedAttribute = $this->findSomething('findAttribute', $schema, $node, $childNode->getAttribute("ref")); |
||
359 | $attribute = $this->loadAttributeRef($referencedAttribute, $childNode); |
||
360 | } else { |
||
361 | $attribute = $this->loadAttribute($schema, $childNode); |
||
362 | } |
||
363 | |||
364 | $type->addAttribute($attribute); |
||
365 | break; |
||
366 | case 'attributeGroup': |
||
367 | $attribute = $this->findSomething('findAttributeGroup', $schema, $node, $childNode->getAttribute("ref")); |
||
368 | $type->addAttribute($attribute); |
||
369 | break; |
||
370 | } |
||
371 | } |
||
372 | |||
373 | if ($callback) { |
||
374 | call_user_func($callback, $type); |
||
375 | } |
||
376 | }; |
||
377 | } |
||
378 | |||
379 | private function loadSimpleType(Schema $schema, DOMElement $node, $callback = null) |
||
380 | { |
||
381 | $type = new SimpleType($schema, $node->getAttribute("name")); |
||
382 | $type->setDoc($this->getDocumentation($node)); |
||
383 | if ($node->getAttribute("name")) { |
||
384 | $schema->addType($type); |
||
385 | } |
||
386 | |||
387 | return function () use($type, $node, $callback) |
||
388 | { |
||
389 | $this->fillTypeNode($type, $node); |
||
390 | |||
391 | foreach ($node->childNodes as $childNode) { |
||
392 | switch ($childNode->localName) { |
||
393 | case 'union': |
||
394 | $this->loadUnion($type, $childNode); |
||
395 | break; |
||
396 | case 'list': |
||
397 | $this->loadList($type, $childNode); |
||
398 | break; |
||
399 | } |
||
400 | } |
||
401 | |||
402 | if ($callback) { |
||
403 | call_user_func($callback, $type); |
||
404 | } |
||
405 | }; |
||
406 | } |
||
407 | |||
408 | private function loadList(SimpleType $type, DOMElement $node) |
||
409 | { |
||
410 | if ($node->hasAttribute("itemType")) { |
||
411 | $type->setList($this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("itemType"))); |
||
412 | }else{ |
||
413 | $addCallback = function ($list) use($type) |
||
414 | { |
||
415 | $type->setList($list); |
||
416 | }; |
||
417 | |||
418 | foreach ($node->childNodes as $childNode) { |
||
419 | switch ($childNode->localName) { |
||
420 | case 'simpleType': |
||
421 | call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback)); |
||
422 | break; |
||
423 | } |
||
424 | } |
||
425 | } |
||
426 | } |
||
427 | |||
428 | private function loadUnion(SimpleType $type, DOMElement $node) |
||
429 | { |
||
430 | if ($node->hasAttribute("memberTypes")) { |
||
431 | $types = preg_split('/\s+/', $node->getAttribute("memberTypes")); |
||
432 | foreach ($types as $typeName) { |
||
433 | $type->addUnion($this->findSomething('findType', $type->getSchema(), $node, $typeName)); |
||
434 | } |
||
435 | } |
||
436 | $addCallback = function ($unType) use($type) |
||
437 | { |
||
438 | $type->addUnion($unType); |
||
439 | }; |
||
440 | |||
441 | foreach ($node->childNodes as $childNode) { |
||
442 | switch ($childNode->localName) { |
||
443 | case 'simpleType': |
||
444 | call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback)); |
||
445 | break; |
||
446 | } |
||
447 | } |
||
448 | } |
||
449 | |||
450 | private function fillTypeNode(Type $type, DOMElement $node, $checkAbstract = true) |
||
451 | { |
||
452 | |||
453 | if($checkAbstract){ |
||
454 | $type->setAbstract($node->getAttribute("abstract")==="true" || $node->getAttribute("abstract")==="1"); |
||
455 | } |
||
456 | |||
457 | foreach ($node->childNodes as $childNode) { |
||
458 | switch ($childNode->localName) { |
||
459 | case 'restriction': |
||
460 | $this->loadRestriction($type, $childNode); |
||
461 | break; |
||
462 | case 'extension': |
||
463 | $this->loadExtension($type, $childNode); |
||
0 ignored issues
–
show
|
|||
464 | break; |
||
465 | case 'simpleContent': |
||
466 | case 'complexContent': |
||
467 | $this->fillTypeNode($type, $childNode, false); |
||
468 | break; |
||
469 | } |
||
470 | } |
||
471 | } |
||
472 | |||
473 | private function loadExtension(BaseComplexType $type, DOMElement $node) |
||
474 | { |
||
475 | $extension = new Extension(); |
||
476 | $type->setExtension($extension); |
||
477 | |||
478 | if ($node->hasAttribute("base")) { |
||
479 | $parent = $this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("base")); |
||
480 | $extension->setBase($parent); |
||
481 | } |
||
482 | |||
483 | foreach ($node->childNodes as $childNode) { |
||
484 | switch ($childNode->localName) { |
||
485 | case 'sequence': |
||
486 | case 'choice': |
||
487 | case 'all': |
||
488 | $this->loadSequence($type, $childNode); |
||
489 | break; |
||
490 | case 'attribute': |
||
491 | if ($childNode->hasAttribute("ref")) { |
||
492 | $attribute = $this->findSomething('findAttribute', $type->getSchema(), $node, $childNode->getAttribute("ref")); |
||
493 | } else { |
||
494 | $attribute = $this->loadAttribute($type->getSchema(), $childNode); |
||
495 | } |
||
496 | $type->addAttribute($attribute); |
||
497 | break; |
||
498 | case 'attributeGroup': |
||
499 | $attribute = $this->findSomething('findAttributeGroup', $type->getSchema(), $node, $childNode->getAttribute("ref")); |
||
500 | $type->addAttribute($attribute); |
||
501 | break; |
||
502 | } |
||
503 | } |
||
504 | } |
||
505 | |||
506 | private function loadRestriction(Type $type, DOMElement $node) |
||
507 | { |
||
508 | $restriction = new Restriction(); |
||
509 | $type->setRestriction($restriction); |
||
510 | if ($node->hasAttribute("base")) { |
||
511 | $restrictedType = $this->findSomething('findType', $type->getSchema(), $node, $node->getAttribute("base")); |
||
512 | $restriction->setBase($restrictedType); |
||
513 | } else { |
||
514 | $addCallback = function ($restType) use($restriction) |
||
515 | { |
||
516 | $restriction->setBase($restType); |
||
517 | }; |
||
518 | |||
519 | foreach ($node->childNodes as $childNode) { |
||
520 | switch ($childNode->localName) { |
||
521 | case 'simpleType': |
||
522 | call_user_func($this->loadSimpleType($type->getSchema(), $childNode, $addCallback)); |
||
523 | break; |
||
524 | } |
||
525 | } |
||
526 | } |
||
527 | foreach ($node->childNodes as $childNode) { |
||
528 | if (in_array($childNode->localName, |
||
529 | [ |
||
530 | 'enumeration', |
||
531 | 'pattern', |
||
532 | 'length', |
||
533 | 'minLength', |
||
534 | 'maxLength', |
||
535 | 'minInclusive', |
||
536 | 'maxInclusive', |
||
537 | 'minExclusive', |
||
538 | 'maxExclusive' |
||
539 | ], true)) { |
||
540 | $restriction->addCheck($childNode->localName, |
||
541 | [ |
||
542 | 'value' => $childNode->getAttribute("value"), |
||
543 | 'doc' => $this->getDocumentation($childNode) |
||
544 | ]); |
||
545 | } |
||
546 | } |
||
547 | } |
||
548 | |||
549 | private static function splitParts(DOMElement $node, $typeName) |
||
550 | { |
||
551 | $namespace = null; |
||
552 | $prefix = null; |
||
553 | $name = $typeName; |
||
554 | if (strpos($typeName, ':') !== false) { |
||
555 | list ($prefix, $name) = explode(':', $typeName); |
||
556 | } |
||
557 | |||
558 | $namespace = $node->lookupNamespaceURI($prefix ?: null); |
||
559 | return array( |
||
560 | $name, |
||
561 | $namespace, |
||
562 | $prefix |
||
563 | ); |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * |
||
568 | * @param string $finder |
||
569 | * @param Schema $schema |
||
570 | * @param DOMElement $node |
||
571 | * @param string $typeName |
||
572 | * @throws TypeException |
||
573 | * @return ElementItem|Group|AttributeItem|AttribiuteGroup|Type |
||
574 | */ |
||
575 | private function findSomething($finder, Schema $schema, DOMElement $node, $typeName) |
||
576 | { |
||
577 | list ($name, $namespace) = self::splitParts($node, $typeName); |
||
578 | |||
579 | $namespace = $namespace ?: $schema->getTargetNamespace(); |
||
580 | |||
581 | try { |
||
582 | return $schema->$finder($name, $namespace); |
||
583 | } catch (TypeNotFoundException $e) { |
||
584 | 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); |
||
585 | } |
||
586 | } |
||
587 | |||
588 | private function loadElementDef(Schema $schema, DOMElement $node) |
||
589 | { |
||
590 | $element = new ElementDef($schema, $node->getAttribute("name")); |
||
591 | $schema->addElement($element); |
||
592 | |||
593 | return function () use ($element, $node) { |
||
594 | $this->fillItem($element, $node); |
||
595 | }; |
||
596 | } |
||
597 | |||
598 | private function fillItem(Item $element, DOMElement $node) |
||
599 | { |
||
600 | $localType = null; |
||
601 | foreach ($node->childNodes as $childNode) { |
||
602 | switch ($childNode->localName) { |
||
603 | case 'complexType': |
||
604 | case 'simpleType': |
||
605 | $localType = $childNode; |
||
606 | break 2; |
||
607 | } |
||
608 | } |
||
609 | |||
610 | if ($localType) { |
||
611 | $addCallback = function ($type) use($element) { |
||
612 | $element->setType($type); |
||
613 | }; |
||
614 | switch ($localType->localName) { |
||
615 | case 'complexType': |
||
616 | call_user_func($this->loadComplexType($element->getSchema(), $localType, $addCallback)); |
||
617 | break; |
||
618 | case 'simpleType': |
||
619 | call_user_func($this->loadSimpleType($element->getSchema(), $localType, $addCallback)); |
||
620 | break; |
||
621 | } |
||
622 | } else { |
||
623 | |||
624 | if ($node->getAttribute("type")) { |
||
625 | $type = $this->findSomething('findType', $element->getSchema(), $node, $node->getAttribute("type")); |
||
626 | } else { |
||
627 | $type = $this->findSomething('findType', $element->getSchema(), $node, ($node->lookupPrefix(self::XSD_NS).":anyType")); |
||
628 | } |
||
629 | |||
630 | $element->setType($type); |
||
631 | } |
||
632 | } |
||
633 | |||
634 | private function loadImport(Schema $schema, DOMElement $node) |
||
635 | { |
||
636 | $base = urldecode($node->ownerDocument->documentURI); |
||
637 | $file = UrlUtils::resolveRelativeUrl($base, $node->getAttribute("schemaLocation")); |
||
638 | if ($node->hasAttribute("namespace") |
||
639 | && isset(self::$globalSchemaInfo[$node->getAttribute("namespace")]) |
||
640 | && isset($this->loadedFiles[self::$globalSchemaInfo[$node->getAttribute("namespace")]]) |
||
641 | ){ |
||
642 | |||
643 | $schema->addSchema($this->loadedFiles[self::$globalSchemaInfo[$node->getAttribute("namespace")]]); |
||
644 | |||
645 | return function () |
||
646 | { |
||
647 | }; |
||
648 | }elseif (isset($this->loadedFiles[$file])) { |
||
649 | $schema->addSchema($this->loadedFiles[$file]); |
||
650 | return function () { |
||
651 | }; |
||
652 | } |
||
653 | |||
654 | if (!$node->getAttribute("namespace")){ |
||
655 | $this->loadedFiles[$file] = $newSchema = $schema; |
||
656 | }else{ |
||
657 | $this->loadedFiles[$file] = $newSchema = new Schema(); |
||
658 | $newSchema->addSchema($this->getGlobalSchema()); |
||
659 | } |
||
660 | |||
661 | $xml = $this->getDOM(isset($this->knowLocationSchemas[$file])?$this->knowLocationSchemas[$file]:$file); |
||
662 | |||
663 | $callbacks = $this->schemaNode($newSchema, $xml->documentElement, $schema); |
||
664 | |||
665 | if ($node->getAttribute("namespace")){ |
||
666 | $schema->addSchema($newSchema); |
||
667 | } |
||
668 | |||
669 | |||
670 | return function () use($callbacks) |
||
671 | { |
||
672 | foreach ($callbacks as $callback) { |
||
673 | call_user_func($callback); |
||
674 | } |
||
675 | }; |
||
676 | } |
||
677 | |||
678 | private $globalSchema; |
||
679 | |||
680 | /** |
||
681 | * |
||
682 | * @return \Goetas\XML\XSDReader\Schema\Schema |
||
683 | */ |
||
684 | public function getGlobalSchema() |
||
685 | { |
||
686 | if (! $this->globalSchema) { |
||
687 | $callbacks = array(); |
||
688 | $globalSchemas = array(); |
||
689 | foreach (self::$globalSchemaInfo as $namespace => $uri) { |
||
690 | $this->loadedFiles[$uri] = $globalSchemas [$namespace] = $schema = new Schema(); |
||
691 | if($namespace === self::XSD_NS){ |
||
692 | $this->globalSchema = $schema; |
||
693 | } |
||
694 | $xml = $this->getDOM($this->knowLocationSchemas[$uri]); |
||
695 | $callbacks = array_merge($callbacks, $this->schemaNode($schema, $xml->documentElement)); |
||
696 | } |
||
697 | |||
698 | $globalSchemas[self::XSD_NS]->addType(new SimpleType($globalSchemas[self::XSD_NS], "anySimpleType")); |
||
699 | $globalSchemas[self::XSD_NS]->addType(new SimpleType($globalSchemas[self::XSD_NS], "anyType")); |
||
700 | |||
701 | $globalSchemas[self::XML_NS]->addSchema($globalSchemas[self::XSD_NS], self::XSD_NS); |
||
702 | $globalSchemas[self::XSD_NS]->addSchema($globalSchemas[self::XML_NS], self::XML_NS); |
||
703 | |||
704 | foreach ($callbacks as $callback) { |
||
705 | $callback(); |
||
706 | } |
||
707 | } |
||
708 | return $this->globalSchema; |
||
709 | } |
||
710 | |||
711 | /** |
||
712 | * @return \Goetas\XML\XSDReader\Schema\Schema |
||
713 | */ |
||
714 | public function readNode(\DOMNode $node, $file = 'schema.xsd') |
||
715 | { |
||
716 | $this->loadedFiles[$file] = $rootSchema = new Schema(); |
||
717 | |||
718 | $rootSchema->addSchema($this->getGlobalSchema()); |
||
719 | $callbacks = $this->schemaNode($rootSchema, $node); |
||
0 ignored issues
–
show
$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. ![]() |
|||
720 | |||
721 | foreach ($callbacks as $callback) { |
||
722 | call_user_func($callback); |
||
723 | } |
||
724 | |||
725 | return $rootSchema; |
||
726 | } |
||
727 | |||
728 | |||
729 | /** |
||
730 | * @return \Goetas\XML\XSDReader\Schema\Schema |
||
731 | */ |
||
732 | public function readString($content, $file = 'schema.xsd') |
||
733 | { |
||
734 | $xml = new DOMDocument('1.0', 'UTF-8'); |
||
735 | if (! $xml->loadXML($content)) { |
||
736 | throw new IOException("Can't load the schema"); |
||
737 | } |
||
738 | $xml->documentURI = $file; |
||
739 | |||
740 | return $this->readNode($xml->documentElement, $file); |
||
741 | } |
||
742 | /** |
||
743 | * @return \Goetas\XML\XSDReader\Schema\Schema |
||
744 | */ |
||
745 | public function readFile($file) |
||
746 | { |
||
747 | $xml = $this->getDOM($file); |
||
748 | return $this->readNode($xml->documentElement, $file); |
||
749 | } |
||
750 | |||
751 | /** |
||
752 | * @param string $file |
||
753 | * @throws IOException |
||
754 | * @return \DOMDocument |
||
755 | */ |
||
756 | private function getDOM($file) |
||
757 | { |
||
758 | $xml = new DOMDocument('1.0', 'UTF-8'); |
||
759 | if (! $xml->load($file)) { |
||
760 | throw new IOException("Can't load the file $file"); |
||
761 | } |
||
762 | return $xml; |
||
763 | } |
||
764 | } |
||
765 |
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.