Passed
Push — php-7.1 ( ed6d10...451fb2 )
by SignpostMarv
02:49
created

SchemaReaderLoadAbstraction::loadSimpleType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 12
c 2
b 0
f 0
nc 2
nop 3
dl 0
loc 22
ccs 12
cts 12
cp 1
crap 2
rs 9.2
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 45
    protected function loadAttributeGroup(
41
        Schema $schema,
42
        DOMElement $node
43
    ) : Closure {
44 45
        return AttributeGroup::loadAttributeGroup($this, $schema, $node);
45
    }
46
47 45
    protected function loadAttributeOrElementDef(
48
        Schema $schema,
49
        DOMElement $node,
50
        bool $attributeDef
51
    ) : Closure {
52 45
        $name = $node->getAttribute('name');
53 45
        if ($attributeDef) {
54 45
            $attribute = new AttributeDef($schema, $name);
55 45
            $schema->addAttribute($attribute);
56
        } else {
57 45
            $attribute = new ElementDef($schema, $name);
58 45
            $schema->addElement($attribute);
59
        }
60
61
62 45
        return function () use ($attribute, $node) : void {
63 45
            $this->fillItem($attribute, $node);
64 45
        };
65
    }
66
67 45
    protected function loadAttributeDef(
68
        Schema $schema,
69
        DOMElement $node
70
    ) : Closure {
71 45
        return $this->loadAttributeOrElementDef($schema, $node, true);
72
    }
73
74 45
    protected static function loadSequenceNormaliseMax(
75
        DOMElement $node,
76
        ? int $max
77
    ) : ? int {
78
        return
79
        (
80 45
            (is_int($max) && (bool) $max) ||
81 45
            $node->getAttribute("maxOccurs") == "unbounded" ||
82 45
            $node->getAttribute("maxOccurs") > 1
83
        )
84 45
            ? 2
85 45
            : null;
86
    }
87
88 45
    protected function loadSequence(
89
        ElementContainer $elementContainer,
90
        DOMElement $node,
91
        int $max = null
92
    ) : void {
93 45
        $max = static::loadSequenceNormaliseMax($node, $max);
94
95 45
        static::againstDOMNodeList(
96 45
            $node,
97 45
            function (
98
                DOMElement $node,
99
                DOMElement $childNode
100
            ) use (
101 45
                $elementContainer,
102 45
                $max
103
            ) : void {
104 45
                $this->loadSequenceChildNode(
105 45
                    $elementContainer,
106 45
                    $node,
107 45
                    $childNode,
108 45
                    $max
109
                );
110 45
            }
111
        );
112 45
    }
113
114 45
    protected function loadSequenceChildNode(
115
        ElementContainer $elementContainer,
116
        DOMElement $node,
117
        DOMElement $childNode,
118
        ? int $max
119
    ) : void {
120
        $commonMethods = [
121
            [
122 45
                ['sequence', 'choice', 'all'],
123 45
                [$this, 'loadSequenceChildNodeLoadSequence'],
124
                [
125 45
                    $elementContainer,
126 45
                    $childNode,
127 45
                    $max,
128
                ],
129
            ],
130
        ];
131
        $methods = [
132
            'element' => [
133 45
                [$this, 'loadSequenceChildNodeLoadElement'],
134
                [
135 45
                    $elementContainer,
136 45
                    $node,
137 45
                    $childNode,
138 45
                    $max
139
                ]
140
            ],
141
            'group' => [
142 45
                [$this, 'loadSequenceChildNodeLoadGroup'],
143
                [
144 45
                    $elementContainer,
145 45
                    $node,
146 45
                    $childNode
147
                ]
148
            ],
149
        ];
150
151 45
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
152 45
    }
153
154 45
    protected function loadSequenceChildNodeLoadSequence(
155
        ElementContainer $elementContainer,
156
        DOMElement $childNode,
157
        ? int $max
158
    ) : void {
159 45
        $this->loadSequence($elementContainer, $childNode, $max);
160 45
    }
161
162 45
    protected function loadSequenceChildNodeLoadElement(
163
        ElementContainer $elementContainer,
164
        DOMElement $node,
165
        DOMElement $childNode,
166
        ? int $max
167
    ) : void {
168 45
        if ($childNode->hasAttribute("ref")) {
169
            /**
170
            * @var ElementDef $referencedElement
171
            */
172 45
            $referencedElement = $this->findSomething('findElement', $elementContainer->getSchema(), $node, $childNode->getAttribute("ref"));
173 45
            $element = ElementRef::loadElementRef(
174 45
                $referencedElement,
175 45
                $childNode
176
            );
177
        } else {
178 45
            $element = Element::loadElement(
179 45
                $this,
180 45
                $elementContainer->getSchema(),
181 45
                $childNode
182
            );
183
        }
184 45
        if (is_int($max) && (bool) $max) {
185 45
            $element->setMax($max);
186
        }
187 45
        $elementContainer->addElement($element);
188 45
    }
189
190 45
    protected function loadSequenceChildNodeLoadGroup(
191
        ElementContainer $elementContainer,
192
        DOMElement $node,
193
        DOMElement $childNode
194
    ) : void {
195 45
        $this->addGroupAsElement(
196 45
            $elementContainer->getSchema(),
197 45
            $node,
198 45
            $childNode,
199 45
            $elementContainer
200
        );
201 45
    }
202
203 45
    protected function addGroupAsElement(
204
        Schema $schema,
205
        DOMElement $node,
206
        DOMElement $childNode,
207
        ElementContainer $elementContainer
208
    ) : void {
209
        /**
210
        * @var Group $referencedGroup
211
        */
212 45
        $referencedGroup = $this->findSomething(
213 45
            'findGroup',
214 45
            $schema,
215 45
            $node,
216 45
            $childNode->getAttribute("ref")
217
        );
218
219 45
        $group = GroupRef::loadGroupRef($referencedGroup, $childNode);
220 45
        $elementContainer->addElement($group);
221 45
    }
222
223 45
    protected function loadGroup(Schema $schema, DOMElement $node) : Closure
224
    {
225 45
        return Group::loadGroup($this, $schema, $node);
226
    }
227
228 45
    protected function loadComplexTypeBeforeCallbackCallback(
229
        Schema $schema,
230
        DOMElement $node
231
    ) : BaseComplexType {
232
        /**
233
        * @var bool $isSimple
234
        */
235 45
        $isSimple = false;
236
237 45
        static::againstDOMNodeList(
238 45
            $node,
239 45
            function (
240
                DOMElement $node,
241
                DOMElement $childNode
242
            ) use (
243 45
                & $isSimple
244
            ) : void {
245 45
                if ($isSimple) {
246 1
                    return;
247
                }
248 45
                if ($childNode->localName === "simpleContent") {
249 2
                    $isSimple = true;
250
                }
251 45
            }
252
        );
253
254 45
        $type = $isSimple ? new ComplexTypeSimpleContent($schema, $node->getAttribute("name")) : new ComplexType($schema, $node->getAttribute("name"));
255
256 45
        $type->setDoc(static::getDocumentation($node));
257 45
        if ($node->getAttribute("name")) {
258 45
            $schema->addType($type);
259
        }
260
261 45
        return $type;
262
    }
263
264 45
    protected function loadComplexType(
265
        Schema $schema,
266
        DOMElement $node,
267
        Closure $callback = null
268
    ) : Closure {
269 45
        $type = $this->loadComplexTypeBeforeCallbackCallback($schema, $node);
270
271 45
        return $this->makeCallbackCallback(
272 45
            $type,
273 45
            $node,
274 45
            function (
275
                DOMElement $node,
276
                DOMElement $childNode
277
            ) use(
278 45
                $schema,
279 45
                $type
280
            ) : void {
281 45
                $this->loadComplexTypeFromChildNode(
282 45
                    $type,
283 45
                    $node,
284 45
                    $childNode,
285 45
                    $schema
286
                );
287 45
            },
288 45
            $callback
289
        );
290
    }
291
292 45
    protected function loadComplexTypeFromChildNode(
293
        BaseComplexType $type,
294
        DOMElement $node,
295
        DOMElement $childNode,
296
        Schema $schema
297
    ) : void {
298
        $commonMethods = [
299
            [
300 45
                ['sequence', 'choice', 'all'],
301 45
                [$this, 'maybeLoadSequenceFromElementContainer'],
302
                [
303 45
                    $type,
304 45
                    $childNode,
305
                ],
306
            ],
307
        ];
308
        $methods = [
309 45
            'attribute' => [
310 45
                [$type, 'addAttributeFromAttributeOrRef'],
311
                [
312 45
                    $this,
313 45
                    $childNode,
314 45
                    $schema,
315 45
                    $node
316
                ]
317
            ],
318
            'attributeGroup' => [
319
                (AttributeGroup::class . '::findSomethingLikeThis'),
320
                [
321 45
                    $this,
322 45
                    $schema,
323 45
                    $node,
324 45
                    $childNode,
325 45
                    $type
326
                ]
327
            ],
328
        ];
329
        if (
330 45
            $type instanceof ComplexType
331
        ) {
332 45
            $methods['group'] = [
333 45
                [$this, 'addGroupAsElement'],
334
                [
335 45
                    $schema,
336 45
                    $node,
337 45
                    $childNode,
338 45
                    $type
339
                ]
340
            ];
341
        }
342
343 45
        $this->maybeCallCallableWithArgs($childNode, $commonMethods, $methods);
344 45
    }
345
346 45
    protected function loadSimpleType(
347
        Schema $schema,
348
        DOMElement $node,
349
        Closure $callback = null
350
    ) : Closure {
351 45
        $type = new SimpleType($schema, $node->getAttribute("name"));
352 45
        $type->setDoc(static::getDocumentation($node));
353 45
        if ($node->getAttribute("name")) {
354 45
            $schema->addType($type);
355
        }
356
357 45
        return $this->makeCallbackCallback(
358 45
            $type,
359 45
            $node,
360 45
            $this->CallbackGeneratorMaybeCallMethodAgainstDOMNodeList(
361 45
                $type,
362
                [
363 45
                    'union' => 'loadUnion',
364
                    'list' => 'loadList',
365
                ]
366
            ),
367 45
            $callback
368
        );
369
    }
370
371 45
    protected function loadList(SimpleType $type, DOMElement $node) : void
372
    {
373 45
        if ($node->hasAttribute("itemType")) {
374
            /**
375
            * @var SimpleType $listType
376
            */
377 45
            $listType = $this->findSomeType($type, $node, 'itemType');
378 45
            $type->setList($listType);
379
        } else {
380 45
            $addCallback = function (SimpleType $list) use ($type) : void {
381 45
                $type->setList($list);
382 45
            };
383
384 45
            Type::loadTypeWithCallbackOnChildNodes(
385 45
                $this,
386 45
                $type->getSchema(),
387 45
                $node,
388 45
                $addCallback
389
            );
390
        }
391 45
    }
392
393 45
    protected function loadUnion(SimpleType $type, DOMElement $node) : void
394
    {
395 45
        if ($node->hasAttribute("memberTypes")) {
396 45
            $types = preg_split('/\s+/', $node->getAttribute("memberTypes"));
397 45
            foreach ($types as $typeName) {
398
                /**
399
                * @var SimpleType $unionType
400
                */
401 45
                $unionType = $this->findSomeTypeFromAttribute(
402 45
                    $type,
403 45
                    $node,
404 45
                    $typeName
405
                );
406 45
                $type->addUnion($unionType);
407
            }
408
        }
409 45
        $addCallback = function (SimpleType $unType) use ($type) : void {
410 45
            $type->addUnion($unType);
411 45
        };
412
413 45
        Type::loadTypeWithCallbackOnChildNodes(
414 45
            $this,
415 45
            $type->getSchema(),
416 45
            $node,
417 45
            $addCallback
418
        );
419 45
    }
420
421 45
    protected function loadExtensionChildNodes(
422
        BaseComplexType $type,
423
        DOMElement $node
424
    ) : void {
425 45
        static::againstDOMNodeList(
426 45
            $node,
427 45
            function (
428
                DOMElement $node,
429
                DOMElement $childNode
430
            ) use (
431 45
                $type
432
            ) : void {
433
                $commonMethods = [
434
                    [
435 45
                        ['sequence', 'choice', 'all'],
436 45
                        [$this, 'maybeLoadSequenceFromElementContainer'],
437
                        [
438 45
                            $type,
439 45
                            $childNode,
440
                        ],
441
                    ],
442
                ];
443
                $methods = [
444 45
                    'attribute' => [
445 45
                        [$type, 'addAttributeFromAttributeOrRef'],
446
                        [
447 45
                            $this,
448 45
                            $childNode,
449 45
                            $type->getSchema(),
450 45
                            $node
451
                        ]
452
                    ],
453
                    'attributeGroup' => [
454
                        (AttributeGroup::class . '::findSomethingLikeThis'),
455
                        [
456 45
                            $this,
457 45
                            $type->getSchema(),
458 45
                            $node,
459 45
                            $childNode,
460 45
                            $type
461
                        ]
462
                    ],
463
                ];
464
465 45
                $this->maybeCallCallableWithArgs(
466 45
                    $childNode,
467 45
                    $commonMethods,
468 45
                    $methods
469
                );
470 45
            }
471
        );
472 45
    }
473
474 45
    protected function loadExtension(
475
        BaseComplexType $type,
476
        DOMElement $node
477
    ) : void {
478 45
        $extension = new Extension();
479 45
        $type->setExtension($extension);
480
481 45
        if ($node->hasAttribute("base")) {
482 45
            $this->findAndSetSomeBase(
483 45
                $type,
484 45
                $extension,
485 45
                $node
486
            );
487
        }
488 45
        $this->loadExtensionChildNodes($type, $node);
489 45
    }
490
491 45
    protected function loadRestriction(Type $type, DOMElement $node) : void
492
    {
493 45
        Restriction::loadRestriction($this, $type, $node);
494 45
    }
495
496 45
    protected function loadElementDef(
497
        Schema $schema,
498
        DOMElement $node
499
    ) : Closure {
500 45
        return $this->loadAttributeOrElementDef($schema, $node, false);
501
    }
502
}
503