Passed
Push — master ( 66592a...152b2f )
by Tim
02:08
created

processArrayContents()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 56
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

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

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