Passed
Push — static-analysis ( e3e805...309dd4 )
by SignpostMarv
03:34
created

SchemaReaderLoadAbstraction::loadAttributeGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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