Passed
Pull Request — master (#337)
by Tim
02:05
created

AbstractIndexedEndpointType::validateArray()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 52
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 31
nc 16
nop 1
dl 0
loc 52
rs 8.8017
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\ArrayizableElementInterface;
11
use SimpleSAML\XML\Attribute as XMLAttribute;
12
use SimpleSAML\XML\Chunk;
13
use SimpleSAML\XML\Exception\InvalidDOMElementException;
14
use SimpleSAML\XML\SerializableElementInterface;
15
16
use function array_filter;
17
use function array_key_exists;
18
use function array_keys;
19
use function is_bool;
20
use function strval;
21
22
/**
23
 * Class representing a SAML2 IndexedEndpointType.
24
 *
25
 * @package simplesamlphp/saml2
26
 */
27
abstract class AbstractIndexedEndpointType extends AbstractEndpointType implements ArrayizableElementInterface
28
{
29
    use IndexedElementTrait;
30
31
32
    /**
33
     * IndexedEndpointType constructor.
34
     *
35
     * Note: if you extend this class, the constructor must retain its signature. You cannot extend this class and
36
     * modify the signature of the constructor, unless you implement fromXML() yourself. This class provides
37
     * static methods to get its properties from a given \DOMElement for your convenience. Look at the implementation
38
     * of fromXML() to know how to use them.
39
     *
40
     * @param int $index
41
     * @param string $binding
42
     * @param string $location
43
     * @param bool|null $isDefault
44
     * @param string|null $responseLocation
45
     * @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...
46
     * @param array $children
47
     */
48
    public function __construct(
49
        int $index,
50
        string $binding,
51
        string $location,
52
        ?bool $isDefault = null,
53
        ?string $responseLocation = null,
54
        array $attributes = [],
55
        array $children = [],
56
    ) {
57
        parent::__construct($binding, $location, $responseLocation, $attributes, $children);
58
59
        $this->setIndex($index);
60
        $this->setIsDefault($isDefault);
61
    }
62
63
64
    /**
65
     * Initialize an IndexedEndpointType.
66
     *
67
     * @param \DOMElement $xml The XML element we should load.
68
     * @return static
69
     *
70
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
71
     *   if the qualified name of the supplied element is wrong
72
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
73
     *   if the supplied element is missing any of the mandatory attributes
74
     */
75
    public static function fromXML(DOMElement $xml): static
76
    {
77
        $qualifiedName = static::getClassName(static::class);
78
        Assert::eq(
79
            $xml->localName,
80
            $qualifiedName,
81
            'Unexpected name for endpoint: ' . $xml->localName . '. Expected: ' . $qualifiedName . '.',
82
            InvalidDOMElementException::class,
83
        );
84
85
        $index = self::getIntegerAttribute($xml, 'index');
86
        $binding = self::getAttribute($xml, 'Binding');
87
        $location = self::getAttribute($xml, 'Location');
88
89
        $children = [];
90
        foreach ($xml->childNodes as $child) {
91
            if ($child->namespaceURI === C::NS_MD) {
92
                continue;
93
            } elseif (!($child instanceof DOMElement)) {
94
                continue;
95
            }
96
97
            $children[] = new Chunk($child);
98
        }
99
100
        return new static(
101
            $index,
102
            $binding,
103
            $location,
104
            self::getOptionalBooleanAttribute($xml, 'isDefault', null),
105
            self::getOptionalAttribute($xml, 'ResponseLocation', null),
106
            self::getAttributesNSFromXML($xml),
107
            $children,
108
        );
109
    }
110
111
112
    /**
113
     * Add this endpoint to an XML element.
114
     *
115
     * @param \DOMElement $parent The element we should append this endpoint to.
116
     * @return \DOMElement
117
     */
118
    public function toXML(DOMElement $parent = null): DOMElement
119
    {
120
        $e = parent::instantiateParentElement($parent);
121
122
        $e->setAttribute('Binding', $this->getBinding());
123
        $e->setAttribute('Location', $this->getLocation());
124
        if ($this->getResponseLocation() !== null) {
125
            $e->setAttribute('ResponseLocation', $this->getResponseLocation());
126
        }
127
128
        $e->setAttribute('index', strval($this->getIndex()));
129
130
        if (is_bool($this->getIsDefault())) {
131
            $e->setAttribute('isDefault', $this->getIsDefault() ? 'true' : 'false');
132
        }
133
134
        foreach ($this->getAttributesNS() as $attr) {
135
            $attr->toXML($e);
136
        }
137
138
        /** @var \SimpleSAML\XML\SerializableElementInterface $child */
139
        foreach ($this->getElements() as $child) {
140
            if (!$child->isEmptyElement()) {
141
                $child->toXML($e);
142
            }
143
        }
144
145
        return $e;
146
    }
147
148
149
    /**
150
     * Create a class from an array
151
     *
152
     * @param array $data
153
     * @return static
154
     */
155
    public static function fromArray(array $data): static
156
    {
157
        $data = self::validateArray($data);
158
159
        $responseLocation = array_key_exists('ResponseLocation', $data) ? $data['ResponseLocation'] : null;
160
        $Extensions = array_key_exists('Extensions', $data) ? $data['Extensions'] : null;
161
162
        return new static(
163
            $data['index'],
164
            $data['Binding'],
165
            $data['Location'],
166
            array_key_exists('isDefault', $data) ? $data['isDefault'] : null,
167
            $responseLocation,
168
            $data['attributes'],
169
            $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

169
            /** @scrutinizer ignore-type */ $Extensions,
Loading history...
170
        );
171
    }
172
173
174
    /**
175
     * Validates an array representation of this object and returns the same array with
176
     * rationalized keys (casing) and parsed sub-elements.
177
     *
178
     * @param array $data
179
     * @return array $data
180
     */
181
    private static function validateArray(array $data): array
182
    {
183
        $data = array_change_key_case($data, CASE_LOWER);
184
185
        // Make sure the array keys are known for this kind of object
186
        Assert::allOneOf(
187
            array_keys($data),
188
            ['index', 'binding', 'location', 'isdefault', 'responselocation', 'extensions', 'attributes'],
189
        );
190
191
        // Make sure all the mandatory items exist
192
        Assert::keyExists($data, 'binding');
193
        Assert::keyExists($data, 'location');
194
        Assert::keyExists($data, 'index');
195
196
        // Make sure the items have the correct data type
197
        Assert::integer($data['index']);
198
        Assert::range($data['index'], 0, 65535);
199
        Assert::string($data['binding']);
200
        Assert::string($data['location']);
201
202
        $retval = [
203
            'Binding' => $data['binding'],
204
            'Location' => $data['location'],
205
            'index' => $data['index'],
206
        ];
207
208
        if (array_key_exists('isdefault', $data)) {
209
            Assert::boolean($data['isdefault']);
210
            $retval['isDefault'] = $data['isdefault'];
211
        }
212
213
        if (array_key_exists('responselocation', $data)) {
214
            Assert::string($data['responselocation']);
215
            $retval['ResponseLocation'] = $data['responselocation'];
216
        }
217
218
        if (array_key_exists('extensions', $data)) {
219
            Assert::isArray($data['extensions']);
220
            Assert::allIsInstanceOf($data['extensions'], SerializableElementInterface::class);
221
            $retval['Extensions'] = $data['extensions'];
222
        }
223
224
        if (array_key_exists('attributes', $data)) {
225
            Assert::isArray($data['attributes']);
226
            Assert::allIsArray($data['attributes']);
227
            foreach ($data['attributes'] as $i => $attr) {
228
                $retval['attributes'][] = XMLAttribute::fromArray($attr);
229
            }
230
        }
231
232
        return $retval;
233
    }
234
235
236
    /**
237
     * Create an array from this class
238
     *
239
     * @return array
240
     */
241
    public function toArray(): array
242
    {
243
        $data = parent::toArray();
244
        $data['index'] = $this->getIndex();
245
        $data['isDefault'] = $this->getIsDefault();
246
247
        return array_filter($data);
248
    }
249
}
250