Passed
Push — master ( cdd857...612985 )
by Tim
02:06 queued 25s
created

AbstractXMLElement::getNamespaceURI()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 5
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML;
6
7
use DOMElement;
8
use RuntimeException;
9
use SimpleSAML\XML\DOMDocumentFactory;
10
use SimpleSAML\XML\Exception\MissingAttributeException;
11
use Serializable;
12
use SimpleSAML\Assert\Assert;
13
14
/**
15
 * Abstract class to be implemented by all classes
16
 *
17
 * @package simplesamlphp/xml-common
18
 */
19
abstract class AbstractXMLElement extends AbstractSerializableXML
20
{
21
    /**
22
     * Create a document structure for this element
23
     *
24
     * @param \DOMElement|null $parent The element we should append to.
25
     * @return \DOMElement
26
     */
27
    public function instantiateParentElement(DOMElement $parent = null): DOMElement
28
    {
29
        $qualifiedName = $this->getQualifiedName();
30
        $namespace = static::getNamespaceURI();
31
32
        if ($parent === null) {
33
            $doc = DOMDocumentFactory::create();
34
            $e = $doc->createElementNS($namespace, $qualifiedName);
35
            $doc->appendChild($e);
36
        } else {
37
            $doc = $parent->ownerDocument;
38
            Assert::notNull($doc);
39
40
            /** @psalm-var \DOMDocument $doc */
41
            $e = $doc->createElementNS($namespace, $qualifiedName);
42
            $parent->appendChild($e);
43
        }
44
45
        return $e;
46
    }
47
48
49
    /**
50
     * Get the value of an attribute from a given element.
51
     *
52
     * @param \DOMElement $xml The element where we should search for the attribute.
53
     * @param string      $name The name of the attribute.
54
     * @param string|null $default The default to return in case the attribute does not exist and it is optional.
55
     * @return string|null
56
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is missing from the element
57
     */
58
    public static function getAttribute(DOMElement $xml, string $name, ?string $default = ''): ?string
59
    {
60
        if (!$xml->hasAttribute($name)) {
61
            Assert::nullOrStringNotEmpty(
62
                $default,
63
                'Missing \'' . $name . '\' attribute on ' . static::getNamespacePrefix() . ':'
64
                    . self::getLocalName() . '.',
65
                MissingAttributeException::class
66
            );
67
68
            return $default;
69
        }
70
71
        return $xml->getAttribute($name);
72
    }
73
74
75
    /**
76
     * @param \DOMElement $xml The element where we should search for the attribute.
77
     * @param string      $name The name of the attribute.
78
     * @param string|null $default The default to return in case the attribute does not exist and it is optional.
79
     * @return bool|null
80
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not a boolean
81
     */
82
    public static function getBooleanAttribute(DOMElement $xml, string $name, ?string $default = ''): ?bool
83
    {
84
        $value = self::getAttribute($xml, $name, $default);
85
        if ($value === null) {
86
            return null;
87
        }
88
89
        Assert::oneOf(
90
            $value,
91
            ['0', '1', 'false', 'true'],
92
            'The \'' . $name . '\' attribute of ' . static::getNamespacePrefix() . ':' . self::getLocalName() .
93
            ' must be boolean.'
94
        );
95
96
        return in_array($value, ['1', 'true'], true);
97
    }
98
99
100
    /**
101
     * Get the integer value of an attribute from a given element.
102
     *
103
     * @param \DOMElement $xml The element where we should search for the attribute.
104
     * @param string      $name The name of the attribute.
105
     * @param string|null $default The default to return in case the attribute does not exist and it is optional.
106
     *
107
     * @return int|null
108
     * @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not an integer
109
     */
110
    public static function getIntegerAttribute(DOMElement $xml, string $name, ?string $default = ''): ?int
111
    {
112
        $value = self::getAttribute($xml, $name, $default);
113
        if ($value === null) {
114
            return null;
115
        }
116
117
        Assert::numeric(
118
            $value,
119
            'The \'' . $name . '\' attribute of ' . static::getNamespacePrefix() . ':' . self::getLocalName()
120
                . ' must be numerical.'
121
        );
122
123
        return intval($value);
124
    }
125
126
127
    /**
128
     * Static method that processes a fully namespaced class name and returns the name of the class from it.
129
     *
130
     * @param string $class
131
     * @return string
132
     */
133
    public static function getClassName(string $class): string
134
    {
135
        return join('', array_slice(explode('\\', $class), -1));
136
    }
137
138
139
    /**
140
     * Get the XML qualified name (prefix:name) of the element represented by this class.
141
     *
142
     * @return string
143
     */
144
    public function getQualifiedName(): string
145
    {
146
        return static::getNamespacePrefix() . ':' . static::getLocalName();
147
    }
148
149
150
    /**
151
     * Extract localized names from the children of a given element.
152
     *
153
     * @param \DOMElement $parent The element we want to search.
154
     * @return static[] An array of objects of this class.
155
     * @psalm-return array
156
     */
157
    public static function getChildrenOfClass(DOMElement $parent): array
158
    {
159
        $ret = [];
160
        foreach ($parent->childNodes as $node) {
161
            if (
162
                $node->namespaceURI === static::getNamespaceURI()
163
                && $node->localName === static::getLocalName()
164
            ) {
165
                /** @psalm-var \DOMElement $node */
166
                $ret[] = static::fromXML($node);
167
            }
168
        }
169
        return $ret;
170
    }
171
172
173
    /**
174
     * Get the namespace for the element.
175
     *
176
     * @return string
177
     */
178
    public static function getNamespaceURI(): string
179
    {
180
        Assert::true(
181
            defined('static::NS'),
182
            self::getClassName(static::class) . '::NS constant must be defined and set to the namespace for the XML-class it represents.',
183
            RuntimeException::class
184
        );
185
        return static::NS;
0 ignored issues
show
Bug introduced by
The constant SimpleSAML\XML\AbstractXMLElement::NS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
186
    }
187
188
189
    /**
190
     * Get the namespace-prefix for the element.
191
     *
192
     * @return string
193
     */
194
    public static function getNamespacePrefix(): string
195
    {
196
        Assert::true(
197
            defined('static::NS_PREFIX'),
198
            self::getClassName(static::class) . '::NS_PREFIX constant must be defined and set to the namespace prefix for the XML-class it represents.',
199
            RuntimeException::class
200
        );
201
        return static::NS_PREFIX;
0 ignored issues
show
Bug introduced by
The constant SimpleSAML\XML\AbstractXMLElement::NS_PREFIX was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
202
    }
203
204
205
    /**
206
     * Get the local name for the element.
207
     *
208
     * @return string
209
     */
210
    public static function getLocalName(): string
211
    {
212
        if (defined('static::LOCALNAME')) {
213
            return static::LOCALNAME;
0 ignored issues
show
Bug introduced by
The constant SimpleSAML\XML\AbstractXMLElement::LOCALNAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
214
        }
215
216
        return self::getClassName(static::class);
217
    }
218
219
220
    /**
221
     * Create a class from an array
222
     *
223
     * @param array $data
224
     * @return self
225
     */
226
    public static function fromArray(/** @scrutinizer ignore-unused */array $data): object
227
    {
228
        throw new RuntimeException('Not implemented.');
229
    }
230
231
232
    /**
233
     * Create an array from this class
234
     *
235
     * @return array
236
     */
237
    public function toArray(): array
238
    {
239
        throw new RuntimeException('Not implemented');
240
    }
241
}
242