Passed
Pull Request — master (#280)
by Tim
02:13
created

SPSSODescriptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 50
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 24
nc 1
nop 17
dl 0
loc 50
rs 9.536
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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;
10
use SimpleSAML\XML\Exception\InvalidDOMElementException;
11
use SimpleSAML\XML\Exception\TooManyElementsException;
12
use SimpleSAML\XML\Utils as XMLUtils;
13
use SimpleSAML\XMLSecurity\XML\ds\Signature;
14
15
use function array_filter;
16
use function is_bool;
17
use function preg_split;
18
19
/**
20
 * Class representing SAML 2 SPSSODescriptor.
21
 *
22
 * @package simplesamlphp/saml2
23
 */
24
final class SPSSODescriptor extends AbstractSSODescriptor
25
{
26
    /**
27
     * Whether this SP signs authentication requests.
28
     *
29
     * @var bool|null
30
     */
31
    protected ?bool $authnRequestsSigned = null;
32
33
    /**
34
     * Whether this SP wants the Assertion elements to be signed.
35
     *
36
     * @var bool|null
37
     */
38
    protected ?bool $wantAssertionsSigned = null;
39
40
    /**
41
     * List of AssertionConsumerService endpoints for this SP.
42
     *
43
     * Array with IndexedEndpointType objects.
44
     *
45
     * @var \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
46
     */
47
    protected array $assertionConsumerService = [];
48
49
    /**
50
     * List of AttributeConsumingService descriptors for this SP.
51
     *
52
     * Array with \SimpleSAML\SAML2\XML\md\AttributeConsumingService objects.
53
     *
54
     * @var \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
55
     */
56
    protected array $attributeConsumingService = [];
57
58
59
    /**
60
     * SPSSODescriptor constructor.
61
     *
62
     * @param \SimpleSAML\SAML2\XML\md\AssertionConsumerService[] $assertionConsumerService
63
     * @param string[] $protocolSupportEnumeration
64
     * @param bool|null $authnRequestsSigned
65
     * @param bool|null $wantAssertionsSigned
66
     * @param \SimpleSAML\SAML2\XML\md\AttributeConsumingService[] $attributeConsumingService
67
     * @param string|null $ID
68
     * @param int|null $validUntil
69
     * @param string|null $cacheDuration
70
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
71
     * @param string|null $errorURL
72
     * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors
73
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
74
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts
75
     * @param \SimpleSAML\SAML2\XML\md\ArtifactResolutionService[] $artifactResolutionService
76
     * @param \SimpleSAML\SAML2\XML\md\SingleLogoutService[] $singleLogoutService
77
     * @param \SimpleSAML\SAML2\XML\md\ManageNameIDService[] $manageNameIDService
78
     * @param \SimpleSAML\SAML2\XML\md\NameIDFormat[] $nameIDFormat
79
     */
80
    public function __construct(
81
        array $assertionConsumerService,
82
        array $protocolSupportEnumeration,
83
        ?bool $authnRequestsSigned = null,
84
        ?bool $wantAssertionsSigned = null,
85
        array $attributeConsumingService = [],
86
        ?string $ID = null,
87
        ?int $validUntil = null,
88
        ?string $cacheDuration = null,
89
        ?Extensions $extensions = null,
90
        ?string $errorURL = null,
91
        array $keyDescriptors = [],
92
        ?Organization $organization = null,
93
        array $contacts = [],
94
        array $artifactResolutionService = [],
95
        array $singleLogoutService = [],
96
        array $manageNameIDService = [],
97
        array $nameIDFormat = []
98
    ) {
99
        parent::__construct(
100
            $protocolSupportEnumeration,
101
            $ID,
102
            $validUntil,
103
            $cacheDuration,
104
            $extensions,
105
            $errorURL,
106
            $keyDescriptors,
107
            $organization,
108
            $contacts,
109
            $artifactResolutionService,
110
            $singleLogoutService,
111
            $manageNameIDService,
112
            $nameIDFormat
113
        );
114
115
        $this->setAssertionConsumerService($assertionConsumerService);
116
        $this->setAuthnRequestsSigned($authnRequestsSigned);
117
        $this->setWantAssertionsSigned($wantAssertionsSigned);
118
        $this->setAttributeConsumingService($attributeConsumingService);
119
120
        // test that only one ACS is marked as default
121
        Assert::maxCount(
122
            array_filter(
123
                $this->getAttributeConsumingService(),
124
                function (AttributeConsumingService $acs) {
125
                    return $acs->getIsDefault() === true;
126
                }
127
            ),
128
            1,
129
            'Only one md:AttributeConsumingService can be set as default.'
130
        );
131
    }
132
133
134
    /**
135
     * Collect the value of the AuthnRequestsSigned-property
136
     *
137
     * @return bool|null
138
     */
139
    public function getAuthnRequestsSigned(): ?bool
140
    {
141
        return $this->authnRequestsSigned;
142
    }
143
144
145
    /**
146
     * Set the value of the AuthnRequestsSigned-property
147
     *
148
     * @param bool|null $flag
149
     */
150
    private function setAuthnRequestsSigned(?bool $flag): void
151
    {
152
        $this->authnRequestsSigned = $flag;
153
    }
154
155
156
    /**
157
     * Collect the value of the WantAssertionsSigned-property
158
     *
159
     * @return bool|null
160
     */
161
    public function getWantAssertionsSigned(): ?bool
162
    {
163
        return $this->wantAssertionsSigned;
164
    }
165
166
167
    /**
168
     * Set the value of the WantAssertionsSigned-property
169
     *
170
     * @param bool|null $flag
171
     */
172
    private function setWantAssertionsSigned(?bool $flag): void
173
    {
174
        $this->wantAssertionsSigned = $flag;
175
    }
176
177
178
    /**
179
     * Collect the value of the AssertionConsumerService-property
180
     *
181
     * @return \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
182
     */
183
    public function getAssertionConsumerService(): array
184
    {
185
        return $this->assertionConsumerService;
186
    }
187
188
189
    /**
190
     * Set the value of the AssertionConsumerService-property
191
     *
192
     * @param \SimpleSAML\SAML2\XML\md\AssertionConsumerService[] $acs
193
     * @throws \SimpleSAML\Assert\AssertionFailedException
194
     */
195
    private function setAssertionConsumerService(array $acs): void
196
    {
197
        Assert::minCount($acs, 1, 'At least one AssertionConsumerService must be specified.');
198
        Assert::allIsInstanceOf(
199
            $acs,
200
            AssertionConsumerService::class,
201
            'All md:AssertionConsumerService endpoints must be an instance of AssertionConsumerService.'
202
        );
203
        $this->assertionConsumerService = $acs;
204
    }
205
206
207
    /**
208
     * Collect the value of the AttributeConsumingService-property
209
     *
210
     * @return \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
211
     */
212
    public function getAttributeConsumingService(): array
213
    {
214
        return $this->attributeConsumingService;
215
    }
216
217
218
    /**
219
     * Set the value of the AttributeConsumingService-property
220
     *
221
     * @param \SimpleSAML\SAML2\XML\md\AttributeConsumingService[] $acs
222
     * @throws \SimpleSAML\Assert\AssertionFailedException
223
     */
224
    private function setAttributeConsumingService(array $acs): void
225
    {
226
        Assert::allIsInstanceOf(
227
            $acs,
228
            AttributeConsumingService::class,
229
            'All md:AttributeConsumingService endpoints must be an instance of AttributeConsumingService.'
230
        );
231
        $this->attributeConsumingService = $acs;
232
    }
233
234
235
    /**
236
     * Convert XML into a SPSSODescriptor
237
     *
238
     * @param \DOMElement $xml The XML element we should load
239
     *
240
     * @return self
241
     *
242
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
243
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
244
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
245
     */
246
    public static function fromXML(DOMElement $xml): object
247
    {
248
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
249
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
250
251
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
252
        $validUntil = self::getAttribute($xml, 'validUntil', null);
253
        $orgs = Organization::getChildrenOfClass($xml);
254
        Assert::maxCount($orgs, 1, 'More than one Organization found in this descriptor', TooManyElementsException::class);
255
256
        $extensions = Extensions::getChildrenOfClass($xml);
257
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
258
259
        $signature = Signature::getChildrenOfClass($xml);
260
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
261
262
        $spssod = new self(
263
            AssertionConsumerService::getChildrenOfClass($xml),
264
            preg_split('/[\s]+/', trim($protocols)),
265
            self::getBooleanAttribute($xml, 'AuthnRequestsSigned', null),
266
            self::getBooleanAttribute($xml, 'WantAssertionsSigned', null),
267
            AttributeConsumingService::getChildrenOfClass($xml),
268
            self::getAttribute($xml, 'ID', null),
269
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
270
            self::getAttribute($xml, 'cacheDuration', null),
271
            !empty($extensions) ? $extensions[0] : null,
272
            self::getAttribute($xml, 'errorURL', null),
273
            KeyDescriptor::getChildrenOfClass($xml),
274
            !empty($orgs) ? $orgs[0] : null,
275
            ContactPerson::getChildrenOfClass($xml),
276
            ArtifactResolutionService::getChildrenOfClass($xml),
277
            SingleLogoutService::getChildrenOfClass($xml),
278
            ManageNameIDService::getChildrenOfClass($xml),
279
            NameIDFormat::getChildrenOfClass($xml)
280
        );
281
282
        if (!empty($signature)) {
283
            $spssod->setSignature($signature[0]);
284
        }
285
286
        $spssod->setXML($xml);
287
288
        return $spssod;
289
    }
290
291
292
    /**
293
     * Convert this descriptor to an unsigned XML document.
294
     * This method does not sign the resulting XML document.
295
     *
296
     * @param \DOMElement|null $parent
297
     * @return \DOMElement The root element of the DOM tree
298
     */
299
    protected function toUnsignedXML(DOMElement $parent = null): DOMElement
300
    {
301
        $e = parent::toUnsignedXML($parent);
302
303
        if (is_bool($this->authnRequestsSigned)) {
304
            $e->setAttribute('AuthnRequestsSigned', $this->authnRequestsSigned ? 'true' : 'false');
305
        }
306
307
        if (is_bool($this->wantAssertionsSigned)) {
308
            $e->setAttribute('WantAssertionsSigned', $this->wantAssertionsSigned ? 'true' : 'false');
309
        }
310
311
        foreach ($this->assertionConsumerService as $ep) {
312
            $ep->toXML($e);
313
        }
314
315
        foreach ($this->attributeConsumingService as $acs) {
316
            $acs->toXML($e);
317
        }
318
319
        return $e;
320
    }
321
}
322