Passed
Push — master ( e83944...4f4375 )
by Tim
01:40
created

Chunk::getOptionalBooleanAttribute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML;
6
7
use DOMDocument;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\XML\Exception\MissingAttributeException;
11
use SimpleSAML\XML\Exception\SchemaViolationException;
12
use SimpleSAML\XML\SerializableElementTrait;
13
use SimpleSAML\XML\Utils;
14
15
use function func_num_args;
16
use function in_array;
17
use function intval;
18
19
/**
20
 * Serializable class used to hold an XML element.
21
 *
22
 * @package simplesamlphp/xml-common
23
 */
24
final class Chunk implements ElementInterface, SerializableElementInterface
25
{
26
    use SerializableElementTrait;
27
28
29
    /**
30
     * The localName of the element.
31
     *
32
     * @var string
33
     */
34
    protected string $localName;
35
36
    /**
37
     * The namespaceURI of this element.
38
     *
39
     * @var string|null
40
     */
41
    protected ?string $namespaceURI;
42
43
    /**
44
     * The prefix of this element.
45
     *
46
     * @var string|null
47
     */
48
    protected ?string $prefix;
49
50
51
    /**
52
     * Create an XML Chunk from a copy of the given \DOMElement.
53
     *
54
     * @param \DOMElement $xml The element we should copy.
55
     */
56
    public function __construct(
57
        protected DOMElement $xml
58
    ) {
59
        $this->setLocalName($xml->localName);
60
        $this->setNamespaceURI($xml->namespaceURI);
61
        $this->setPrefix($xml->prefix);
62
    }
63
64
65
    /**
66
     * Collect the value of the localName-property
67
     *
68
     * @return string
69
     */
70
    public function getLocalName(): string
71
    {
72
        return $this->localName;
73
    }
74
75
76
    /**
77
     * Set the value of the localName-property
78
     *
79
     * @param string $localName
80
     * @throws \SimpleSAML\Assert\AssertionFailedException if $localName is an empty string
81
     */
82
    public function setLocalName(string $localName): void
83
    {
84
        Assert::validNCName($localName, SchemaViolationException::class); // Covers the empty string
85
        $this->localName = $localName;
86
    }
87
88
89
    /**
90
     * Collect the value of the namespaceURI-property
91
     *
92
     * @return string|null
93
     */
94
    public function getNamespaceURI(): ?string
95
    {
96
        return $this->namespaceURI;
97
    }
98
99
100
    /**
101
     * Set the value of the namespaceURI-property
102
     *
103
     * @param string|null $namespaceURI
104
     */
105
    protected function setNamespaceURI(string $namespaceURI = null): void
106
    {
107
        Assert::nullOrValidURI($namespaceURI, SchemaViolationException::class);
108
        $this->namespaceURI = $namespaceURI;
109
    }
110
111
112
    /**
113
     * Get this \DOMElement.
114
     *
115
     * @return \DOMElement This element.
116
     */
117
    public function getXML(): DOMElement
118
    {
119
        return $this->xml;
120
    }
121
122
123
    /**
124
     * Collect the value of the prefix-property
125
     *
126
     * @return string|null
127
     */
128
    public function getPrefix(): ?string
129
    {
130
        return $this->prefix;
131
    }
132
133
134
    /**
135
     * Set the value of the prefix-property
136
     *
137
     * @param string|null $prefix
138
     */
139
    protected function setPrefix(string $prefix = null): void
140
    {
141
        $this->prefix = $prefix;
142
    }
143
144
145
    /**
146
     * Get the XML qualified name (prefix:name, or just name when not prefixed)
147
     *  of the element represented by this class.
148
     *
149
     * @return string
150
     */
151
    public function getQualifiedName(): string
152
    {
153
        $prefix = $this->getPrefix();
154
155
        if (is_null($prefix)) {
156
            return $this->getLocalName();
157
        } else {
158
            return $prefix . ':' . $this->getLocalName();
159
        }
160
    }
161
162
163
    /**
164
     * @param \DOMElement $xml The element where we should search for the attribute.
165
     * @param string      $name The name of the attribute.
166
     * @return string
167
     *
168
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the attribute is missing from the element
169
     */
170
    public static function getAttribute(DOMElement $xml, string $name): string
171
    {
172
        Assert::true(
173
            $xml->hasAttribute($name),
174
            'Missing \'' . $name . '\' attribute on ' . $xml->prefix . ':' . $xml->localName . '.',
175
            MissingAttributeException::class,
176
        );
177
178
        return $xml->getAttribute($name);
179
    }
180
181
182
    /**
183
     * @param \DOMElement $xml The element where we should search for the attribute.
184
     * @param string      $name The name of the attribute.
185
     * @param string|null $default The default to return in case the attribute does not exist and it is optional.
186
     * @return string|null
187
     */
188
    public static function getOptionalAttribute(DOMElement $xml, string $name, ?string $default = null): ?string
189
    {
190
        if (!$xml->hasAttribute($name)) {
191
            return $default;
192
        }
193
194
        return $xml->getAttribute($name);
195
    }
196
197
198
    /**
199
     * @param \DOMElement $xml The element where we should search for the attribute.
200
     * @param string      $name The name of the attribute.
201
     * @return bool
202
     *
203
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the attribute is missing from the element
204
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not a boolean
205
     */
206
    public static function getBooleanAttribute(DOMElement $xml, string $name): bool
207
    {
208
        $value = self::getAttribute($xml, $name);
209
210
        Assert::oneOf(
211
            $value,
212
            ['0', '1', 'false', 'true'],
213
            'The \'' . $name . '\' attribute of ' . $xml->prefix . ':' . $xml->localName . ' must be boolean.',
214
        );
215
216
        return in_array($value, ['1', 'true'], true);
217
    }
218
219
220
    /**
221
     * @param \DOMElement $xml The element where we should search for the attribute.
222
     * @param string      $name The name of the attribute.
223
     * @param bool|null   $default The default to return in case the attribute does not exist and it is optional.
224
     * @return bool|null
225
     *
226
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not a boolean
227
     */
228
    public static function getOptionalBooleanAttribute(DOMElement $xml, string $name, ?bool $default = null): ?bool
229
    {
230
        if (!$xml->hasAttribute($name)) {
231
            return $default;
232
        }
233
234
        return self::getBooleanAttribute($xml, $name);
235
    }
236
237
238
    /**
239
     * Get the integer value of an attribute from a given element.
240
     *
241
     * @param \DOMElement $xml The element where we should search for the attribute.
242
     * @param string      $name The name of the attribute.
243
     * @param int         $default The default to return in case the attribute does not exist and it is optional.
244
     * @return int
245
     *
246
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the attribute is missing from the element
247
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not an integer
248
     */
249
    public static function getIntegerAttribute(DOMElement $xml, string $name): int
250
    {
251
        $value = self::getAttribute($xml, $name);
252
253
        Assert::numeric(
254
            $value,
255
            'The \'' . $name . '\' attribute of ' . $xml->prefix . ':' . $xml->localName . ' must be numerical.',
256
        );
257
258
        return intval($value);
259
    }
260
261
262
    /**
263
     * Get the integer value of an attribute from a given element.
264
     *
265
     * @param \DOMElement $xml The element where we should search for the attribute.
266
     * @param string      $name The name of the attribute.
267
     * @param int|null    $default The default to return in case the attribute does not exist and it is optional.
268
     * @return int|null
269
     *
270
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not an integer
271
     */
272
    public static function getOptionalIntegerAttribute(DOMElement $xml, string $name, ?int $default = null): ?int
273
    {
274
        if (!$xml->hasAttribute($name)) {
275
            return $default;
276
        }
277
278
        return self::getIntegerAttribute($xml, $name);
279
    }
280
281
282
    /**
283
     * Test if an object, at the state it's in, would produce an empty XML-element
284
     *
285
     * @return bool
286
     */
287
    public function isEmptyElement(): bool
288
    {
289
        $xml = $this->getXML();
290
        return ($xml->childNodes->length === 0) && ($xml->attributes->length === 0);
291
    }
292
293
294
    /**
295
     * @param \DOMElement $xml
296
     * @return static
297
     */
298
    public static function fromXML(DOMElement $xml): static
299
    {
300
        return new static($xml);
301
    }
302
303
304
    /**
305
     * Append this XML element to a different XML element.
306
     *
307
     * @param  \DOMElement|null $parent The element we should append this element to.
308
     * @return \DOMElement The new element.
309
     */
310
    public function toXML(DOMElement $parent = null): DOMElement
311
    {
312
        if ($parent === null) {
313
            $doc = new DOMDocument();
314
        } else {
315
            $doc = $parent->ownerDocument;
316
            Assert::notNull($doc);
317
        }
318
319
        if ($parent === null) {
320
            $parent = $doc;
321
        }
322
323
        /**
324
         * @psalm-var \DOMDocument $parent
325
         * @psalm-var \DOMDocument $doc
326
         */
327
        $parent->appendChild($doc->importNode($this->getXML(), true));
0 ignored issues
show
Bug introduced by
The method appendChild() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

327
        $parent->/** @scrutinizer ignore-call */ 
328
                 appendChild($doc->importNode($this->getXML(), true));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
328
329
        return $doc->documentElement;
330
    }
331
}
332