AbstractElement   B
last analyzed

Complexity

Total Complexity 46

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 76
dl 0
loc 302
rs 8.72
c 0
b 0
f 0
wmc 46

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getLocalType() 0 3 1
A getDefault() 0 3 1
F toXML() 0 63 15
A getType() 0 3 1
A getBlock() 0 3 1
A getFinal() 0 3 1
A getFixed() 0 3 1
A getIdentityConstraint() 0 3 1
C isEmptyElement() 0 18 16
A __construct() 0 56 4
A getForm() 0 3 1
A getNillable() 0 3 1
A getSubstitutionGroup() 0 3 1
A getAbstract() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractElement 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 AbstractElement, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XMLSchema\XML;
6
7
use DOMElement;
8
use SimpleSAML\XML\Assert\Assert;
9
use SimpleSAML\XML\Constants as C;
10
use SimpleSAML\XMLSchema\Exception\{ProtocolViolationException, SchemaViolationException};
11
use SimpleSAML\XMLSchema\Type\{BooleanValue, IDValue, NCNameValue, QNameValue, StringValue};
12
use SimpleSAML\XMLSchema\Type\Schema\{
13
    BlockSetValue,
14
    DerivationSetValue,
15
    FormChoiceValue,
16
    MaxOccursValue,
17
    MinOccursValue,
18
};
19
use SimpleSAML\XMLSchema\XML\Interface\IdentityConstraintInterface;
20
use SimpleSAML\XMLSchema\XML\Trait\{DefRefTrait, OccursTrait};
21
22
use function strval;
23
24
/**
25
 * Abstract class representing the element-type.
26
 *
27
 * @package simplesamlphp/xml-common
28
 */
29
abstract class AbstractElement extends AbstractAnnotated
30
{
31
    use DefRefTrait;
32
    use OccursTrait;
33
34
    /**
35
     * Element constructor
36
     *
37
     * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $name
38
     * @param \SimpleSAML\XMLSchema\Type\QNameValue|null $reference
39
     * @param \SimpleSAML\XMLSchema\XML\LocalSimpleType|\SimpleSAML\XMLSchema\XML\LocalComplexType|null $localType
40
     * @param array<\SimpleSAML\XMLSchema\XML\Interface\IdentityConstraintInterface> $identityConstraint
41
     * @param \SimpleSAML\XMLSchema\Type\QNameValue|null $type
42
     * @param \SimpleSAML\XMLSchema\Type\QNameValue|null $substitutionGroup
43
     * @param \SimpleSAML\XMLSchema\Type\Schema\MinOccursValue|null $minOccurs
44
     * @param \SimpleSAML\XMLSchema\Type\Schema\MaxOccursValue|null $maxOccurs
45
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $default
46
     * @param \SimpleSAML\XMLSchema\Type\StringValue|null $fixed
47
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $nillable
48
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $abstract
49
     * @param \SimpleSAML\XMLSchema\Type\Schema\DerivationSetValue|null $final
50
     * @param \SimpleSAML\XMLSchema\Type\Schema\BlockSetValue|null $block
51
     * @param \SimpleSAML\XMLSchema\Type\Schema\FormChoiceValue|null $form
52
     * @param \SimpleSAML\XMLSchema\XML\Annotation|null $annotation
53
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id
54
     * @param array<\SimpleSAML\XML\Attribute> $namespacedAttributes
55
     */
56
    public function __construct(
57
        ?NCNameValue $name = null,
58
        ?QNameValue $reference = null,
59
        protected LocalSimpleType|LocalComplexType|null $localType = null,
60
        protected array $identityConstraint = [],
61
        protected ?QNameValue $type = null,
62
        protected ?QNameValue $substitutionGroup = null,
63
        ?MinOccursValue $minOccurs = null,
64
        ?MaxOccursValue $maxOccurs = null,
65
        protected ?StringValue $default = null,
66
        protected ?StringValue $fixed = null,
67
        protected ?BooleanValue $nillable = null,
68
        protected ?BooleanValue $abstract = null,
69
        protected ?DerivationSetValue $final = null,
70
        protected ?BlockSetValue $block = null,
71
        protected ?FormChoiceValue $form = null,
72
        ?Annotation $annotation = null,
73
        ?IDValue $id = null,
74
        array $namespacedAttributes = [],
75
    ) {
76
        Assert::maxCount($identityConstraint, C::UNBOUNDED_LIMIT);
77
        Assert::allIsInstanceOf(
78
            $identityConstraint,
79
            IdentityConstraintInterface::class,
80
            SchemaViolationException::class,
81
        );
82
83
        /**
84
         * An element is declared by either: a name and a type (either nested or referenced via the type attribute)
85
         * or a ref to an existing element declaration
86
         *
87
         * type and ref are mutually exclusive.
88
         * name and ref are mutually exclusive, one is required
89
         */
90
        Assert::oneOf(null, [$type, $reference], ProtocolViolationException::class);
91
        Assert::oneOf(null, [$name, $reference], ProtocolViolationException::class);
92
        Assert::false(is_null($name) && is_null($reference), ProtocolViolationException::class);
93
94
        /**
95
         * default and fixed are mutually exclusive
96
         */
97
        Assert::oneOf(null, [$default, $fixed], ProtocolViolationException::class);
98
99
        /**
100
         * simpleType or complexType only if no type|ref attribute
101
         */
102
        if ($localType !== null) {
103
            Assert::true(is_null($type) || is_null($reference), ProtocolViolationException::class);
104
        }
105
106
        parent::__construct($annotation, $id, $namespacedAttributes);
107
108
        $this->setName($name);
109
        $this->setReference($reference);
110
        $this->setMinOccurs($minOccurs);
111
        $this->setMaxOccurs($maxOccurs);
112
    }
113
114
115
    /**
116
     * Collect the value of the localType-property
117
     *
118
     * @return \SimpleSAML\XMLSchema\XML\LocalSimpleType|\SimpleSAML\XMLSchema\XML\LocalComplexType|null
119
     */
120
    public function getLocalType(): LocalSimpleType|LocalComplexType|null
121
    {
122
        return $this->localType;
123
    }
124
125
126
    /**
127
     * Collect the value of the identityConstraint-property
128
     *
129
     * @return array<\SimpleSAML\XMLSchema\XML\Interface\IdentityConstraintInterface>
130
     */
131
    public function getIdentityConstraint(): array
132
    {
133
        return $this->identityConstraint;
134
    }
135
136
137
    /**
138
     * Collect the value of the type-property
139
     *
140
     * @return \SimpleSAML\XMLSchema\Type\QNameValue|null
141
     */
142
    public function getType(): ?QNameValue
143
    {
144
        return $this->type;
145
    }
146
147
148
    /**
149
     * Collect the value of the substitutionGroup-property
150
     *
151
     * @return \SimpleSAML\XMLSchema\Type\QNameValue|null
152
     */
153
    public function getSubstitutionGroup(): ?QNameValue
154
    {
155
        return $this->substitutionGroup;
156
    }
157
158
159
    /**
160
     * Collect the value of the default-property
161
     *
162
     * @return \SimpleSAML\XMLSchema\Type\StringValue|null
163
     */
164
    public function getDefault(): ?StringValue
165
    {
166
        return $this->default;
167
    }
168
169
170
    /**
171
     * Collect the value of the fixed-property
172
     *
173
     * @return \SimpleSAML\XMLSchema\Type\StringValue|null
174
     */
175
    public function getFixed(): ?StringValue
176
    {
177
        return $this->fixed;
178
    }
179
180
181
    /**
182
     * Collect the value of the nillable-property
183
     *
184
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
185
     */
186
    public function getNillable(): ?BooleanValue
187
    {
188
        return $this->nillable;
189
    }
190
191
192
    /**
193
     * Collect the value of the abstract-property
194
     *
195
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
196
     */
197
    public function getAbstract(): ?BooleanValue
198
    {
199
        return $this->abstract;
200
    }
201
202
203
    /**
204
     * Collect the value of the final-property
205
     *
206
     * @return \SimpleSAML\XMLSchema\Type\Schema\DerivationSetValue|null
207
     */
208
    public function getFinal(): ?DerivationSetValue
209
    {
210
        return $this->final;
211
    }
212
213
214
    /**
215
     * Collect the value of the block-property
216
     *
217
     * @return \SimpleSAML\XMLSchema\Type\Schema\BlockSetValue|null
218
     */
219
    public function getBlock(): ?BlockSetValue
220
    {
221
        return $this->block;
222
    }
223
224
225
    /**
226
     * Collect the value of the form-property
227
     *
228
     * @return \SimpleSAML\XMLSchema\Type\Schema\FormChoiceValue|null
229
     */
230
    public function getForm(): ?FormChoiceValue
231
    {
232
        return $this->form;
233
    }
234
235
236
    /**
237
     * Test if an object, at the state it's in, would produce an empty XML-element
238
     *
239
     * @return bool
240
     */
241
    public function isEmptyElement(): bool
242
    {
243
        return parent::isEmptyElement() &&
244
            empty($this->getName()) &&
245
            empty($this->getReference()) &&
246
            empty($this->getLocalType()) &&
247
            empty($this->getIdentityConstraint()) &&
248
            empty($this->getType()) &&
249
            empty($this->getSubstitutionGroup()) &&
250
            empty($this->getMinOccurs()) &&
251
            empty($this->getMaxOccurs()) &&
252
            empty($this->getDefault()) &&
253
            empty($this->getFixed()) &&
254
            empty($this->getNillable()) &&
255
            empty($this->getAbstract()) &&
256
            empty($this->getFinal()) &&
257
            empty($this->getBlock()) &&
258
            empty($this->getForm());
259
    }
260
261
262
    /**
263
     * Add this Annotated to an XML element.
264
     *
265
     * @param \DOMElement|null $parent The element we should append this Annotated to.
266
     * @return \DOMElement
267
     */
268
    public function toXML(?DOMElement $parent = null): DOMElement
269
    {
270
        $e = parent::toXML($parent);
271
272
        if ($this->getName() !== null) {
273
            $e->setAttribute('name', strval($this->getName()));
274
        }
275
276
        if ($this->getReference() !== null) {
277
            $e->setAttribute('ref', strval($this->getReference()));
278
        }
279
280
        if ($this->getType() !== null) {
281
            $e->setAttribute('type', strval($this->getType()));
282
        }
283
284
        if ($this->getSubstitutionGroup() !== null) {
285
            $e->setAttribute('substitutionGroup', strval($this->getSubstitutionGroup()));
286
        }
287
288
        if ($this->getMinOccurs() !== null) {
289
            $e->setAttribute('minOccurs', strval($this->getMinOccurs()));
290
        }
291
292
        if ($this->getMaxOccurs() !== null) {
293
            $e->setAttribute('maxOccurs', strval($this->getMaxOccurs()));
294
        }
295
296
        if ($this->getDefault() !== null) {
297
            $e->setAttribute('default', strval($this->getDefault()));
298
        }
299
300
        if ($this->getFixed() !== null) {
301
            $e->setAttribute('fixed', strval($this->getFixed()));
302
        }
303
304
        if ($this->getNillable() !== null) {
305
            $e->setAttribute('nillable', strval($this->getNillable()));
306
        }
307
308
        if ($this->getAbstract() !== null) {
309
            $e->setAttribute('abstract', strval($this->getAbstract()));
310
        }
311
312
        if ($this->getFinal() !== null) {
313
            $e->setAttribute('final', strval($this->getFinal()));
314
        }
315
316
        if ($this->getBlock() !== null) {
317
            $e->setAttribute('block', strval($this->getBlock()));
318
        }
319
320
        if ($this->getForm() !== null) {
321
            $e->setAttribute('form', strval($this->getForm()));
322
        }
323
324
        $this->getLocalType()?->toXML($e);
325
326
        foreach ($this->getIdentityConstraint() as $identityConstraint) {
327
            $identityConstraint->toXML($e);
328
        }
329
330
        return $e;
331
    }
332
}
333