Passed
Push — master ( 64d78c...9221fc )
by Tim
02:38
created

Response::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 10
dl 0
loc 25
rs 9.8666
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\samlp;
6
7
use DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
11
use SimpleSAML\SAML2\Constants as C;
12
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
13
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
14
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
15
use SimpleSAML\SAML2\XML\saml\Assertion;
16
use SimpleSAML\SAML2\XML\saml\EncryptedAssertion;
17
use SimpleSAML\SAML2\XML\saml\Issuer;
18
use SimpleSAML\XML\Exception\InvalidDOMElementException;
19
use SimpleSAML\XML\Exception\MissingElementException;
20
use SimpleSAML\XML\Exception\TooManyElementsException;
21
use SimpleSAML\XMLSecurity\XML\ds\Signature;
22
23
use function array_merge;
24
use function array_pop;
25
26
/**
27
 * Class for SAML 2 Response messages.
28
 *
29
 * @package simplesamlphp/saml2
30
 */
31
class Response extends AbstractStatusResponse
32
{
33
    /**
34
     * Constructor for SAML 2 response messages.
35
     *
36
     * @param \SimpleSAML\SAML2\XML\samlp\Status $status
37
     * @param \DateTimeImmutable $issueInstant
38
     * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
39
     * @param string|null $id
40
     * @param string $version
41
     * @param string $inResponseTo
42
     * @param string|null $destination
43
     * @param string|null $consent
44
     * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions
45
     * @param (\SimpleSAML\SAML2\XML\saml\Assertion|\SimpleSAML\SAML2\XML\saml\EncryptedAssertion)[] $assertions
46
     */
47
    final public function __construct(
48
        Status $status,
49
        DateTimeImmutable $issueInstant,
50
        ?Issuer $issuer = null,
51
        ?string $id = null,
52
        string $version = '2.0',
53
        ?string $inResponseTo = null,
54
        ?string $destination = null,
55
        ?string $consent = null,
56
        ?Extensions $extensions = null,
57
        protected array $assertions = [],
58
    ) {
59
        Assert::maxCount($assertions, C::UNBOUNDED_LIMIT);
60
        Assert::allIsInstanceOfAny($assertions, [Assertion::class, EncryptedAssertion::class]);
61
62
        parent::__construct(
63
            $status,
64
            $issueInstant,
65
            $issuer,
66
            $id,
67
            $version,
68
            $inResponseTo,
69
            $destination,
70
            $consent,
71
            $extensions,
72
        );
73
    }
74
75
76
    /**
77
     * Retrieve the assertions in this response.
78
     *
79
     * @return \SimpleSAML\SAML2\XML\saml\Assertion[]|\SimpleSAML\SAML2\XML\saml\EncryptedAssertion[]
80
     */
81
    public function getAssertions(): array
82
    {
83
        return $this->assertions;
84
    }
85
86
87
    /**
88
     * Convert XML into a Response element.
89
     *
90
     * @param \DOMElement $xml The input message.
91
     * @return static
92
     *
93
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
94
     *   if the qualified name of the supplied element is wrong
95
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
96
     *   if the supplied element is missing one of the mandatory attributes
97
     * @throws \SimpleSAML\XML\Exception\MissingElementException
98
     *   if one of the mandatory child-elements is missing
99
     */
100
    public static function fromXML(DOMElement $xml): static
101
    {
102
        Assert::same($xml->localName, 'Response', InvalidDOMElementException::class);
103
        Assert::same($xml->namespaceURI, Response::NS, InvalidDOMElementException::class);
104
105
        $version = self::getAttribute($xml, 'Version');
106
        Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class);
107
        Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class);
108
109
        $signature = Signature::getChildrenOfClass($xml);
110
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
111
112
        $id = self::getAttribute($xml, 'ID');
113
        Assert::validNCName($id); // Covers the empty string
114
115
        $inResponseTo = self::getOptionalAttribute($xml, 'InResponseTo', null);
116
        $destination = self::getOptionalAttribute($xml, 'Destination', null);
117
        $consent = self::getOptionalAttribute($xml, 'Consent', null);
118
119
        $issueInstant = self::getAttribute($xml, 'IssueInstant');
120
        // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
121
        $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
122
123
        SAMLAssert::validDateTime($issueInstant, ProtocolViolationException::class);
124
        $issueInstant = new DateTimeImmutable($issueInstant);
125
126
        $issuer = Issuer::getChildrenOfClass($xml);
127
        Assert::countBetween($issuer, 0, 1);
128
129
        $status = Status::getChildrenOfClass($xml);
130
        Assert::minCount($status, 1, MissingElementException::class);
131
        Assert::maxCount($status, 1, TooManyElementsException::class);
132
133
        $extensions = Extensions::getChildrenOfClass($xml);
134
        Assert::maxCount(
135
            $extensions,
136
            1,
137
            'Only one saml:Extensions element is allowed.',
138
            TooManyElementsException::class,
139
        );
140
141
        $response = new static(
142
            array_pop($status),
143
            $issueInstant,
144
            empty($issuer) ? null : array_pop($issuer),
145
            $id,
146
            $version,
147
            $inResponseTo,
148
            $destination,
149
            $consent,
150
            empty($extensions) ? null : array_pop($extensions),
151
            array_merge(Assertion::getChildrenOfClass($xml), EncryptedAssertion::getChildrenOfClass($xml)),
152
        );
153
154
        if (!empty($signature)) {
155
            $response->setSignature($signature[0]);
156
            $response->messageContainedSignatureUponConstruction = true;
157
            $response->setXML($xml);
158
        }
159
160
        return $response;
161
    }
162
163
164
    /**
165
     * Convert the response message to an XML element.
166
     *
167
     * @return \DOMElement This response.
168
     */
169
    protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
170
    {
171
        $e = parent::toUnsignedXML($parent);
172
173
        foreach ($this->getAssertions() as $assertion) {
174
            $assertion->toXML($e);
175
        }
176
177
        return $e;
178
    }
179
}
180