Passed
Pull Request — master (#374)
by Tim
02:41
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 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 \SimpleSAML\SAML2\Type\AnyURIListValue $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
        AnyURIListValue $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
        $orgs = Organization::getChildrenOfClass($xml);
176
        Assert::maxCount(
177
            $orgs,
178
            1,
179
            'More than one Organization found in this descriptor',
180
            TooManyElementsException::class,
181
        );
182
183
        $extensions = Extensions::getChildrenOfClass($xml);
184
        Assert::maxCount(
185
            $extensions,
186
            1,
187
            'Only one md:Extensions element is allowed.',
188
            TooManyElementsException::class,
189
        );
190
191
        $signature = Signature::getChildrenOfClass($xml);
192
        Assert::maxCount(
193
            $signature,
194
            1,
195
            'Only one ds:Signature element is allowed.',
196
            TooManyElementsException::class,
197
        );
198
199
        $spssod = new static(
200
            AssertionConsumerService::getChildrenOfClass($xml),
201
            self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
202
            self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null),
203
            self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null),
204
            AttributeConsumingService::getChildrenOfClass($xml),
205
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
206
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
207
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),
208
            !empty($extensions) ? $extensions[0] : null,
209
            self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null),
210
            KeyDescriptor::getChildrenOfClass($xml),
211
            !empty($orgs) ? $orgs[0] : null,
212
            ContactPerson::getChildrenOfClass($xml),
213
            ArtifactResolutionService::getChildrenOfClass($xml),
214
            SingleLogoutService::getChildrenOfClass($xml),
215
            ManageNameIDService::getChildrenOfClass($xml),
216
            NameIDFormat::getChildrenOfClass($xml),
217
        );
218
219
        if (!empty($signature)) {
220
            $spssod->setSignature($signature[0]);
221
            $spssod->setXML($xml);
222
        }
223
224
        return $spssod;
225
    }
226
227
228
    /**
229
     * Convert this assertion to an unsigned XML document.
230
     * This method does not sign the resulting XML document.
231
     *
232
     * @return \DOMElement The root element of the DOM tree
233
     */
234
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
235
    {
236
        $e = parent::toUnsignedXML($parent);
237
238
        if ($this->getAuthnRequestsSigned() !== null) {
239
            $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true));
240
        }
241
242
        if ($this->getWantAssertionsSigned() !== null) {
243
            $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true));
244
        }
245
246
        foreach ($this->getAssertionConsumerService() as $ep) {
247
            $ep->toXML($e);
248
        }
249
250
        foreach ($this->getAttributeConsumingService() as $acs) {
251
            $acs->toXML($e);
252
        }
253
254
        return $e;
255
    }
256
}
257