Passed
Push — master ( 714cfc...b39eb7 )
by Tim
01:51
created

AbstractXMLElement::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 2
b 0
f 1
nc 1
nop 0
dl 0
loc 3
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);
1 ignored issue
show
Bug introduced by
The method createElementNS() 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

41
            /** @scrutinizer ignore-call */ 
42
            $e = $doc->createElementNS($namespace, $qualifiedName);

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...
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::getClassName(static::class) . '.',
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::getClassName(static::class) .
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::getClassName(static::class)
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 local name of the element represented by this class.
141
     *
142
     * @return string
143
     */
144
    public function getLocalName(): string
145
    {
146
        return self::getClassName(get_class($this));
147
    }
148
149
150
    /**
151
     * Get the XML qualified name (prefix:name) of the element represented by this class.
152
     *
153
     * @return string
154
     */
155
    public function getQualifiedName(): string
156
    {
157
        return static::getNamespacePrefix() . ':' . $this->getLocalName();
158
    }
159
160
161
    /**
162
     * Extract localized names from the children of a given element.
163
     *
164
     * @param \DOMElement $parent The element we want to search.
165
     * @return static[] An array of objects of this class.
166
     * @psalm-return array
167
     */
168
    public static function getChildrenOfClass(DOMElement $parent): array
169
    {
170
        $ret = [];
171
        foreach ($parent->childNodes as $node) {
172
            if (
173
                $node->namespaceURI === static::getNamespaceURI()
174
                && $node->localName === self::getClassName(static::class)
175
            ) {
176
                /** @psalm-var \DOMElement $node */
177
                $ret[] = static::fromXML($node);
178
            }
179
        }
180
        return $ret;
181
    }
182
183
184
    /**
185
     * Get the namespace for the element.
186
     *
187
     * @return string
188
     */
189
    abstract public static function getNamespaceURI(): string;
190
191
192
    /**
193
     * Get the namespace-prefix for the element.
194
     *
195
     * @return string
196
     */
197
    abstract public static function getNamespacePrefix(): string;
198
199
200
    /**
201
     * Create a class from an array
202
     *
203
     * @param array $data
204
     * @return self
205
     */
206
    public static function fromArray(array $data): object
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

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

206
    public static function fromArray(/** @scrutinizer ignore-unused */ array $data): object

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
207
    {
208
        throw new RuntimeException('Not implemented.');
209
    }
210
211
212
    /**
213
     * Create an array from this class
214
     *
215
     * @return array
216
     */
217
    public function toArray(): array
218
    {
219
        throw new RuntimeException('Not implemented');
220
    }
221
}
222