Passed
Push — php-7.1 ( a96878...0e63f5 )
by SignpostMarv
10:37 queued 02:26
created

Schema::hasLoadedFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 9
ccs 0
cts 0
cp 0
crap 12
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GoetasWebservices\XML\XSDReader\Schema;
6
7
use DOMElement;
8
use GoetasWebservices\XML\XSDReader\SchemaReader;
9
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
10
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
11
use GoetasWebservices\XML\XSDReader\Schema\Element\Group;
12
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
13
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
14
use GoetasWebservices\XML\XSDReader\Schema\Exception\TypeNotFoundException;
15 45
use GoetasWebservices\XML\XSDReader\Schema\Exception\SchemaException;
16
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem;
17
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeDef;
18
19
class Schema
20
{
21 45
    /**
22 45
     * @param bool[] $calling
23
     */
24 45
    protected function findSomethingNoThrow(
25 45
        string $getter,
26
        string $name,
27 45
        string $namespace = null,
28
        array &$calling = array()
29
    ): ? SchemaItem {
30
        $calling[spl_object_hash($this)] = true;
31
        $cid = "$getter, $name, $namespace";
32 45
33
        if (isset($this->typeCache[$cid])) {
34 45
            return $this->typeCache[$cid];
35 45
        } elseif (
36
            $this->getTargetNamespace() === $namespace
37
        ) {
38
            /**
39 45
             * @var SchemaItem|null
40 45
             */
41 45
            $item = $this->$getter($name);
42 45
43 45
            if ($item instanceof SchemaItem) {
44 45
                return $this->typeCache[$cid] = $item;
45 45
            }
46
        }
47
48
        return $this->findSomethingNoThrowSchemas(
49
            $this->getSchemas(),
50
            $cid,
51
            $getter,
52
            $name,
53 45
            $namespace,
54
            $calling
55
        );
56
    }
57
58
    /**
59
     * @param Schema[] $schemas
60
     * @param bool[]   $calling
61 45
     */
62 45
    protected function findSomethingNoThrowSchemas(
63
        array $schemas,
64
        string $cid,
65
        string $getter,
66 45
        string $name,
67
        string $namespace = null,
68 45
        array &$calling = array()
69 45
    ): ? SchemaItem {
70
        foreach ($schemas as $childSchema) {
71
            if (!isset($calling[spl_object_hash($childSchema)])) {
72
                /**
73
                 * @var SchemaItem|null
74 7
                 */
75
                $in = $childSchema->findSomethingNoThrow($getter, $name, $namespace, $calling);
76
77
                if ($in instanceof SchemaItem) {
78
                    return $this->typeCache[$cid] = $in;
79
                }
80
            }
81 45
        }
82
83
        return null;
84
    }
85
86
    /**
87 45
     * @param bool[] $calling
88 45
     *
89 45
     * @throws TypeNotFoundException
90 45
     */
91 45
    protected function findSomething(
92
        string $getter,
93
        string $name,
94 45
        string $namespace = null,
95 45
        array &$calling = array()
96
    ): SchemaItem {
97
        $in = $this->findSomethingNoThrow(
98 5
            $getter,
99
            $name,
100
            $namespace,
101
            $calling
102
        );
103
104
        if ($in instanceof SchemaItem) {
105
            return $in;
106 45
        }
107
108
        throw new TypeNotFoundException(
109
            sprintf("Can't find the %s named {%s}#%s.", substr($getter, 3), (string) $namespace, $name)
110
        );
111 45
    }
112
113 45
    /**
114
     * @var bool
115 45
     */
116 45
    protected $elementsQualification = false;
117
118
    /**
119 45
     * @var bool
120 45
     */
121 45
    protected $attributesQualification = false;
122
123
    /**
124 45
     * @var null|string
125
     */
126 45
    protected $targetNamespace;
127
128
    /**
129
     * @var Schema[]
130
     */
131
    protected $schemas = array();
132 1
133
    /**
134
     * @var Type[]
135
     */
136
    protected $types = array();
137
138
    /**
139
     * @var ElementDef[]
140
     */
141 1
    protected $elements = array();
142 1
143 1
    /**
144
     * @var Group[]
145
     */
146 1
    protected $groups = array();
147
148
    /**
149
     * @var AttributeGroup[]
150
     */
151 1
    protected $attributeGroups = array();
152
153
    /**
154
     * @var AttributeDef[]
155
     */
156
    protected $attributes = array();
157 1
158
    /**
159
     * @var string|null
160
     */
161
    protected $doc;
162
163
    /**
164
     * @var \GoetasWebservices\XML\XSDReader\Schema\SchemaItem[]
165
     */
166 1
    protected $typeCache = array();
167
168 1
    public function getElementsQualification(): bool
169 1
    {
170 1
        return $this->elementsQualification;
171 1
    }
172 1
173 1
    public function setElementsQualification(
174
        bool $elementsQualification
175 1
    ): void {
176 1
        $this->elementsQualification = $elementsQualification;
177
    }
178 1
179 1
    public function getAttributesQualification(): bool
180 1
    {
181
        return $this->attributesQualification;
182
    }
183
184
    public function setAttributesQualification(
185
        bool $attributesQualification
186
    ): void {
187
        $this->attributesQualification = $attributesQualification;
188
    }
189
190
    /**
191
     * @return null|string
192
     */
193 1
    public function getTargetNamespace(): ? string
194
    {
195 1
        return $this->targetNamespace;
196 1
    }
197 1
198 1
    /**
199 1
     * @param null|string $targetNamespace
200
     */
201
    public function setTargetNamespace(? string $targetNamespace): void
202 1
    {
203
        $this->targetNamespace = $targetNamespace;
204 1
    }
205
206
    /**
207
     * @return Type[]
208
     */
209
    public function getTypes(): array
210
    {
211
        return $this->types;
212
    }
213
214
    /**
215
     * @return ElementDef[]
216
     */
217
    public function getElements(): array
218
    {
219
        return $this->elements;
220
    }
221
222
    /**
223
     * @return Schema[]
224
     */
225
    public function getSchemas(): array
226
    {
227
        return $this->schemas;
228
    }
229
230
    /**
231
     * @return AttributeDef[]
232
     */
233
    public function getAttributes(): array
234
    {
235
        return $this->attributes;
236
    }
237
238
    /**
239
     * @return Group[]
240
     */
241
    public function getGroups(): array
242
    {
243
        return $this->groups;
244
    }
245
246
    public function getDoc(): ? string
247
    {
248
        return $this->doc;
249
    }
250
251
    public function setDoc(string $doc): void
252
    {
253
        $this->doc = $doc;
254
    }
255
256
    public function addType(Type $type): void
257
    {
258
        $this->types[$type->getName()] = $type;
259
    }
260
261
    public function addElement(ElementDef $element): void
262
    {
263
        $this->elements[$element->getName()] = $element;
264
    }
265
266
    public function addSchema(self $schema, string $namespace = null): void
267
    {
268
        if ($namespace !== null) {
269
            if ($schema->getTargetNamespace() !== $namespace) {
270
                throw new SchemaException(
271
                    sprintf(
272
                        "The target namespace ('%s') for schema, does not match the declared namespace '%s'",
273
                        (string) $schema->getTargetNamespace(),
274
                        $namespace
275
                    )
276
                );
277
            }
278
            $this->schemas[$namespace] = $schema;
279
        } else {
280
            $this->schemas[] = $schema;
281
        }
282
    }
283
284
    public function addAttribute(AttributeDef $attribute): void
285
    {
286
        $this->attributes[$attribute->getName()] = $attribute;
287
    }
288
289
    public function addGroup(Group $group): void
290
    {
291
        $this->groups[$group->getName()] = $group;
292
    }
293
294
    public function addAttributeGroup(AttributeGroup $group): void
295
    {
296
        $this->attributeGroups[$group->getName()] = $group;
297
    }
298
299
    /**
300
     * @return AttributeGroup[]
301
     */
302
    public function getAttributeGroups(): array
303
    {
304
        return $this->attributeGroups;
305
    }
306
307
    public function getGroup(string $name): ? Group
308
    {
309
        if (isset($this->groups[$name])) {
310
            return $this->groups[$name];
311
        }
312
313
        return null;
314
    }
315
316
    /**
317
     * @param string $name
318
     *
319
     * @return ElementItem|false
320
     */
321
    public function getElement($name)
322
    {
323
        if (isset($this->elements[$name])) {
324
            return $this->elements[$name];
325
        }
326
327
        return false;
328
    }
329
330
    /**
331
     * @param string $name
332
     *
333
     * @return Type|false
334
     */
335
    public function getType($name)
336
    {
337
        if (isset($this->types[$name])) {
338
            return $this->types[$name];
339
        }
340
341
        return false;
342
    }
343
344
    /**
345
     * @param string $name
346
     *
347
     * @return AttributeItem|false
348
     */
349
    public function getAttribute($name)
350
    {
351
        if (isset($this->attributes[$name])) {
352
            return $this->attributes[$name];
353
        }
354
355
        return false;
356
    }
357
358
    /**
359
     * @param string $name
360
     *
361
     * @return AttributeGroup|false
362
     */
363
    public function getAttributeGroup($name)
364
    {
365
        if (isset($this->attributeGroups[$name])) {
366
            return $this->attributeGroups[$name];
367
        }
368
369
        return false;
370
    }
371
372
    public function __toString()
373
    {
374
        return sprintf('Target namespace %s', (string) $this->getTargetNamespace());
375
    }
376
377
    public function findType(string $name, string $namespace = null): Type
378
    {
379
        /**
380
         * @var Type
381
         */
382
        $out = $this->findSomething('getType', $name, $namespace);
383
384
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type GoetasWebservices\XML\XSDReader\Schema\SchemaItem which includes types incompatible with the type-hinted return GoetasWebservices\XML\XSDReader\Schema\Type\Type.
Loading history...
385
    }
386
387
    public function findGroup(string $name, string $namespace = null): Group
388
    {
389
        /**
390
         * @var Group
391
         */
392
        $out = $this->findSomething('getGroup', $name, $namespace);
393
394
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type GoetasWebservices\XML\XSDReader\Schema\SchemaItem which includes types incompatible with the type-hinted return GoetasWebservices\XML\XS...er\Schema\Element\Group.
Loading history...
395
    }
396
397
    public function findElement(string $name, string $namespace = null): ElementDef
398
    {
399
        /**
400
         * @var ElementDef
401
         */
402
        $out = $this->findSomething('getElement', $name, $namespace);
403
404
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type GoetasWebservices\XML\XSDReader\Schema\SchemaItem which includes types incompatible with the type-hinted return GoetasWebservices\XML\XS...hema\Element\ElementDef.
Loading history...
405
    }
406
407
    public function findAttribute(string $name, string $namespace = null): AttributeItem
408
    {
409
        /**
410
         * @var AttributeItem
411
         */
412
        $out = $this->findSomething('getAttribute', $name, $namespace);
413
414
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type GoetasWebservices\XML\XSDReader\Schema\SchemaItem which includes types incompatible with the type-hinted return GoetasWebservices\XML\XS...Attribute\AttributeItem.
Loading history...
415
    }
416
417
    public function findAttributeGroup(string $name, string $namespace = null): AttributeGroup
418
    {
419
        /**
420
         * @var AttributeGroup
421
         */
422
        $out = $this->findSomething('getAttributeGroup', $name, $namespace);
423
424
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out returns the type GoetasWebservices\XML\XSDReader\Schema\SchemaItem which includes types incompatible with the type-hinted return GoetasWebservices\XML\XS...\Schema\Attribute\Group.
Loading history...
425
    }
426
427
    public function setSchemaThingsFromNode(
428
        DOMElement $node,
429
        self $parent = null
430
    ): void {
431
        $this->setDoc(SchemaReader::getDocumentation($node));
432
433
        if ($node->hasAttribute('targetNamespace')) {
434
            $this->setTargetNamespace($node->getAttribute('targetNamespace'));
435
        } elseif ($parent) {
436
            $this->setTargetNamespace($parent->getTargetNamespace());
437
        }
438
        $this->setElementsQualification($node->getAttribute('elementFormDefault') == 'qualified');
439
        $this->setAttributesQualification($node->getAttribute('attributeFormDefault') == 'qualified');
440
        $this->setDoc(SchemaReader::getDocumentation($node));
441
    }
442
}
443