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

SPSSODescriptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 61
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 31
nc 1
nop 17
dl 0
loc 61
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\{SchemaValidatableElementInterface, SchemaValidatableElementTrait};
12
use SimpleSAML\XMLSchema\Exception\{InvalidDOMElementException, TooManyElementsException};
13
use SimpleSAML\XMLSchema\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\XMLSchema\Type\BooleanValue|null $authnRequestsSigned
34
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $wantAssertionsSigned
35
     * @param array<\SimpleSAML\SAML2\XML\md\AttributeConsumingService> $attributeConsumingService
36
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID
37
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil
38
     * @param \SimpleSAML\XMLSchema\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
        /**
99
         * E87:  test that only one ACS is marked as default
100
         */
101
        Assert::maxCount(
102
            array_filter(
103
                $attributeConsumingService,
104
                function (AttributeConsumingService $acs) {
105
                    return $acs->getIsDefault()?->toBoolean() === true;
106
                },
107
            ),
108
            1,
109
            'At most one <AttributeConsumingService> element can have the attribute isDefault set to true.',
110
        );
111
    }
112
113
114
    /**
115
     * Collect the value of the AuthnRequestsSigned-property
116
     *
117
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
118
     */
119
    public function getAuthnRequestsSigned(): ?BooleanValue
120
    {
121
        return $this->authnRequestsSigned;
122
    }
123
124
125
    /**
126
     * Collect the value of the WantAssertionsSigned-property
127
     *
128
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
129
     */
130
    public function getWantAssertionsSigned(): ?BooleanValue
131
    {
132
        return $this->wantAssertionsSigned;
133
    }
134
135
136
    /**
137
     * Collect the value of the AssertionConsumerService-property
138
     *
139
     * @return \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
140
     */
141
    public function getAssertionConsumerService(): array
142
    {
143
        return $this->assertionConsumerService;
144
    }
145
146
147
    /**
148
     * Collect the value of the AttributeConsumingService-property
149
     *
150
     * @return \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
151
     */
152
    public function getAttributeConsumingService(): array
153
    {
154
        return $this->attributeConsumingService;
155
    }
156
157
158
    /**
159
     * Convert XML into a SPSSODescriptor
160
     *
161
     * @param \DOMElement $xml The XML element we should load
162
     * @return static
163
     *
164
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
165
     *   if the qualified name of the supplied element is wrong
166
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
167
     *   if the supplied element is missing one of the mandatory attributes
168
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
169
     *   if too many child-elements of a type are specified
170
     */
171
    public static function fromXML(DOMElement $xml): static
172
    {
173
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
174
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
175
176
        $orgs = Organization::getChildrenOfClass($xml);
177
        Assert::maxCount(
178
            $orgs,
179
            1,
180
            'More than one Organization found in this descriptor',
181
            TooManyElementsException::class,
182
        );
183
184
        $extensions = Extensions::getChildrenOfClass($xml);
185
        Assert::maxCount(
186
            $extensions,
187
            1,
188
            'Only one md:Extensions element is allowed.',
189
            TooManyElementsException::class,
190
        );
191
192
        $signature = Signature::getChildrenOfClass($xml);
193
        Assert::maxCount(
194
            $signature,
195
            1,
196
            'Only one ds:Signature element is allowed.',
197
            TooManyElementsException::class,
198
        );
199
200
        $spssod = new static(
201
            AssertionConsumerService::getChildrenOfClass($xml),
202
            self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
203
            self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null),
204
            self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null),
205
            AttributeConsumingService::getChildrenOfClass($xml),
206
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
207
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
208
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),
209
            !empty($extensions) ? $extensions[0] : null,
210
            self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null),
211
            KeyDescriptor::getChildrenOfClass($xml),
212
            !empty($orgs) ? $orgs[0] : null,
213
            ContactPerson::getChildrenOfClass($xml),
214
            ArtifactResolutionService::getChildrenOfClass($xml),
215
            SingleLogoutService::getChildrenOfClass($xml),
216
            ManageNameIDService::getChildrenOfClass($xml),
217
            NameIDFormat::getChildrenOfClass($xml),
218
        );
219
220
        if (!empty($signature)) {
221
            $spssod->setSignature($signature[0]);
222
            $spssod->setXML($xml);
223
        }
224
225
        return $spssod;
226
    }
227
228
229
    /**
230
     * Convert this assertion to an unsigned XML document.
231
     * This method does not sign the resulting XML document.
232
     *
233
     * @return \DOMElement The root element of the DOM tree
234
     */
235
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
236
    {
237
        $e = parent::toUnsignedXML($parent);
238
239
        if ($this->getAuthnRequestsSigned() !== null) {
240
            $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true));
241
        }
242
243
        if ($this->getWantAssertionsSigned() !== null) {
244
            $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true));
245
        }
246
247
        foreach ($this->getAssertionConsumerService() as $ep) {
248
            $ep->toXML($e);
249
        }
250
251
        foreach ($this->getAttributeConsumingService() as $acs) {
252
            $acs->toXML($e);
253
        }
254
255
        return $e;
256
    }
257
}
258