Passed
Push — static-analysis ( 172fb7...c3aabf )
by SignpostMarv
03:20
created

maybeLoadExtensionFromBaseComplexType()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.8204

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 3
cts 13
cp 0.2308
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 1
nop 2
crap 3.8204
1
<?php
2
namespace GoetasWebservices\XML\XSDReader;
3
4
use Closure;
5
use DOMDocument;
6
use DOMElement;
7
use DOMNode;
8
use DOMNodeList;
9
use GoetasWebservices\XML\XSDReader\Exception\IOException;
10
use GoetasWebservices\XML\XSDReader\Exception\TypeException;
11
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Attribute;
12
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeDef;
13
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem;
14
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
15
use GoetasWebservices\XML\XSDReader\Schema\Element\Element;
16
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementContainer;
17
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
18
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
19
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementRef;
20
use GoetasWebservices\XML\XSDReader\Schema\Element\Group;
21
use GoetasWebservices\XML\XSDReader\Schema\Element\GroupRef;
22
use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetMinMax;
23
use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException;
24
use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Base;
25
use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Extension;
26
use GoetasWebservices\XML\XSDReader\Schema\Inheritance\Restriction;
27
use GoetasWebservices\XML\XSDReader\Schema\Item;
28
use GoetasWebservices\XML\XSDReader\Schema\Schema;
29
use GoetasWebservices\XML\XSDReader\Schema\SchemaItem;
30
use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType;
31
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
32
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexTypeSimpleContent;
33
use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType;
34
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
35
use GoetasWebservices\XML\XSDReader\Utils\UrlUtils;
36
use RuntimeException;
37
38
class SchemaReader extends SchemaReaderCallbackAbstraction
39
{
40
    /**
41
    * @return Closure
42
    */
43 135
    protected function loadAttributeGroup(Schema $schema, DOMElement $node)
44
    {
45 135
        return AttributeGroup::loadAttributeGroup($this, $schema, $node);
46
    }
47
48
    /**
49
    * @param bool $attributeDef
50
    *
51
    * @return Closure
52
    */
53 135
    protected function loadAttributeOrElementDef(
54
        Schema $schema,
55
        DOMElement $node,
56
        $attributeDef
57
    ) {
58 135
        $name = $node->getAttribute('name');
59 135
        if ($attributeDef) {
60 135
            $attribute = new AttributeDef($schema, $name);
61 135
            $schema->addAttribute($attribute);
62 45
        } else {
63 135
            $attribute = new ElementDef($schema, $name);
64 135
            $schema->addElement($attribute);
65
        }
66
67
68
        return function () use ($attribute, $node) {
69 135
            $this->fillItem($attribute, $node);
70 135
        };
71
    }
72
73
    /**
74
    * @return Closure
75
    */
76 135
    protected function loadAttributeDef(Schema $schema, DOMElement $node)
77
    {
78 135
        return $this->loadAttributeOrElementDef($schema, $node, true);
79
    }
80
81 135
    protected function setSchemaThingsFromNode(
82
        Schema $schema,
83
        DOMElement $node,
84
        Schema $parent = null
85
    ) {
86 135
        $schema->setDoc(static::getDocumentation($node));
87
88 135
        if ($node->hasAttribute("targetNamespace")) {
89 135
            $schema->setTargetNamespace($node->getAttribute("targetNamespace"));
90 45
        } elseif ($parent) {
91
            $schema->setTargetNamespace($parent->getTargetNamespace());
92
        }
93 135
        $schema->setElementsQualification($node->getAttribute("elementFormDefault") == "qualified");
94 135
        $schema->setAttributesQualification($node->getAttribute("attributeFormDefault") == "qualified");
95 135
        $schema->setDoc(static::getDocumentation($node));
96 135
    }
97
98
    /**
99
     *
100
     * @param Schema $schema
101
     * @param DOMElement $node
102
     * @param Schema $parent
103
     * @return Closure[]
104
     */
105 135
    protected function schemaNode(Schema $schema, DOMElement $node, Schema $parent = null)
106
    {
107 135
        $this->setSchemaThingsFromNode($schema, $node, $parent);
108 135
        $functions = array();
109
110 90
        static $methods = [
111
            'include' => 'loadImport',
112
            'import' => 'loadImport',
113
            'element' => 'loadElementDef',
114
            'attribute' => 'loadAttributeDef',
115
            'attributeGroup' => 'loadAttributeGroup',
116
            'group' => 'loadGroup',
117
            'complexType' => 'loadComplexType',
118
            'simpleType' => 'loadSimpleType',
119 45
        ];
120
121 135
        foreach ($node->childNodes as $childNode) {
122 135
            $callback = $this->maybeCallMethod(
123 135
                $methods,
124 135
                (string) $childNode->localName,
125 135
                $childNode,
126 135
                $schema,
127 90
                $childNode
128 45
            );
129
130 135
            if ($callback instanceof Closure) {
131 135
                $functions[] = $callback;
132 45
            }
133 45
        }
134
135 135
        return $functions;
136
    }
137
138
    /**
139
    * @param int|null $max
140
    *
141
    * @return int|null
142
    */
143 135
    protected static function loadSequenceNormaliseMax(DOMElement $node, $max)
144
    {
145
        return
146
        (
147 135
            (is_int($max) && (bool) $max) ||
148 135
            $node->getAttribute("maxOccurs") == "unbounded" ||
149 135
            $node->getAttribute("maxOccurs") > 1
150 45
        )
151 90
            ? 2
152 135
            : null;
153
    }
154
155
    /**
156
    * @param int|null $max
157
    */
158 135
    protected function loadSequence(ElementContainer $elementContainer, DOMElement $node, $max = null)
159
    {
160 135
        $max = static::loadSequenceNormaliseMax($node, $max);
161
162 135
        foreach ($node->childNodes as $childNode) {
163 135
            if ($childNode instanceof DOMElement) {
164 135
                $this->loadSequenceChildNode(
165 135
                    $elementContainer,
166 135
                    $node,
167 135
                    $childNode,
168 90
                    $max
169 45
                );
170 45
            }
171 45
        }
172 135
    }
173
174
    /**
175
    * @param int|null $max
176
    */
177 135
    protected function loadSequenceChildNode(
178
        ElementContainer $elementContainer,
179
        DOMElement $node,
180
        DOMElement $childNode,
181
        $max
182
    ) {
183
        $commonMethods = [
184
            [
185 135
                ['sequence', 'choice', 'all'],
186 135
                [$this, 'loadSequenceChildNodeLoadSequence'],
187
                [
188 135
                    $elementContainer,
189 135
                    $childNode,
190 135
                    $max,
191 45
                ],
192 45
            ],
193 45
        ];
194
        $methods = [
195
            'element' => [
196 135
                [$this, 'loadSequenceChildNodeLoadElement'],
197
                [
198 135
                    $elementContainer,
199 135
                    $node,
200 135
                    $childNode,
201 90
                    $max
202 45
                ]
203 45
            ],
204
            'group' => [
205 135
                [$this, 'loadSequenceChildNodeLoadGroup'],
206
                [
207 135
                    $elementContainer,
208 135
                    $node,
209 90
                    $childNode
210 45
                ]
211 45
            ],
212 45
        ];
213
214 135
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
215 135
    }
216
217
    /**
218
    * @param int|null $max
219
    */
220 135
    protected function loadSequenceChildNodeLoadSequence(
221
        ElementContainer $elementContainer,
222
        DOMElement $childNode,
223
        $max
224
    ) {
225 135
        $this->loadSequence($elementContainer, $childNode, $max);
226 135
    }
227
228
    /**
229
    * @param int|null $max
230
    */
231 135
    protected function loadSequenceChildNodeLoadElement(
232
        ElementContainer $elementContainer,
233
        DOMElement $node,
234
        DOMElement $childNode,
235
        $max
236
    ) {
237 135
        if ($childNode->hasAttribute("ref")) {
238
            /**
239
            * @var ElementDef $referencedElement
240
            */
241 135
            $referencedElement = $this->findSomething('findElement', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref"));
242 135
            $element = ElementRef::loadElementRef(
243 135
                $referencedElement,
244 90
                $childNode
245 45
            );
246 45
        } else {
247 135
            $element = Element::loadElement(
248 135
                $this,
249 135
                $elementContainer->getSchema(),
250 90
                $childNode
251 45
            );
252
        }
253 135
        if (is_int($max) && (bool) $max) {
254 135
            $element->setMax($max);
255 45
        }
256 135
        $elementContainer->addElement($element);
257 135
    }
258
259 135
    protected function loadSequenceChildNodeLoadGroup(
260
        ElementContainer $elementContainer,
261
        DOMElement $node,
262
        DOMElement $childNode
263
    ) {
264 135
        $this->addGroupAsElement(
265 135
            $elementContainer->getSchema(),
266 135
            $node,
267 135
            $childNode,
268 90
            $elementContainer
269 45
        );
270 135
    }
271
272 135
    protected function addGroupAsElement(
273
        Schema $schema,
274
        DOMElement $node,
275
        DOMElement $childNode,
276
        ElementContainer $elementContainer
277
    ) {
278
        /**
279
        * @var Group $referencedGroup
280
        */
281 135
        $referencedGroup = $this->findSomething(
282 135
            'findGroup',
283 135
            $schema,
284 135
            $node,
285 135
            $childNode->getAttribute("ref")
286 45
        );
287
288 135
        $group = GroupRef::loadGroupRef($referencedGroup, $childNode);
289 135
        $elementContainer->addElement($group);
290 135
    }
291
292
    /**
293
    * @return Closure
294
    */
295 135
    protected function loadGroup(Schema $schema, DOMElement $node)
296
    {
297 135
        return Group::loadGroup($this, $schema, $node);
298
    }
299
300
    /**
301
    * @return BaseComplexType
302
    */
303 135
    protected function loadComplexTypeBeforeCallbackCallback(
304
        Schema $schema,
305
        DOMElement $node
306
    ) {
307 135
        $isSimple = false;
308
309 135
        foreach ($node->childNodes as $childNode) {
310 135
            if ($childNode->localName === "simpleContent") {
311 6
                $isSimple = true;
312 49
                break;
313
            }
314 45
        }
315
316 135
        $type = $isSimple ? new ComplexTypeSimpleContent($schema, $node->getAttribute("name")) : new ComplexType($schema, $node->getAttribute("name"));
317
318 135
        $type->setDoc(static::getDocumentation($node));
319 135
        if ($node->getAttribute("name")) {
320 135
            $schema->addType($type);
321 45
        }
322
323 135
        return $type;
324
    }
325
326
    /**
327
    * @param Closure|null $callback
328
    *
329
    * @return Closure
330
    */
331 135
    protected function loadComplexType(Schema $schema, DOMElement $node, $callback = null)
332
    {
333 135
        $type = $this->loadComplexTypeBeforeCallbackCallback($schema, $node);
334
335 135
        return $this->makeCallbackCallback(
336 135
            $type,
337 135
            $node,
338
            function (
339
                DOMElement $node,
340
                DOMElement $childNode
341
            ) use(
342 135
                $schema,
343 135
                $type
344
            ) {
345 135
                $this->loadComplexTypeFromChildNode(
346 135
                    $type,
347 135
                    $node,
348 135
                    $childNode,
349 90
                    $schema
350 45
                );
351 135
            },
352 90
            $callback
353 45
        );
354
    }
355
356 135
    protected function loadComplexTypeFromChildNode(
357
        BaseComplexType $type,
358
        DOMElement $node,
359
        DOMElement $childNode,
360
        Schema $schema
361
    ) {
362
        $commonMethods = [
363
            [
364 135
                ['sequence', 'choice', 'all'],
365 135
                [$this, 'maybeLoadSequenceFromElementContainer'],
366
                [
367 135
                    $type,
368 135
                    $childNode,
369 45
                ],
370 45
            ],
371 45
        ];
372
        $methods = [
373 90
            'attribute' => [
374 135
                [$type, 'addAttributeFromAttributeOrRef'],
375
                [
376 135
                    $this,
377 135
                    $childNode,
378 135
                    $schema,
379 90
                    $node
380 45
                ]
381 45
            ],
382
            'attributeGroup' => [
383 45
                (AttributeGroup::class . '::findSomethingLikeThis'),
384
                [
385 135
                    $this,
386 135
                    $schema,
387 135
                    $node,
388 135
                    $childNode,
389 90
                    $type
390 45
                ]
391 45
            ],
392 45
        ];
393
        if (
394 90
            $type instanceof ComplexType
395 45
        ) {
396 135
            $methods['group'] = [
397 135
                [$this, 'addGroupAsElement'],
398
                [
399 135
                    $schema,
400 135
                    $node,
401 135
                    $childNode,
402 90
                    $type
403 45
                ]
404 45
            ];
405 45
        }
406
407 135
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
408 135
    }
409
410
    /**
411
    * @param Closure|null $callback
412
    *
413
    * @return Closure
414
    */
415 135
    protected function loadSimpleType(Schema $schema, DOMElement $node, $callback = null)
416
    {
417 135
        $type = new SimpleType($schema, $node->getAttribute("name"));
418 135
        $type->setDoc(static::getDocumentation($node));
419 135
        if ($node->getAttribute("name")) {
420 135
            $schema->addType($type);
421 45
        }
422
423 90
        static $methods = [
424
            'union' => 'loadUnion',
425
            'list' => 'loadList',
426 45
        ];
427
428 135
        return $this->makeCallbackCallback(
429 135
            $type,
430 135
            $node,
431
            function (
432
                DOMElement $node,
433
                DOMElement $childNode
434
            ) use (
435 135
                $methods,
436 135
                $type
437
            ) {
438 135
                $this->maybeCallMethod(
439 135
                    $methods,
440 135
                    $childNode->localName,
441 135
                    $childNode,
442 135
                    $type,
443 90
                    $childNode
444 45
                );
445 135
            },
446 90
            $callback
447 45
        );
448
    }
449
450 135
    protected function loadList(SimpleType $type, DOMElement $node)
451
    {
452 135
        if ($node->hasAttribute("itemType")) {
453
            /**
454
            * @var SimpleType $listType
455
            */
456 135
            $listType = $this->findSomeType($type, $node, 'itemType');
457 135
            $type->setList($listType);
458 45
        } else {
459
            $addCallback = function (SimpleType $list) use ($type) {
460 135
                $type->setList($list);
461 135
            };
462
463 135
            Type::loadTypeWithCallbackOnChildNodes(
464 135
                $this,
465 135
                $type->getSchema(),
466 135
                $node,
467 90
                $addCallback
468 45
            );
469
        }
470 135
    }
471
472
    /**
473
    * @param string $attributeName
474
    *
475
    * @return SchemaItem
476
    */
477 135
    protected function findSomeType(
478
        SchemaItem $fromThis,
479
        DOMElement $node,
480
        $attributeName
481
    ) {
482 135
        return $this->findSomeTypeFromAttribute(
483 135
            $fromThis,
484 135
            $node,
485 135
            $node->getAttribute($attributeName)
486 45
        );
487
    }
488
489
    /**
490
    * @param string $attributeName
491
    *
492
    * @return SchemaItem
493
    */
494 135
    protected function findSomeTypeFromAttribute(
495
        SchemaItem $fromThis,
496
        DOMElement $node,
497
        $attributeName
498
    ) {
499
        /**
500
        * @var SchemaItem $out
501
        */
502 135
        $out = $this->findSomething(
503 135
            'findType',
504 135
            $fromThis->getSchema(),
505 135
            $node,
506 90
            $attributeName
507 45
        );
508
509 135
        return $out;
510
    }
511
512 135
    protected function loadUnion(SimpleType $type, DOMElement $node)
513
    {
514 135
        if ($node->hasAttribute("memberTypes")) {
515 135
            $types = preg_split('/\s+/', $node->getAttribute("memberTypes"));
516 135
            foreach ($types as $typeName) {
517
                /**
518
                * @var SimpleType $unionType
519
                */
520 135
                $unionType = $this->findSomeTypeFromAttribute(
521 135
                    $type,
522 135
                    $node,
523 90
                    $typeName
524 45
                );
525 135
                $type->addUnion($unionType);
526 45
            }
527 45
        }
528
        $addCallback = function (SimpleType $unType) use ($type) {
529 135
            $type->addUnion($unType);
530 135
        };
531
532 135
        Type::loadTypeWithCallbackOnChildNodes(
533 135
            $this,
534 135
            $type->getSchema(),
535 135
            $node,
536 90
            $addCallback
537 45
        );
538 135
    }
539
540
    /**
541
    * @param bool $checkAbstract
542
    */
543 135
    protected function fillTypeNode(Type $type, DOMElement $node, $checkAbstract = false)
544
    {
545
546 135
        if ($checkAbstract) {
547 135
            $type->setAbstract($node->getAttribute("abstract") === "true" || $node->getAttribute("abstract") === "1");
548 45
        }
549
550 90
        static $methods = [
551
            'restriction' => 'loadRestriction',
552
            'extension' => 'maybeLoadExtensionFromBaseComplexType',
553
            'simpleContent' => 'fillTypeNode',
554
            'complexContent' => 'fillTypeNode',
555 45
        ];
556
557 135
        foreach ($node->childNodes as $childNode) {
558 135
            $this->maybeCallMethod(
559 135
                $methods,
560 135
                (string) $childNode->localName,
561 135
                $childNode,
562 135
                $type,
563 90
                $childNode
564 45
            );
565 45
        }
566 135
    }
567
568 135
    protected function loadExtensionChildNode(
569
        BaseComplexType $type,
570
        DOMElement $node,
571
        DOMElement $childNode
572
    ) {
573
        $commonMethods = [
574
            [
575 135
                ['sequence', 'choice', 'all'],
576 135
                [$this, 'maybeLoadSequenceFromElementContainer'],
577
                [
578 135
                    $type,
579 135
                    $childNode,
580 45
                ],
581 45
            ],
582 45
        ];
583
        $methods = [
584 90
            'attribute' => [
585 135
                [$type, 'addAttributeFromAttributeOrRef'],
586
                [
587 135
                    $this,
588 135
                    $childNode,
589 135
                    $type->getSchema(),
590 90
                    $node
591 45
                ]
592 45
            ],
593
            'attributeGroup' => [
594 45
                (AttributeGroup::class . '::findSomethingLikeThis'),
595
                [
596 135
                    $this,
597 135
                    $type->getSchema(),
598 135
                    $node,
599 135
                    $childNode,
600 90
                    $type
601 45
                ]
602 45
            ],
603 45
        ];
604
605 135
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
606 135
    }
607
608 135
    protected function loadExtension(BaseComplexType $type, DOMElement $node)
609
    {
610 135
        $extension = new Extension();
611 135
        $type->setExtension($extension);
612
613 135
        if ($node->hasAttribute("base")) {
614 135
            $this->findAndSetSomeBase(
615 135
                $type,
616 135
                $extension,
617 90
                $node
618 45
            );
619 45
        }
620
621 135
        $this->loadExtensionChildNodes($type, $node->childNodes, $node);
622 135
    }
623
624 135
    protected function loadExtensionChildNodes(
625
        BaseComplexType $type,
626
        DOMNodeList $childNodes,
627
        DOMElement $node
628
    ) {
629 135
        foreach ($childNodes as $childNode) {
630 135
            if ($childNode instanceof DOMElement) {
631 135
                $this->loadExtensionChildNode(
632 135
                    $type,
633 135
                    $node,
634 90
                    $childNode
635 45
                );
636 45
            }
637 45
        }
638 135
    }
639
640 135
    protected function loadRestriction(Type $type, DOMElement $node)
641
    {
642 135
        Restriction::loadRestriction($this, $type, $node);
643 135
    }
644
645
    /**
646
    * @param string $typeName
647
    *
648
    * @return mixed[]
649
    */
650 135
    protected static function splitParts(DOMElement $node, $typeName)
651
    {
652 135
        $prefix = null;
653 135
        $name = $typeName;
654 135
        if (strpos($typeName, ':') !== false) {
655 135
            list ($prefix, $name) = explode(':', $typeName);
656 45
        }
657
658 135
        $namespace = $node->lookupNamespaceUri($prefix ?: '');
659
        return array(
660 135
            $name,
661 135
            $namespace,
662 90
            $prefix
663 45
        );
664
    }
665
666
    /**
667
    * @return Closure
668
    */
669 135
    protected function loadElementDef(Schema $schema, DOMElement $node)
670
    {
671 135
        return $this->loadAttributeOrElementDef($schema, $node, false);
672
    }
673
674 135
    protected function fillItemNonLocalType(Item $element, DOMElement $node)
675
    {
676 135
        if ($node->getAttribute("type")) {
677
            /**
678
            * @var Type $type
679
            */
680 135
            $type = $this->findSomeType($element, $node, 'type');
681 45
        } else {
682
            /**
683
            * @var Type $type
684
            */
685 135
            $type = $this->findSomeTypeFromAttribute(
686 135
                $element,
687 135
                $node,
688 135
                ($node->lookupPrefix(self::XSD_NS) . ':anyType')
689 45
            );
690
        }
691
692 135
        $element->setType($type);
693 135
    }
694
695
    /**
696
    * @return Closure
697
    */
698 135
    protected function loadImport(Schema $schema, DOMElement $node)
699
    {
700 135
        $base = urldecode($node->ownerDocument->documentURI);
701 135
        $file = UrlUtils::resolveRelativeUrl($base, $node->getAttribute("schemaLocation"));
702
703 135
        $namespace = $node->getAttribute("namespace");
704
705
        if (
706
            (
707 135
                isset(self::$globalSchemaInfo[$namespace]) &&
708 135
                Schema::hasLoadedFile(
709 135
                    $loadedFilesKey = self::$globalSchemaInfo[$namespace]
710 45
                )
711 45
            ) ||
712 9
            Schema::hasLoadedFile(
713 9
                $loadedFilesKey = $this->getNamespaceSpecificFileIndex(
714 9
                    $file,
715 6
                    $namespace
716 3
                )
717 3
            ) ||
718 47
            Schema::hasLoadedFile($loadedFilesKey = $file)
719 45
        ) {
720 135
            $schema->addSchema(Schema::getLoadedFile($loadedFilesKey));
721
722
            return function() {
723 135
            };
724
        }
725
726 3
        return $this->loadImportFresh($schema, $node, $file, $namespace);
727
    }
728
729
    /**
730
    * @param string $file
731
    * @param string $namespace
732
    *
733
    * @return Closure
734
    */
735 3
    protected function loadImportFresh(
736
        Schema $schema,
737
        DOMElement $node,
738
        $file,
739
        $namespace
740
    ) {
741 3
        if (! $namespace) {
742 3
            $newSchema = Schema::setLoadedFile($file, $schema);
743 1
        } else {
744
            $newSchema = Schema::setLoadedFile($file, new Schema());
745
            $newSchema->addSchema($this->getGlobalSchema());
746
        }
747
748 3
        $xml = $this->getDOM(isset($this->knownLocationSchemas[$file]) ? $this->knownLocationSchemas[$file] : $file);
749
750 3
        $callbacks = $this->schemaNode($newSchema, $xml->documentElement, $schema);
751
752 3
        if ($namespace) {
753
            $schema->addSchema($newSchema);
754
        }
755
756
757 3
        return function () use ($callbacks) {
758 3
            foreach ($callbacks as $callback) {
759 3
                $callback();
760 1
            }
761 3
        };
762
    }
763
764
    /**
765
    * @return Schema[]
766
    */
767 135
    protected function setupGlobalSchemas(array & $callbacks)
768
    {
769 135
            $globalSchemas = array();
770 135
            foreach (self::$globalSchemaInfo as $namespace => $uri) {
771 135
                Schema::setLoadedFile(
772 135
                    $uri,
773 135
                    $globalSchemas[$namespace] = $schema = new Schema()
774 45
                );
775 135
                if ($namespace === self::XSD_NS) {
776 135
                    $this->globalSchema = $schema;
777 45
                }
778 135
                $xml = $this->getDOM($this->knownLocationSchemas[$uri]);
779 135
                $callbacks = array_merge($callbacks, $this->schemaNode($schema, $xml->documentElement));
780 45
            }
781
782 135
        return $globalSchemas;
783
    }
784
785
    /**
786
     * It is possible that a single file contains multiple <xsd:schema/> nodes, for instance in a WSDL file.
787
     *
788
     * Each of these  <xsd:schema/> nodes typically target a specific namespace. Append the target namespace to the
789
     * file to distinguish between multiple schemas in a single file.
790
     *
791
     * @param string $file
792
     * @param string $targetNamespace
793
     *
794
     * @return string
795
     */
796 135
    protected function getNamespaceSpecificFileIndex($file, $targetNamespace)
797
    {
798 135
        return $file . '#' . $targetNamespace;
799
    }
800
801
    /**
802
     * @param string $file
803
     *
804
     * @return DOMDocument
805
     *
806
     * @throws IOException
807
     */
808 135
    protected function getDOM($file)
809
    {
810 135
        $xml = new DOMDocument('1.0', 'UTF-8');
811 135
        if (!$xml->load($file)) {
812
            throw new IOException("Can't load the file $file");
813
        }
814 135
        return $xml;
815
    }
816
}
817