Passed
Push — static-analysis ( 0e0544...c612e4 )
by SignpostMarv
03:28
created

loadExtensionChildNodes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 48
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 30
c 3
b 0
f 0
nc 1
nop 2
dl 0
loc 48
ccs 33
cts 33
cp 1
crap 1
rs 9.125
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
abstract class SchemaReaderLoadAbstraction extends SchemaReaderFillAbstraction
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
    /**
82
    * @param int|null $max
83
    *
84
    * @return int|null
85
    */
86 135
    protected static function loadSequenceNormaliseMax(DOMElement $node, $max)
87
    {
88
        return
89
        (
90 135
            (is_int($max) && (bool) $max) ||
91 135
            $node->getAttribute("maxOccurs") == "unbounded" ||
92 135
            $node->getAttribute("maxOccurs") > 1
93 45
        )
94 90
            ? 2
95 135
            : null;
96
    }
97
98
    /**
99
    * @param int|null $max
100
    */
101 135
    protected function loadSequence(ElementContainer $elementContainer, DOMElement $node, $max = null)
102
    {
103 135
        $max = static::loadSequenceNormaliseMax($node, $max);
104
105 135
        static::againstDOMNodeList(
106 135
            $node,
107
            function (
108
                DOMElement $node,
109
                DOMElement $childNode
110
            ) use (
111 135
                $elementContainer,
112 135
                $max
113
            ) {
114 135
                $this->loadSequenceChildNode(
115 135
                    $elementContainer,
116 135
                    $node,
117 135
                    $childNode,
118 90
                    $max
119 45
                );
120 135
            }
121 45
        );
122 135
    }
123
124
    /**
125
    * @param int|null $max
126
    */
127 135
    protected function loadSequenceChildNode(
128
        ElementContainer $elementContainer,
129
        DOMElement $node,
130
        DOMElement $childNode,
131
        $max
132
    ) {
133
        $commonMethods = [
134
            [
135 135
                ['sequence', 'choice', 'all'],
136 135
                [$this, 'loadSequenceChildNodeLoadSequence'],
137
                [
138 135
                    $elementContainer,
139 135
                    $childNode,
140 135
                    $max,
141 45
                ],
142 45
            ],
143 45
        ];
144
        $methods = [
145
            'element' => [
146 135
                [$this, 'loadSequenceChildNodeLoadElement'],
147
                [
148 135
                    $elementContainer,
149 135
                    $node,
150 135
                    $childNode,
151 90
                    $max
152 45
                ]
153 45
            ],
154
            'group' => [
155 135
                [$this, 'loadSequenceChildNodeLoadGroup'],
156
                [
157 135
                    $elementContainer,
158 135
                    $node,
159 90
                    $childNode
160 45
                ]
161 45
            ],
162 45
        ];
163
164 135
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
165 135
    }
166
167
    /**
168
    * @param int|null $max
169
    */
170 135
    protected function loadSequenceChildNodeLoadSequence(
171
        ElementContainer $elementContainer,
172
        DOMElement $childNode,
173
        $max
174
    ) {
175 135
        $this->loadSequence($elementContainer, $childNode, $max);
176 135
    }
177
178
    /**
179
    * @param int|null $max
180
    */
181 135
    protected function loadSequenceChildNodeLoadElement(
182
        ElementContainer $elementContainer,
183
        DOMElement $node,
184
        DOMElement $childNode,
185
        $max
186
    ) {
187 135
        if ($childNode->hasAttribute("ref")) {
188
            /**
189
            * @var ElementDef $referencedElement
190
            */
191 135
            $referencedElement = $this->findSomething('findElement', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref"));
192 135
            $element = ElementRef::loadElementRef(
193 135
                $referencedElement,
194 90
                $childNode
195 45
            );
196 45
        } else {
197 135
            $element = Element::loadElement(
198 135
                $this,
199 135
                $elementContainer->getSchema(),
200 90
                $childNode
201 45
            );
202
        }
203 135
        if (is_int($max) && (bool) $max) {
204 135
            $element->setMax($max);
205 45
        }
206 135
        $elementContainer->addElement($element);
207 135
    }
208
209 135
    protected function loadSequenceChildNodeLoadGroup(
210
        ElementContainer $elementContainer,
211
        DOMElement $node,
212
        DOMElement $childNode
213
    ) {
214 135
        $this->addGroupAsElement(
215 135
            $elementContainer->getSchema(),
216 135
            $node,
217 135
            $childNode,
218 90
            $elementContainer
219 45
        );
220 135
    }
221
222 135
    protected function addGroupAsElement(
223
        Schema $schema,
224
        DOMElement $node,
225
        DOMElement $childNode,
226
        ElementContainer $elementContainer
227
    ) {
228
        /**
229
        * @var Group $referencedGroup
230
        */
231 135
        $referencedGroup = $this->findSomething(
232 135
            'findGroup',
233 135
            $schema,
234 135
            $node,
235 135
            $childNode->getAttribute("ref")
236 45
        );
237
238 135
        $group = GroupRef::loadGroupRef($referencedGroup, $childNode);
239 135
        $elementContainer->addElement($group);
240 135
    }
241
242
    /**
243
    * @return Closure
244
    */
245 135
    protected function loadGroup(Schema $schema, DOMElement $node)
246
    {
247 135
        return Group::loadGroup($this, $schema, $node);
248
    }
249
250
    /**
251
    * @return BaseComplexType
252
    */
253 135
    protected function loadComplexTypeBeforeCallbackCallback(
254
        Schema $schema,
255
        DOMElement $node
256
    ) {
257
        /**
258
        * @var bool $isSimple
259
        */
260 135
        $isSimple = false;
261
262 135
        static::againstDOMNodeList(
263 135
            $node,
264
            function (
265
                DOMElement $node,
266
                DOMElement $childNode
267
            ) use (
268 45
                & $isSimple
269
            ) {
270 135
                if ($isSimple) {
271 3
                    return;
272
                }
273 135
                if ($childNode->localName === "simpleContent") {
274 6
                    $isSimple = true;
275 2
                }
276 135
            }
277 45
        );
278
279 135
        $type = $isSimple ? new ComplexTypeSimpleContent($schema, $node->getAttribute("name")) : new ComplexType($schema, $node->getAttribute("name"));
280
281 135
        $type->setDoc(static::getDocumentation($node));
282 135
        if ($node->getAttribute("name")) {
283 135
            $schema->addType($type);
284 45
        }
285
286 135
        return $type;
287
    }
288
289
    /**
290
    * @param Closure|null $callback
291
    *
292
    * @return Closure
293
    */
294 135
    protected function loadComplexType(Schema $schema, DOMElement $node, $callback = null)
295
    {
296 135
        $type = $this->loadComplexTypeBeforeCallbackCallback($schema, $node);
297
298 135
        return $this->makeCallbackCallback(
299 135
            $type,
300 135
            $node,
301
            function (
302
                DOMElement $node,
303
                DOMElement $childNode
304
            ) use(
305 135
                $schema,
306 135
                $type
307
            ) {
308 135
                $this->loadComplexTypeFromChildNode(
309 135
                    $type,
310 135
                    $node,
311 135
                    $childNode,
312 90
                    $schema
313 45
                );
314 135
            },
315 90
            $callback
316 45
        );
317
    }
318
319 135
    protected function loadComplexTypeFromChildNode(
320
        BaseComplexType $type,
321
        DOMElement $node,
322
        DOMElement $childNode,
323
        Schema $schema
324
    ) {
325
        $commonMethods = [
326
            [
327 135
                ['sequence', 'choice', 'all'],
328 135
                [$this, 'maybeLoadSequenceFromElementContainer'],
329
                [
330 135
                    $type,
331 135
                    $childNode,
332 45
                ],
333 45
            ],
334 45
        ];
335
        $methods = [
336 90
            'attribute' => [
337 135
                [$type, 'addAttributeFromAttributeOrRef'],
338
                [
339 135
                    $this,
340 135
                    $childNode,
341 135
                    $schema,
342 90
                    $node
343 45
                ]
344 45
            ],
345
            'attributeGroup' => [
346 45
                (AttributeGroup::class . '::findSomethingLikeThis'),
347
                [
348 135
                    $this,
349 135
                    $schema,
350 135
                    $node,
351 135
                    $childNode,
352 90
                    $type
353 45
                ]
354 45
            ],
355 45
        ];
356
        if (
357 90
            $type instanceof ComplexType
358 45
        ) {
359 135
            $methods['group'] = [
360 135
                [$this, 'addGroupAsElement'],
361
                [
362 135
                    $schema,
363 135
                    $node,
364 135
                    $childNode,
365 90
                    $type
366 45
                ]
367 45
            ];
368 45
        }
369
370 135
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
371 135
    }
372
373
    /**
374
    * @param Closure|null $callback
375
    *
376
    * @return Closure
377
    */
378 135
    protected function loadSimpleType(Schema $schema, DOMElement $node, $callback = null)
379
    {
380 135
        $type = new SimpleType($schema, $node->getAttribute("name"));
381 135
        $type->setDoc(static::getDocumentation($node));
382 135
        if ($node->getAttribute("name")) {
383 135
            $schema->addType($type);
384 45
        }
385
386 90
        static $methods = [
387
            'union' => 'loadUnion',
388
            'list' => 'loadList',
389 45
        ];
390
391 135
        return $this->makeCallbackCallback(
392 135
            $type,
393 135
            $node,
394 View Code Duplication
            function (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
395
                DOMElement $node,
396
                DOMElement $childNode
397
            ) use (
398 135
                $methods,
399 135
                $type
400
            ) {
401
                /**
402
                * @var string[]
403
                */
404 135
                $methods = $methods;
405
406 135
                $this->maybeCallMethod(
407 135
                    $methods,
408 135
                    $childNode->localName,
409 135
                    $childNode,
410 135
                    $type,
411 90
                    $childNode
412 45
                );
413 135
            },
414 90
            $callback
415 45
        );
416
    }
417
418 135
    protected function loadList(SimpleType $type, DOMElement $node)
419
    {
420 135
        if ($node->hasAttribute("itemType")) {
421
            /**
422
            * @var SimpleType $listType
423
            */
424 135
            $listType = $this->findSomeType($type, $node, 'itemType');
425 135
            $type->setList($listType);
426 45
        } else {
427
            $addCallback = function (SimpleType $list) use ($type) {
428 135
                $type->setList($list);
429 135
            };
430
431 135
            Type::loadTypeWithCallbackOnChildNodes(
432 135
                $this,
433 135
                $type->getSchema(),
434 135
                $node,
435 90
                $addCallback
436 45
            );
437
        }
438 135
    }
439
440 135
    protected function loadUnion(SimpleType $type, DOMElement $node)
441
    {
442 135
        if ($node->hasAttribute("memberTypes")) {
443 135
            $types = preg_split('/\s+/', $node->getAttribute("memberTypes"));
444 135
            foreach ($types as $typeName) {
445
                /**
446
                * @var SimpleType $unionType
447
                */
448 135
                $unionType = $this->findSomeTypeFromAttribute(
449 135
                    $type,
450 135
                    $node,
451 90
                    $typeName
452 45
                );
453 135
                $type->addUnion($unionType);
454 45
            }
455 45
        }
456
        $addCallback = function (SimpleType $unType) use ($type) {
457 135
            $type->addUnion($unType);
458 135
        };
459
460 135
        Type::loadTypeWithCallbackOnChildNodes(
461 135
            $this,
462 135
            $type->getSchema(),
463 135
            $node,
464 90
            $addCallback
465 45
        );
466 135
    }
467
468 135
    protected function loadExtensionChildNodes(
469
        BaseComplexType $type,
470
        DOMElement $node
471
    ) {
472 135
        static::againstDOMNodeList(
473 135
            $node,
474 135
            function (
475
                DOMElement $node,
476
                DOMElement $childNode
477
            ) use (
478 135
                $type
479
            ) {
480
                $commonMethods = [
481
                    [
482 135
                        ['sequence', 'choice', 'all'],
483 135
                        [$this, 'maybeLoadSequenceFromElementContainer'],
484
                        [
485 135
                            $type,
486 135
                            $childNode,
487 45
                        ],
488 45
                    ],
489 45
                ];
490
                $methods = [
491 90
                    'attribute' => [
492 135
                        [$type, 'addAttributeFromAttributeOrRef'],
493
                        [
494 135
                            $this,
495 135
                            $childNode,
496 135
                            $type->getSchema(),
497 90
                            $node
498 45
                        ]
499 45
                    ],
500
                    'attributeGroup' => [
501 45
                        (AttributeGroup::class . '::findSomethingLikeThis'),
502
                        [
503 135
                            $this,
504 135
                            $type->getSchema(),
505 135
                            $node,
506 135
                            $childNode,
507 90
                            $type
508 45
                        ]
509 45
                    ],
510 45
                ];
511
512 135
                $this->maybeCallCallableWithArgs(
513 135
                    $childNode,
514 135
                    $commonMethods,
515 90
                    $methods
516 45
                );
517 135
            }
518 45
        );
519 135
    }
520
521 135
    protected function loadExtension(BaseComplexType $type, DOMElement $node)
522
    {
523 135
        $extension = new Extension();
524 135
        $type->setExtension($extension);
525
526 135
        if ($node->hasAttribute("base")) {
527 135
            $this->findAndSetSomeBase(
528 135
                $type,
529 135
                $extension,
530 90
                $node
531 45
            );
532 45
        }
533 135
        $this->loadExtensionChildNodes($type, $node);
534 135
    }
535
536 135
    protected function loadRestriction(Type $type, DOMElement $node)
537
    {
538 135
        Restriction::loadRestriction($this, $type, $node);
539 135
    }
540
541
    /**
542
    * @return Closure
543
    */
544 135
    protected function loadElementDef(Schema $schema, DOMElement $node)
545
    {
546 135
        return $this->loadAttributeOrElementDef($schema, $node, false);
547
    }
548
}
549