Passed
Push — master ( 049d3a...532795 )
by Tim
02:10
created

AbstractEndpointType::toArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 0
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\Constants as C;
10
use SimpleSAML\XML\Attribute as XMLAttribute;
11
use SimpleSAML\XML\Chunk;
12
use SimpleSAML\XML\Exception\InvalidDOMElementException;
13
use SimpleSAML\XML\Exception\SchemaViolationException;
14
use SimpleSAML\XML\ArrayizableElementInterface;
15
use SimpleSAML\XML\ExtendableAttributesTrait;
16
use SimpleSAML\XML\ExtendableElementTrait;
17
18
/**
19
 * Class representing SAML 2 EndpointType.
20
 *
21
 * This class can be used in two different ways:
22
 *
23
 *   - You can extend the class without extending the constructor. Then you can use the methods available and the class
24
 *     will generate an element with the same name as the extending class
25
 *     (e.g. \SimpleSAML\SAML2\XML\md\AttributeService).
26
 *
27
 *   - Alternatively, you may want to extend the type to add new attributes (e.g look at IndexedEndpointType). In that
28
 *     case, you cannot use this class normally, as if you change the signature of the constructor, you cannot call
29
 *     fromXML() in this class. In order to process an XML document, you can use the get*Attribute() static methods
30
 *     from AbstractElement, and reimplement the fromXML() method with them to suit your new constructor.
31
 *
32
 * @package simplesamlphp/saml2
33
 */
34
abstract class AbstractEndpointType extends AbstractMdElement implements ArrayizableElementInterface
35
{
36
    use ExtendableAttributesTrait;
1 ignored issue
show
introduced by
The trait SimpleSAML\XML\ExtendableAttributesTrait requires some properties which are not provided by SimpleSAML\SAML2\XML\md\AbstractEndpointType: $localName, $nodeValue, $namespaceURI, $prefix, $attributes
Loading history...
37
    use ExtendableElementTrait;
38
39
    /** The namespace-attribute for the xs:any element */
40
    public const XS_ANY_ELT_NAMESPACE = C::XS_ANY_NS_OTHER;
41
42
    /** The namespace-attribute for the xs:anyAttribute element */
43
    public const XS_ANY_ATTR_NAMESPACE = C::XS_ANY_NS_OTHER;
44
45
46
    /**
47
     * EndpointType constructor.
48
     *
49
     * @param string $binding
50
     * @param string $location
51
     * @param string|null $responseLocation
52
     * @param list<\SimpleSAML\XML\Attribute> $attributes
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
53
     * @param \SimpleSAML\XML\ElementInterface[] $children
54
     *
55
     * @throws \SimpleSAML\Assert\AssertionFailedException
56
     */
57
    public function __construct(
58
        protected string $binding,
59
        protected string $location,
60
        protected ?string $responseLocation = null,
61
        array $attributes = [],
62
        array $children = [],
63
    ) {
64
        Assert::validURI($binding, SchemaViolationException::class); // Covers the empty string
65
        Assert::validURI($location, SchemaViolationException::class); // Covers the empty string
66
        Assert::nullOrValidURI($responseLocation, SchemaViolationException::class); // Covers the empty string
67
68
        $this->setAttributesNS($attributes);
69
        $this->setElements($children);
70
    }
71
72
73
    /**
74
     * Collect the value of the Binding property.
75
     *
76
     * @return string
77
     */
78
    public function getBinding(): string
79
    {
80
        return $this->binding;
81
    }
82
83
84
    /**
85
     * Collect the value of the Location property.
86
     *
87
     * @return string
88
     */
89
    public function getLocation(): string
90
    {
91
        return $this->location;
92
    }
93
94
95
    /**
96
     * Collect the value of the ResponseLocation property.
97
     *
98
     * @return string|null
99
     */
100
    public function getResponseLocation(): ?string
101
    {
102
        return $this->responseLocation;
103
    }
104
105
106
    /**
107
     * Initialize an EndpointType.
108
     *
109
     * Note: this method cannot be used when extending this class, if the constructor has a different signature.
110
     *
111
     * @param \DOMElement $xml The XML element we should load.
112
     * @return static
113
     *
114
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
115
     *   if the qualified name of the supplied element is wrong
116
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
117
     *   if the supplied element is missing any of the mandatory attributes
118
     */
119
    public static function fromXML(DOMElement $xml): static
120
    {
121
        $qualifiedName = static::getClassName(static::class);
122
        Assert::eq(
123
            $xml->localName,
124
            $qualifiedName,
125
            'Unexpected name for endpoint: ' . $xml->localName . '. Expected: ' . $qualifiedName . '.',
126
            InvalidDOMElementException::class,
127
        );
128
129
        $binding = self::getAttribute($xml, 'Binding');
130
        $location = self::getAttribute($xml, 'Location');
131
132
        $children = [];
133
        foreach ($xml->childNodes as $child) {
134
            if ($child->namespaceURI === C::NS_MD) {
135
                continue;
136
            } elseif (!($child instanceof DOMElement)) {
137
                continue;
138
            }
139
140
            $children[] = new Chunk($child);
141
        }
142
143
        return new static(
144
            $binding,
145
            $location,
146
            self::getOptionalAttribute($xml, 'ResponseLocation', null),
147
            self::getAttributesNSFromXML($xml),
148
            $children,
149
        );
150
    }
151
152
153
    /**
154
     * Add this endpoint to an XML element.
155
     *
156
     * @param \DOMElement $parent The element we should append this endpoint to.
157
     * @return \DOMElement
158
     */
159
    public function toXML(DOMElement $parent = null): DOMElement
160
    {
161
        $e = parent::instantiateParentElement($parent);
162
163
        $e->setAttribute('Binding', $this->getBinding());
164
        $e->setAttribute('Location', $this->getLocation());
165
166
        if ($this->getResponseLocation() !== null) {
167
            $e->setAttribute('ResponseLocation', $this->getResponseLocation());
168
        }
169
170
        foreach ($this->getAttributesNS() as $attr) {
171
            $attr->toXML($e);
172
        }
173
174
        /** @var \SimpleSAML\XML\SerializableElementInterface $child */
175
        foreach ($this->getElements() as $child) {
176
            if (!$child->isEmptyElement()) {
177
                $child->toXML($e);
178
            }
179
        }
180
181
        return $e;
182
    }
183
184
185
    /**
186
     * Create a class from an array
187
     *
188
     * @param array $data
189
     * @return static
190
     */
191
    public static function fromArray(array $data): static
192
    {
193
        Assert::keyExists($data, 'Binding');
194
        Assert::keyExists($data, 'Location');
195
196
        $responseLocation = array_key_exists('ResponseLocation', $data) ? $data['ResponseLocation'] : null;
197
198
        $Extensions = array_key_exists('Extensions', $data) ? $data['Extensions'] : null;
199
200
        $attributes = [];
201
        if (array_key_exists('attributes', $data)) {
202
            foreach ($data['attributes'] as $attr) {
203
                Assert::keyExists($attr, 'namespaceURI');
204
                Assert::keyExists($attr, 'namespacePrefix');
205
                Assert::keyExists($attr, 'attrName');
206
                Assert::keyExists($attr, 'attrValue');
207
208
                $attributes[] = new XMLAttribute(
209
                    $attr['namespaceURI'],
210
                    $attr['namespacePrefix'],
211
                    $attr['attrName'],
212
                    $attr['attrValue'],
213
                );
214
            }
215
        }
216
217
        return new static($data['Binding'], $data['Location'], $responseLocation, $attributes, $Extensions);
0 ignored issues
show
Bug introduced by
It seems like $Extensions can also be of type null; however, parameter $children of SimpleSAML\SAML2\XML\md\...ointType::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

217
        return new static($data['Binding'], $data['Location'], $responseLocation, $attributes, /** @scrutinizer ignore-type */ $Extensions);
Loading history...
218
    }
219
220
221
    /**
222
     * Create an array from this class
223
     *
224
     * @return array
225
     */
226
    public function toArray(): array
227
    {
228
        $data = [
229
            'Binding' => $this->getBinding(),
230
            'Location' => $this->getLocation(),
231
            'ResponseLocation' => $this->getResponseLocation(),
232
            'Extensions' => $this->getElements(),
233
        ];
234
235
        foreach ($this->getAttributesNS() as $a) {
236
            $data['attributes'][] = $a->toArray();
237
        }
238
239
        return array_filter($data);
240
    }
241
}
242