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