Chunk::getQualifiedName()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 8
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML;
6
7
use DOMElement;
8
use SimpleSAML\XML\Assert\Assert;
9
use SimpleSAML\XML\DOMDocumentFactory;
10
use SimpleSAML\XML\SerializableElementTrait;
11
use SimpleSAML\XMLSchema\Exception\MissingAttributeException;
12
use SimpleSAML\XMLSchema\Exception\SchemaViolationException;
13
use SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface;
14
use SimpleSAML\XMLSchema\Type\StringValue;
15
16
/**
17
 * Serializable class used to hold an XML element.
18
 *
19
 * @package simplesamlphp/xml-common
20
 */
21
final class Chunk implements SerializableElementInterface
22
{
23
    use SerializableElementTrait;
24
25
26
    /**
27
     * Whether the element may be normalized
28
     *
29
     * @var bool $normalization
30
     */
31
    protected bool $normalization = true;
32
33
    /**
34
     * The localName of the element.
35
     *
36
     * @var string
37
     */
38
    protected string $localName;
39
40
    /**
41
     * The namespaceURI of this element.
42
     *
43
     * @var string|null
44
     */
45
    protected ?string $namespaceURI;
46
47
    /**
48
     * The prefix of this element.
49
     *
50
     * @var string
51
     */
52
    protected string $prefix;
53
54
55
    /**
56
     * Create an XML Chunk from a copy of the given \DOMElement.
57
     *
58
     * @param \DOMElement $xml The element we should copy.
59
     */
60
    public function __construct(
61
        protected DOMElement $xml,
62
    ) {
63
        $this->setLocalName($xml->localName);
64
        $this->setNamespaceURI($xml->namespaceURI);
65
        $this->setPrefix($xml->prefix);
66
    }
67
68
69
    /**
70
     * Collect the value of the normalization-property
71
     *
72
     * @return bool
73
     */
74
    public function getNormalization(): bool
75
    {
76
        return $this->normalization;
77
    }
78
79
80
    /**
81
     * Set the value of the normalization-property
82
     *
83
     * @param bool $normalization
84
     */
85
    public function setNormalization(bool $normalization): void
86
    {
87
        $this->normalization = $normalization;
88
    }
89
90
91
    /**
92
     * Collect the value of the localName-property
93
     *
94
     * @return string
95
     */
96
    public function getLocalName(): string
97
    {
98
        return $this->localName;
99
    }
100
101
102
    /**
103
     * Set the value of the localName-property
104
     *
105
     * @param string $localName
106
     * @throws \SimpleSAML\Assert\AssertionFailedException if $localName is an empty string
107
     */
108
    public function setLocalName(string $localName): void
109
    {
110
        Assert::validNCName($localName, SchemaViolationException::class); // Covers the empty string
111
        $this->localName = $localName;
112
    }
113
114
115
    /**
116
     * Collect the value of the namespaceURI-property
117
     *
118
     * @return string|null
119
     */
120
    public function getNamespaceURI(): ?string
121
    {
122
        return $this->namespaceURI;
123
    }
124
125
126
    /**
127
     * Set the value of the namespaceURI-property
128
     *
129
     * @param string|null $namespaceURI
130
     */
131
    protected function setNamespaceURI(?string $namespaceURI = null): void
132
    {
133
        Assert::nullOrValidURI($namespaceURI, SchemaViolationException::class);
134
        $this->namespaceURI = $namespaceURI;
135
    }
136
137
138
    /**
139
     * Get this \DOMElement.
140
     *
141
     * @return \DOMElement This element.
142
     */
143
    public function getXML(): DOMElement
144
    {
145
        return $this->xml;
146
    }
147
148
149
    /**
150
     * Collect the value of the prefix-property
151
     *
152
     * @return string
153
     */
154
    public function getPrefix(): string
155
    {
156
        return $this->prefix;
157
    }
158
159
160
    /**
161
     * Set the value of the prefix-property
162
     *
163
     * @param string|null $prefix
164
     */
165
    protected function setPrefix(?string $prefix = null): void
166
    {
167
        $this->prefix = strval($prefix);
168
    }
169
170
171
    /**
172
     * Get the XML qualified name (prefix:name, or just name when not prefixed)
173
     *  of the element represented by this class.
174
     *
175
     * @return string
176
     */
177
    public function getQualifiedName(): string
178
    {
179
        $prefix = $this->getPrefix();
180
181
        if (empty($prefix)) {
182
            return $this->getLocalName();
183
        } else {
184
            return $prefix . ':' . $this->getLocalName();
185
        }
186
    }
187
188
189
    /**
190
     * Get the value of an attribute from a given element.
191
     *
192
     * @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
193
     * @param \DOMElement     $xml The element where we should search for the attribute.
194
     * @param string          $name The name of the attribute.
195
     * @param class-string<T> $type The type of the attribute value.
196
     * @return T
197
     *
198
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException if the attribute is missing from the element
199
     */
200
    public static function getAttribute(
201
        DOMElement $xml,
202
        string $name,
203
        string $type = StringValue::class,
204
    ): ValueTypeInterface {
205
        Assert::isAOf($type, ValueTypeInterface::class);
206
207
        Assert::true(
208
            $xml->hasAttribute($name),
209
            'Missing \'' . $name . '\' attribute on ' . $xml->prefix . ':' . $xml->localName . '.',
210
            MissingAttributeException::class,
211
        );
212
213
        $value = $xml->getAttribute($name);
214
        return $type::fromString($value);
215
    }
216
217
218
    /**
219
     * Get the value of an attribute from a given element.
220
     *
221
     * @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
222
     * @param \DOMElement  $xml The element where we should search for the attribute.
223
     * @param string       $name The name of the attribute.
224
     * @param class-string<T> $type The type of the attribute value.
225
     * @param \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface|null $default
226
     *   The default to return in case the attribute does not exist and it is optional.
227
     * @return ($default is \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface ? T : T|null)
228
     */
229
    public static function getOptionalAttribute(
230
        DOMElement $xml,
231
        string $name,
232
        string $type = StringValue::class,
233
        ?ValueTypeInterface $default = null,
234
    ): ?ValueTypeInterface {
235
        if (!$xml->hasAttribute($name)) {
236
            return $default;
237
        }
238
239
        return self::getAttribute($xml, $name, $type);
240
    }
241
242
243
    /**
244
     * Test if an object, at the state it's in, would produce an empty XML-element
245
     *
246
     * @return bool
247
     */
248
    public function isEmptyElement(): bool
249
    {
250
        /** @var \DOMElement $xml */
251
        $xml = $this->getXML();
252
        return ($xml->childNodes->length === 0) && ($xml->attributes->count() === 0);
0 ignored issues
show
Bug introduced by
The method count() 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

252
        return ($xml->childNodes->length === 0) && ($xml->attributes->/** @scrutinizer ignore-call */ count() === 0);

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...
253
    }
254
255
256
    /**
257
     * @param \DOMElement $xml
258
     * @return static
259
     */
260
    public static function fromXML(DOMElement $xml): static
261
    {
262
        return new static($xml);
263
    }
264
265
266
    /**
267
     * Append this XML element to a different XML element.
268
     *
269
     * @param  \DOMElement|null $parent The element we should append this element to.
270
     * @return \DOMElement The new element.
271
     */
272
    public function toXML(?DOMElement $parent = null): DOMElement
273
    {
274
        if ($parent === null) {
275
            $doc = DOMDocumentFactory::create();
276
        } else {
277
            $doc = $parent->ownerDocument;
278
            Assert::notNull($doc);
279
        }
280
281
        if ($parent === null) {
282
            $parent = $doc;
283
        }
284
285
        $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

285
        $parent->/** @scrutinizer ignore-call */ 
286
                 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...
286
        return $doc->documentElement;
287
    }
288
}
289