Passed
Push — static-analysis ( 4098e3...ccdceb )
by SignpostMarv
03:33
created

SchemaReaderLoadAbstraction::loadSimpleType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 12
nc 2
nop 3
dl 0
loc 19
ccs 15
cts 15
cp 1
crap 2
rs 9.4285
c 2
b 0
f 0
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 135
        return $this->makeCallbackCallback(
387 135
            $type,
388 135
            $node,
389 135
            $this->CallbackGeneratorMaybeCallMethodAgainstDOMNodeList(
390 135
                $type,
391
                [
392 135
                    'union' => 'loadUnion',
393 45
                    'list' => 'loadList',
394
                ]
395 45
            ),
396 90
            $callback
397 45
        );
398
    }
399
400 135
    protected function loadList(SimpleType $type, DOMElement $node)
401
    {
402 135
        if ($node->hasAttribute("itemType")) {
403
            /**
404
            * @var SimpleType $listType
405
            */
406 135
            $listType = $this->findSomeType($type, $node, 'itemType');
407 135
            $type->setList($listType);
408 45
        } else {
409
            $addCallback = function (SimpleType $list) use ($type) {
410 135
                $type->setList($list);
411 135
            };
412
413 135
            Type::loadTypeWithCallbackOnChildNodes(
414 135
                $this,
415 135
                $type->getSchema(),
416 135
                $node,
417 90
                $addCallback
418 45
            );
419
        }
420 135
    }
421
422 135
    protected function loadUnion(SimpleType $type, DOMElement $node)
423
    {
424 135
        if ($node->hasAttribute("memberTypes")) {
425 135
            $types = preg_split('/\s+/', $node->getAttribute("memberTypes"));
426 135
            foreach ($types as $typeName) {
427
                /**
428
                * @var SimpleType $unionType
429
                */
430 135
                $unionType = $this->findSomeTypeFromAttribute(
431 135
                    $type,
432 135
                    $node,
433 90
                    $typeName
434 45
                );
435 135
                $type->addUnion($unionType);
436 45
            }
437 45
        }
438
        $addCallback = function (SimpleType $unType) use ($type) {
439 135
            $type->addUnion($unType);
440 135
        };
441
442 135
        Type::loadTypeWithCallbackOnChildNodes(
443 135
            $this,
444 135
            $type->getSchema(),
445 135
            $node,
446 90
            $addCallback
447 45
        );
448 135
    }
449
450 135
    protected function loadExtensionChildNodes(
451
        BaseComplexType $type,
452
        DOMElement $node
453
    ) {
454 135
        static::againstDOMNodeList(
455 135
            $node,
456 135
            function (
457
                DOMElement $node,
458
                DOMElement $childNode
459
            ) use (
460 135
                $type
461
            ) {
462
                $commonMethods = [
463
                    [
464 135
                        ['sequence', 'choice', 'all'],
465 135
                        [$this, 'maybeLoadSequenceFromElementContainer'],
466
                        [
467 135
                            $type,
468 135
                            $childNode,
469 45
                        ],
470 45
                    ],
471 45
                ];
472
                $methods = [
473 90
                    'attribute' => [
474 135
                        [$type, 'addAttributeFromAttributeOrRef'],
475
                        [
476 135
                            $this,
477 135
                            $childNode,
478 135
                            $type->getSchema(),
479 90
                            $node
480 45
                        ]
481 45
                    ],
482
                    'attributeGroup' => [
483 45
                        (AttributeGroup::class . '::findSomethingLikeThis'),
484
                        [
485 135
                            $this,
486 135
                            $type->getSchema(),
487 135
                            $node,
488 135
                            $childNode,
489 90
                            $type
490 45
                        ]
491 45
                    ],
492 45
                ];
493
494 135
                $this->maybeCallCallableWithArgs(
495 135
                    $childNode,
496 135
                    $commonMethods,
497 90
                    $methods
498 45
                );
499 135
            }
500 45
        );
501 135
    }
502
503 135
    protected function loadExtension(BaseComplexType $type, DOMElement $node)
504
    {
505 135
        $extension = new Extension();
506 135
        $type->setExtension($extension);
507
508 135
        if ($node->hasAttribute("base")) {
509 135
            $this->findAndSetSomeBase(
510 135
                $type,
511 135
                $extension,
512 90
                $node
513 45
            );
514 45
        }
515 135
        $this->loadExtensionChildNodes($type, $node);
516 135
    }
517
518 135
    protected function loadRestriction(Type $type, DOMElement $node)
519
    {
520 135
        Restriction::loadRestriction($this, $type, $node);
521 135
    }
522
523
    /**
524
    * @return Closure
525
    */
526 135
    protected function loadElementDef(Schema $schema, DOMElement $node)
527
    {
528 135
        return $this->loadAttributeOrElementDef($schema, $node, false);
529
    }
530
}
531