Passed
Push — master ( 045039...d7835c )
by Tim
02:26
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\XML\Exception\InvalidDOMElementException;
10
use SimpleSAML\XML\Exception\TooManyElementsException;
11
use SimpleSAML\XML\Utils as XMLUtils;
12
use SimpleSAML\XMLSecurity\XML\ds\Signature;
13
14
use function array_filter;
15
use function is_bool;
16
use function preg_split;
17
18
/**
19
 * Class representing SAML 2 SPSSODescriptor.
20
 *
21
 * @package simplesamlphp/saml2
22
 */
23
final class SPSSODescriptor extends AbstractSSODescriptor
24
{
25
    /**
26
     * Whether this SP signs authentication requests.
27
     *
28
     * @var bool|null
29
     */
30
    protected ?bool $authnRequestsSigned = null;
31
32
    /**
33
     * Whether this SP wants the Assertion elements to be signed.
34
     *
35
     * @var bool|null
36
     */
37
    protected ?bool $wantAssertionsSigned = null;
38
39
    /**
40
     * List of AssertionConsumerService endpoints for this SP.
41
     *
42
     * Array with IndexedEndpointType objects.
43
     *
44
     * @var \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
45
     */
46
    protected array $assertionConsumerService = [];
47
48
    /**
49
     * List of AttributeConsumingService descriptors for this SP.
50
     *
51
     * Array with \SimpleSAML\SAML2\XML\md\AttributeConsumingService objects.
52
     *
53
     * @var \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
54
     */
55
    protected array $attributeConsumingService = [];
56
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
243
     *   if the qualified name of the supplied element is wrong
244
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
245
     *   if the supplied element is missing one of the mandatory attributes
246
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
247
     *   if too many child-elements of a type are specified
248
     */
249
    public static function fromXML(DOMElement $xml): static
250
    {
251
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
252
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
253
254
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
255
        $validUntil = self::getAttribute($xml, 'validUntil', null);
256
        $orgs = Organization::getChildrenOfClass($xml);
257
        Assert::maxCount(
258
            $orgs,
259
            1,
260
            'More than one Organization found in this descriptor',
261
            TooManyElementsException::class
262
        );
263
264
        $extensions = Extensions::getChildrenOfClass($xml);
265
        Assert::maxCount(
266
            $extensions,
267
            1,
268
            'Only one md:Extensions element is allowed.',
269
            TooManyElementsException::class
270
        );
271
272
        $signature = Signature::getChildrenOfClass($xml);
273
        Assert::maxCount(
274
            $signature,
275
            1,
276
            'Only one ds:Signature element is allowed.',
277
            TooManyElementsException::class
278
        );
279
280
        $spssod = new static(
281
            AssertionConsumerService::getChildrenOfClass($xml),
282
            preg_split('/[\s]+/', trim($protocols)),
283
            self::getBooleanAttribute($xml, 'AuthnRequestsSigned', null),
284
            self::getBooleanAttribute($xml, 'WantAssertionsSigned', null),
285
            AttributeConsumingService::getChildrenOfClass($xml),
286
            self::getAttribute($xml, 'ID', null),
287
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
288
            self::getAttribute($xml, 'cacheDuration', null),
289
            !empty($extensions) ? $extensions[0] : null,
290
            self::getAttribute($xml, 'errorURL', null),
291
            KeyDescriptor::getChildrenOfClass($xml),
292
            !empty($orgs) ? $orgs[0] : null,
293
            ContactPerson::getChildrenOfClass($xml),
294
            ArtifactResolutionService::getChildrenOfClass($xml),
295
            SingleLogoutService::getChildrenOfClass($xml),
296
            ManageNameIDService::getChildrenOfClass($xml),
297
            NameIDFormat::getChildrenOfClass($xml)
298
        );
299
        if (!empty($signature)) {
300
            $spssod->setSignature($signature[0]);
301
            $spssod->setXML($xml);
302
        }
303
        return $spssod;
304
    }
305
306
307
    /**
308
     * Convert this assertion to an unsigned XML document.
309
     * This method does not sign the resulting XML document.
310
     *
311
     * @return \DOMElement The root element of the DOM tree
312
     */
313
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
314
    {
315
        $e = parent::toUnsignedXML($parent);
316
317
        if (is_bool($this->getAuthnRequestsSigned())) {
318
            $e->setAttribute('AuthnRequestsSigned', $this->getAuthnRequestsSigned() ? 'true' : 'false');
319
        }
320
321
        if (is_bool($this->getWantAssertionsSigned())) {
322
            $e->setAttribute('WantAssertionsSigned', $this->getWantAssertionsSigned() ? 'true' : 'false');
323
        }
324
325
        foreach ($this->getAssertionConsumerService() as $ep) {
326
            $ep->toXML($e);
327
        }
328
329
        foreach ($this->getAttributeConsumingService() as $acs) {
330
            $acs->toXML($e);
331
        }
332
333
        return $e;
334
    }
335
}
336