Passed
Pull Request — master (#374)
by Tim
02:43
created

SPSSODescriptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 59
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 31
nc 1
nop 17
dl 0
loc 59
rs 9.424
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

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:

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\SAML2\Assert\Assert;
9
use SimpleSAML\SAML2\Type\{SAMLAnyURIValue, SAMLDateTimeValue, SAMLStringValue};
10
use SimpleSAML\XML\Constants as C;
11
use SimpleSAML\XML\Exception\{InvalidDOMElementException, TooManyElementsException};
12
use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait};
13
use SimpleSAML\XML\Type\{BooleanValue, DurationValue, IDValue};
14
use SimpleSAML\XMLSecurity\XML\ds\Signature;
15
16
use function array_filter;
17
use function preg_split;
18
use function var_export;
19
20
/**
21
 * Class representing SAML 2 SPSSODescriptor.
22
 *
23
 * @package simplesamlphp/saml2
24
 */
25
final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValidatableElementInterface
26
{
27
    use SchemaValidatableElementTrait;
28
29
    /**
30
     * SPSSODescriptor constructor.
31
     *
32
     * @param array<\SimpleSAML\SAML2\XML\md\AssertionConsumerService> $assertionConsumerService
33
     * @param string[] $protocolSupportEnumeration
34
     * @param \SimpleSAML\XML\Type\BooleanValue|null $authnRequestsSigned
35
     * @param \SimpleSAML\XML\Type\BooleanValue|null $wantAssertionsSigned
36
     * @param array<\SimpleSAML\SAML2\XML\md\AttributeConsumingService> $attributeConsumingService
37
     * @param \SimpleSAML\XML\Type\IDValue|null $ID
38
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil
39
     * @param \SimpleSAML\XML\Type\DurationValue|null $cacheDuration
40
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
41
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL
42
     * @param array<\SimpleSAML\SAML2\XML\md\KeyDescriptor> $keyDescriptors
43
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
44
     * @param array<\SimpleSAML\SAML2\XML\md\ContactPerson> $contacts
45
     * @param array<\SimpleSAML\SAML2\XML\md\ArtifactResolutionService> $artifactResolutionService
46
     * @param array<\SimpleSAML\SAML2\XML\md\SingleLogoutService> $singleLogoutService
47
     * @param array<\SimpleSAML\SAML2\XML\md\ManageNameIDService> $manageNameIDService
48
     * @param array<\SimpleSAML\SAML2\XML\md\NameIDFormat> $nameIDFormat
49
     */
50
    public function __construct(
51
        protected array $assertionConsumerService,
52
        array $protocolSupportEnumeration,
53
        protected ?BooleanValue $authnRequestsSigned = null,
54
        protected ?BooleanValue $wantAssertionsSigned = null,
55
        protected array $attributeConsumingService = [],
56
        ?IDValue $ID = null,
57
        ?SAMLDateTimeValue $validUntil = null,
58
        ?DurationValue $cacheDuration = null,
59
        ?Extensions $extensions = null,
60
        ?SAMLAnyURIValue $errorURL = null,
61
        array $keyDescriptors = [],
62
        ?Organization $organization = null,
63
        array $contacts = [],
64
        array $artifactResolutionService = [],
65
        array $singleLogoutService = [],
66
        array $manageNameIDService = [],
67
        array $nameIDFormat = [],
68
    ) {
69
        parent::__construct(
70
            $protocolSupportEnumeration,
71
            $ID,
72
            $validUntil,
73
            $cacheDuration,
74
            $extensions,
75
            $errorURL,
76
            $keyDescriptors,
77
            $organization,
78
            $contacts,
79
            $artifactResolutionService,
80
            $singleLogoutService,
81
            $manageNameIDService,
82
            $nameIDFormat,
83
        );
84
85
        Assert::maxCount($assertionConsumerService, C::UNBOUNDED_LIMIT);
86
        Assert::minCount($assertionConsumerService, 1, 'At least one AssertionConsumerService must be specified.');
87
        Assert::allIsInstanceOf(
88
            $assertionConsumerService,
89
            AssertionConsumerService::class,
90
            'All md:AssertionConsumerService endpoints must be an instance of AssertionConsumerService.',
91
        );
92
        Assert::maxCount($attributeConsumingService, C::UNBOUNDED_LIMIT);
93
        Assert::allIsInstanceOf(
94
            $attributeConsumingService,
95
            AttributeConsumingService::class,
96
            'All md:AttributeConsumingService endpoints must be an instance of AttributeConsumingService.',
97
        );
98
99
        // test that only one ACS is marked as default
100
        Assert::maxCount(
101
            array_filter(
102
                $attributeConsumingService,
103
                function (AttributeConsumingService $acs) {
104
                    return $acs->getIsDefault()?->toBoolean() === true;
105
                },
106
            ),
107
            1,
108
            'Only one md:AttributeConsumingService can be set as default.',
109
        );
110
    }
111
112
113
    /**
114
     * Collect the value of the AuthnRequestsSigned-property
115
     *
116
     * @return \SimpleSAML\XML\Type\BooleanValue|null
117
     */
118
    public function getAuthnRequestsSigned(): ?BooleanValue
119
    {
120
        return $this->authnRequestsSigned;
121
    }
122
123
124
    /**
125
     * Collect the value of the WantAssertionsSigned-property
126
     *
127
     * @return \SimpleSAML\XML\Type\BooleanValue|null
128
     */
129
    public function getWantAssertionsSigned(): ?BooleanValue
130
    {
131
        return $this->wantAssertionsSigned;
132
    }
133
134
135
    /**
136
     * Collect the value of the AssertionConsumerService-property
137
     *
138
     * @return \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
139
     */
140
    public function getAssertionConsumerService(): array
141
    {
142
        return $this->assertionConsumerService;
143
    }
144
145
146
    /**
147
     * Collect the value of the AttributeConsumingService-property
148
     *
149
     * @return \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
150
     */
151
    public function getAttributeConsumingService(): array
152
    {
153
        return $this->attributeConsumingService;
154
    }
155
156
157
    /**
158
     * Convert XML into a SPSSODescriptor
159
     *
160
     * @param \DOMElement $xml The XML element we should load
161
     * @return static
162
     *
163
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
164
     *   if the qualified name of the supplied element is wrong
165
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
166
     *   if the supplied element is missing one of the mandatory attributes
167
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
168
     *   if too many child-elements of a type are specified
169
     */
170
    public static function fromXML(DOMElement $xml): static
171
    {
172
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
173
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
174
175
        $protocols = self::getAttribute($xml, 'protocolSupportEnumeration', SAMLStringValue::class);
176
177
        $orgs = Organization::getChildrenOfClass($xml);
178
        Assert::maxCount(
179
            $orgs,
180
            1,
181
            'More than one Organization found in this descriptor',
182
            TooManyElementsException::class,
183
        );
184
185
        $extensions = Extensions::getChildrenOfClass($xml);
186
        Assert::maxCount(
187
            $extensions,
188
            1,
189
            'Only one md:Extensions element is allowed.',
190
            TooManyElementsException::class,
191
        );
192
193
        $signature = Signature::getChildrenOfClass($xml);
194
        Assert::maxCount(
195
            $signature,
196
            1,
197
            'Only one ds:Signature element is allowed.',
198
            TooManyElementsException::class,
199
        );
200
201
        $spssod = new static(
202
            AssertionConsumerService::getChildrenOfClass($xml),
203
            preg_split('/[\s]+/', trim($protocols->getValue())),
204
            self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null),
205
            self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null),
206
            AttributeConsumingService::getChildrenOfClass($xml),
207
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
208
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
209
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),
210
            !empty($extensions) ? $extensions[0] : null,
211
            self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null),
212
            KeyDescriptor::getChildrenOfClass($xml),
213
            !empty($orgs) ? $orgs[0] : null,
214
            ContactPerson::getChildrenOfClass($xml),
215
            ArtifactResolutionService::getChildrenOfClass($xml),
216
            SingleLogoutService::getChildrenOfClass($xml),
217
            ManageNameIDService::getChildrenOfClass($xml),
218
            NameIDFormat::getChildrenOfClass($xml),
219
        );
220
221
        if (!empty($signature)) {
222
            $spssod->setSignature($signature[0]);
223
            $spssod->setXML($xml);
224
        }
225
226
        return $spssod;
227
    }
228
229
230
    /**
231
     * Convert this assertion to an unsigned XML document.
232
     * This method does not sign the resulting XML document.
233
     *
234
     * @return \DOMElement The root element of the DOM tree
235
     */
236
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
237
    {
238
        $e = parent::toUnsignedXML($parent);
239
240
        if ($this->getAuthnRequestsSigned() !== null) {
241
            $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true));
242
        }
243
244
        if ($this->getWantAssertionsSigned() !== null) {
245
            $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true));
246
        }
247
248
        foreach ($this->getAssertionConsumerService() as $ep) {
249
            $ep->toXML($e);
250
        }
251
252
        foreach ($this->getAttributeConsumingService() as $acs) {
253
            $acs->toXML($e);
254
        }
255
256
        return $e;
257
    }
258
}
259