Passed
Push — static-analysis ( a9f152...8be703 )
by SignpostMarv
02:25
created

Schema   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 487
Duplicated Lines 0 %

Test Coverage

Coverage 84.62%

Importance

Changes 0
Metric Value
wmc 51
c 0
b 0
f 0
dl 0
loc 487
ccs 121
cts 143
cp 0.8462
rs 8.3206

35 Methods

Rating   Name   Duplication   Size   Complexity  
A findAttributeGroup() 0 8 1
A findAttribute() 0 8 1
A getElements() 0 3 1
A getTypes() 0 3 1
A findSomethingNoThrowSchemas() 0 17 4
A getElementsQualification() 0 3 1
A getGroups() 0 3 1
B findSomethingNoThrow() 0 31 4
A findType() 0 8 1
A setDoc() 0 3 1
A getGroup() 0 7 2
A getDoc() 0 3 1
A setSchemaThingsFromNode() 0 14 3
A getAttribute() 0 7 2
A setElementsQualification() 0 3 1
A getAttributes() 0 3 1
A addType() 0 3 1
A addAttribute() 0 3 1
A setAttributesQualification() 0 3 1
A getAttributeGroups() 0 3 1
A addSchema() 0 15 3
A addAttributeGroup() 0 3 1
A addGroup() 0 3 1
A findElement() 0 8 1
A getSchemas() 0 3 1
A findGroup() 0 8 1
A __toString() 0 3 1
A addElement() 0 3 1
A getElement() 0 7 2
A getTargetNamespace() 0 3 1
A findSomething() 0 14 2
A getAttributesQualification() 0 3 1
A getAttributeGroup() 0 7 2
A setTargetNamespace() 0 3 1
A getType() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like Schema often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Schema, and based on these observations, apply Extract Interface, too.

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