Completed
Push — master ( 58aafb...63afff )
by Asmir
14s queued 11s
created

Schema::findSomething()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 2

Importance

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