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); |
||
0 ignored issues
–
show
|
|||
75 | break; |
||
76 | case 'attributeGroup': |
||
77 | |||
78 | $attribute = $this->findSomething('findAttributeGroup', $schema, $node, $childNode->getAttribute("ref")); |
||
79 | $attGroup->addAttribute($attribute); |
||
0 ignored issues
–
show
It seems like
$attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 78 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...e\Group::addAttribute() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$referencedElement defined by $this->findSomething('fi...e->getAttribute('ref')) on line 278 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...eader::loadElementRef() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$referencedGroup defined by $this->findSomething('fi...e->getAttribute('ref')) on line 289 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\SchemaReader::loadGroupRef() does only seem to accept object<Goetas\XML\XSDReader\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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$type defined by $isSimple ? new \Goetas\...->getAttribute('name')) on line 337 can also be of type object<Goetas\XML\XSDRea...mplexTypeSimpleContent> ; however, Goetas\XML\XSDReader\SchemaReader::loadSequence() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$referencedAttribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 358 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...der::loadAttributeRef() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 367 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...lexType::addAttribute() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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"))); |
||
0 ignored issues
–
show
It seems like
$this->findSomething('fi...tAttribute('itemType')) targeting Goetas\XML\XSDReader\SchemaReader::findSomething() can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...e\SimpleType::setList() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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)); |
||
0 ignored issues
–
show
It seems like
$this->findSomething('fi...ma(), $node, $typeName) targeting Goetas\XML\XSDReader\SchemaReader::findSomething() can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...\SimpleType::addUnion() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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
$type of type object<Goetas\XML\XSDReader\Schema\Type\Type> is not a sub-type of object<Goetas\XML\XSDRea...a\Type\BaseComplexType> . It seems like you assume a child class of the class Goetas\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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$parent defined by $this->findSomething('fi...->getAttribute('base')) on line 479 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> ; however, Goetas\XML\XSDReader\Sch...ritance\Base::setBase() does only seem to accept object<Goetas\XML\XSDReader\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. ![]() |
|||
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); |
||
0 ignored issues
–
show
$type is of type object<Goetas\XML\XSDRea...a\Type\BaseComplexType> , but the function expects a object<Goetas\XML\XSDRea...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);
![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 492 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...lexType::addAttribute() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
497 | break; |
||
498 | case 'attributeGroup': |
||
499 | $attribute = $this->findSomething('findAttributeGroup', $type->getSchema(), $node, $childNode->getAttribute("ref")); |
||
500 | $type->addAttribute($attribute); |
||
0 ignored issues
–
show
It seems like
$attribute defined by $this->findSomething('fi...e->getAttribute('ref')) on line 499 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> or object<Goetas\XML\XSDReader\Schema\Type\Type> ; however, Goetas\XML\XSDReader\Sch...lexType::addAttribute() does only seem to accept object<Goetas\XML\XSDRea...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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$restrictedType defined by $this->findSomething('fi...->getAttribute('base')) on line 511 can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> ; however, Goetas\XML\XSDReader\Sch...ritance\Base::setBase() does only seem to accept object<Goetas\XML\XSDReader\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. ![]() |
|||
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); |
||
0 ignored issues
–
show
It seems like
$type can also be of type object<Goetas\XML\XSDRea...ma\Element\ElementItem> ; however, Goetas\XML\XSDReader\Schema\Item::setType() does only seem to accept object<Goetas\XML\XSDReader\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. ![]() |
|||
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 |
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:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.