Completed
Push — master ( 55881e...c51bd4 )
by SignpostMarv
03:05
created

Schema::findSomethingNoThrow()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

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