Attribute::toArray()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
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 DOMAttr;
8
use DOMElement;
9
use SimpleSAML\XML\Assert\Assert;
10
use SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface;
11
use SimpleSAML\XMLSchema\Type\StringValue;
12
13
use function array_keys;
14
use function strval;
15
16
/**
17
 * Class to represent an arbitrary namespaced attribute.
18
 *
19
 * @package simplesamlphp/xml-common
20
 */
21
final class Attribute implements ArrayizableElementInterface
22
{
23
    /**
24
     * Create an Attribute class
25
     *
26
     * @param string|null $namespaceURI
27
     * @param string|null $namespacePrefix
28
     * @param string $attrName
29
     * @param \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface $attrValue
30
     */
31
    public function __construct(
32
        protected ?string $namespaceURI,
33
        protected ?string $namespacePrefix,
34
        protected string $attrName,
35
        protected ValueTypeInterface $attrValue,
36
    ) {
37
        Assert::nullOrValidAnyURI($namespaceURI);
38
        if ($namespaceURI !== null) {
39
            Assert::nullOrValidNCName($namespacePrefix);
40
        }
41
        Assert::validNCName($attrName);
42
    }
43
44
45
    /**
46
     * Collect the value of the namespaceURI-property
47
     *
48
     * @return string|null
49
     */
50
    public function getNamespaceURI(): ?string
51
    {
52
        return $this->namespaceURI;
53
    }
54
55
56
    /**
57
     * Collect the value of the namespacePrefix-property
58
     *
59
     * @return string|null
60
     */
61
    public function getNamespacePrefix(): ?string
62
    {
63
        return $this->namespacePrefix;
64
    }
65
66
67
    /**
68
     * Collect the value of the localName-property
69
     *
70
     * @return string
71
     */
72
    public function getAttrName(): string
73
    {
74
        return $this->attrName;
75
    }
76
77
78
    /**
79
     * Collect the value of the value-property
80
     *
81
     * @return \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
82
     */
83
    public function getAttrValue(): ValueTypeInterface
84
    {
85
        return $this->attrValue;
86
    }
87
88
89
    /**
90
     * Create a class from XML
91
     *
92
     * @param \DOMAttr $attr
93
     * @return static
94
     */
95
    public static function fromXML(DOMAttr $attr): static
96
    {
97
        return new static($attr->namespaceURI, $attr->prefix, $attr->localName, StringValue::fromString($attr->value));
98
    }
99
100
101
    /**
102
     * Create XML from this class
103
     *
104
     * @param \DOMElement $parent
105
     * @return \DOMElement
106
     */
107
    public function toXML(DOMElement $parent): DOMElement
108
    {
109
        if ($this->getNamespaceURI() !== null && !$parent->lookupPrefix($this->getNamespacePrefix())) {
110
            $parent->setAttributeNS(
111
                'http://www.w3.org/2000/xmlns/',
112
                'xmlns:' . $this->getNamespacePrefix(),
113
                $this->getNamespaceURI(),
114
            );
115
        }
116
117
        $parent->setAttributeNS(
118
            $this->getNamespaceURI(),
119
            !in_array($this->getNamespacePrefix(), ['', null])
120
                ? ($this->getNamespacePrefix() . ':' . $this->getAttrName())
121
                : $this->getAttrName(),
122
            strval($this->getAttrValue()),
123
        );
124
125
        return $parent;
126
    }
127
128
129
    /**
130
     * Create a class from an array
131
     *
132
     * @param array{
133
     *   namespaceURI: string,
134
     *   namespacePrefix: string|null,
135
     *   attrName: string,
136
     *   attrValue:  \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface,
137
     * } $data
138
     * @return static
139
     */
140
    public static function fromArray(array $data): static
141
    {
142
        $data = self::processArrayContents($data);
143
144
        return new static(
145
            $data['namespaceURI'],
146
            $data['namespacePrefix'],
147
            $data['attrName'],
148
            StringValue::fromString($data['attrValue']),
149
        );
150
    }
151
152
153
    /**
154
     * Validates an array representation of this object and returns the same array with rationalized keys
155
     *
156
     * @param array{namespaceURI: string, namespacePrefix: string|null, attrName: string, attrValue: mixed} $data
157
     * @return array{namespaceURI: string, namespacePrefix: string|null, attrName: string, attrValue: mixed}
158
     */
159
    private static function processArrayContents(array $data): array
160
    {
161
        $data = array_change_key_case($data, CASE_LOWER);
162
163
        /** @var array{namespaceuri: string, namespaceprefix: string|null, attrname: string, attrvalue: mixed} $data */
164
        Assert::allOneOf(
165
            array_keys($data),
166
            ['namespaceuri', 'namespaceprefix', 'attrname', 'attrvalue'],
167
        );
168
169
        Assert::keyExists($data, 'namespaceuri');
170
        Assert::keyExists($data, 'namespaceprefix');
171
        Assert::keyExists($data, 'attrname');
172
        Assert::keyExists($data, 'attrvalue');
173
174
        Assert::nullOrValidAnyURI($data['namespaceuri']);
175
        Assert::nullOrValidNCName($data['namespaceprefix']);
176
        Assert::nullOrValidNCName($data['attrname']);
177
        Assert::string($data['attrvalue']);
178
179
        return [
180
            'namespaceURI' => $data['namespaceuri'],
181
            'namespacePrefix' => $data['namespaceprefix'],
182
            'attrName' => $data['attrname'],
183
            'attrValue' => $data['attrvalue'],
184
        ];
185
    }
186
187
188
    /**
189
     * Create an array from this class
190
     *
191
     * @return array{
0 ignored issues
show
Documentation Bug introduced by
The doc comment array{ at position 2 could not be parsed: the token is null at position 2.
Loading history...
192
     *   attrName: string,
193
     *   attrValue: string,
194
     *   namespacePrefix: string,
195
     *   namespaceURI: null|string,
196
     * }
197
     */
198
    public function toArray(): array
199
    {
200
        return [
201
            'namespaceURI' => $this->getNamespaceURI(),
202
            'namespacePrefix' => $this->getNamespacePrefix(),
203
            'attrName' => $this->getAttrName(),
204
            'attrValue' => $this->getAttrValue()->getValue(),
205
        ];
206
    }
207
}
208