Passed
Pull Request — master (#226)
by Jaime Pérez
02:19
created

LogoutRequest::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 11
dl 0
loc 19
rs 10
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 SAML2\XML\samlp;
6
7
use DOMElement;
8
use Exception;
9
use RobRichards\XMLSecLibs\XMLSecEnc;
10
use RobRichards\XMLSecLibs\XMLSecurityKey;
11
use SAML2\DOMDocumentFactory;
12
use SAML2\Constants;
13
use SAML2\Utils;
14
use SAML2\XML\IdentifierTrait;
15
use SAML2\XML\ds\Signature;
16
use SAML2\XML\saml\IdentifierInterface;
17
use SAML2\XML\saml\BaseID;
18
use SAML2\XML\saml\EncryptedID;
19
use SAML2\XML\saml\NameID;
20
use SAML2\XML\saml\Issuer;
21
use Webmozart\Assert\Assert;
22
23
/**
24
 * Class for SAML 2 logout request messages.
25
 *
26
 * @package SimpleSAMLphp
27
 */
28
class LogoutRequest extends AbstractRequest
29
{
30
    use IdentifierTrait;
31
32
    /**
33
     * The expiration time of this request.
34
     *
35
     * @var int|null
36
     */
37
    private $notOnOrAfter = null;
38
39
    /**
40
     * The SessionIndexes of the sessions that should be terminated.
41
     *
42
     * @var string[]
43
     */
44
    private $sessionIndexes = [];
45
46
    /**
47
     * The optional reason for the logout, typically a URN
48
     * See \SAML2\Constants::LOGOUT_REASON_*
49
     * From the standard section 3.7.3: "other values MAY be agreed on between participants"
50
     *
51
     * @var string|null
52
     */
53
    protected $reason = null;
54
55
56
    /**
57
     * Constructor for SAML 2 AttributeQuery.
58
     *
59
     * @param \SAML2\XML\saml\IdentifierInterface $identifier
60
     * @param int|null $notOnOrAfter
61
     * @param string|null $reason
62
     * @param string[]|null $sessionIndexes
63
     * @param \SAML2\XML\saml\Issuer|null $issuer
64
     * @param string|null $id
65
     * @param string|null $version
66
     * @param int|null $issueInstant
67
     * @param string|null $destination
68
     * @param string|null $consent
69
     * @param \SAML2\XML\samlp\Extensions $extensions
70
     */
71
    public function __construct(
72
        IdentifierInterface $identifier,
73
        int $notOnOrAfter = null,
74
        string $reason = null,
75
        array $sessionIndexes = [],
76
        ?Issuer $issuer = null,
77
        ?string $id = null,
78
        ?string $version = null,
79
        ?int $issueInstant = null,
80
        ?string $destination = null,
81
        ?string $consent = null,
82
        ?Extensions $extensions = null
83
    ) {
84
        parent::__construct($issuer, $id, $version, $issueInstant, $destination, $consent, $extensions);
85
86
        $this->setIdentifier($identifier);
87
        $this->setNotOnOrAfter($notOnOrAfter);
88
        $this->setReason($reason);
89
        $this->setSessionIndexes($sessionIndexes);
90
    }
91
92
93
    /**
94
     * Retrieve the expiration time of this request.
95
     *
96
     * @return int|null The expiration time of this request.
97
     */
98
    public function getNotOnOrAfter(): ?int
99
    {
100
        return $this->notOnOrAfter;
101
    }
102
103
104
    /**
105
     * Set the expiration time of this request.
106
     *
107
     * @param int|null $notOnOrAfter The expiration time of this request.
108
     * @return void
109
     */
110
    public function setNotOnOrAfter(int $notOnOrAfter = null): void
111
    {
112
        $this->notOnOrAfter = $notOnOrAfter;
113
    }
114
115
    /**
116
     * Retrieve the reason for this request.
117
     *
118
     * @return string|null The reason for this request.
119
     */
120
    public function getReason(): ?string
121
    {
122
        return $this->reason;
123
    }
124
125
126
    /**
127
     * Set the reason for this request.
128
     *
129
     * @param string|null $reason The optional reason for this request in URN format
130
     * @return void
131
     */
132
    public function setReason($reason = null): void
133
    {
134
        $this->reason = $reason;
135
    }
136
137
138
    /**
139
     * Retrieve the SessionIndexes of the sessions that should be terminated.
140
     *
141
     * @return string[] The SessionIndexes, or an empty array if all sessions should be terminated.
142
     */
143
    public function getSessionIndexes(): array
144
    {
145
        return $this->sessionIndexes;
146
    }
147
148
149
    /**
150
     * Set the SessionIndexes of the sessions that should be terminated.
151
     *
152
     * @param string[] $sessionIndexes The SessionIndexes, or an empty array if all sessions should be terminated.
153
     * @return void
154
     */
155
    public function setSessionIndexes(array $sessionIndexes): void
156
    {
157
        $this->sessionIndexes = $sessionIndexes;
158
    }
159
160
161
    /**
162
     * Convert XML into a LogoutRequest
163
     *
164
     * @param \DOMElement $xml The XML element we should load
165
     * @return \SAML2\XML\samlp\LogoutRequest
166
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
167
     */
168
    public static function fromXML(DOMElement $xml): object
169
    {
170
        Assert::same($xml->localName, 'LogoutRequest');
171
        Assert::same($xml->namespaceURI, LogoutRequest::NS);
172
173
        $id = self::getAttribute($xml, 'ID');
174
        $version = self::getAttribute($xml, 'Version');
175
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
176
        $inResponseTo = self::getAttribute($xml, 'InResponseTo', null);
0 ignored issues
show
Unused Code introduced by
The assignment to $inResponseTo is dead and can be removed.
Loading history...
177
        $destination = self::getAttribute($xml, 'Destination', null);
178
        $consent = self::getAttribute($xml, 'Consent', null);
179
180
        $notOnOrAfter = self::getAttribute($xml, 'NotOnOrAfter', null);
181
        if ($notOnOrAfter !== null) {
182
            $notOnOrAfter = Utils::xsDateTimeToTimestamp($notOnOrAfter);
183
        }
184
185
        $reason = self::getAttribute($xml, 'Reason', null);
186
        $sessionIndexes = Utils::extractStrings($xml, AbstractSamlpElement::NS, 'SessionIndex');
187
188
        $issuer = Issuer::getChildrenOfClass($xml);
189
        Assert::countBetween($issuer, 0, 1);
190
191
        $extensions = Extensions::getChildrenOfClass($xml);
192
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
193
194
        $identifier = self::getIdentifierFromXML($xml);
195
        Assert::notNull($identifier, 'Missing <saml:NameID>, <saml:BaseID> or <saml:EncryptedID> in <samlp:LogoutRequest>.');
196
        Assert::isInstanceOfAny($identifier, [BaseID::class, NameID::class, EncryptedID::class]);
197
198
        $signature = Signature::getChildrenOfClass($xml);
199
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
200
201
        $request = new self(
202
            $identifier,
203
            $notOnOrAfter,
204
            $reason,
205
            $sessionIndexes,
206
            array_pop($issuer),
207
            $id,
208
            $version,
209
            $issueInstant,
210
            $destination,
211
            $consent,
212
            array_pop($extensions)
213
        );
214
215
        if (!empty($signature)) {
216
            $request->setSignature($signature[0]);
217
            $request->messageContainedSignatureUponConstruction = true;
218
        }
219
220
        return $request;
221
    }
222
223
224
    /**
225
     * Convert this logout request message to an XML element.
226
     *
227
     * @return \DOMElement This logout request.
228
     */
229
    public function toXML(?DOMElement $parent = null): DOMElement
230
    {
231
        Assert::null($parent);
232
233
        $e = parent::toXML($parent);
234
235
        if ($this->notOnOrAfter !== null) {
236
            $e->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter));
237
        }
238
239
        if ($this->reason !== null) {
240
            $e->setAttribute('Reason', $this->reason);
241
        }
242
243
        $this->identifier->toXML($e);
0 ignored issues
show
Bug introduced by
The method toXML() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

243
        $this->identifier->/** @scrutinizer ignore-call */ 
244
                           toXML($e);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
244
245
        foreach ($this->sessionIndexes as $sessionIndex) {
246
            /** @psalm-suppress PossiblyNullReference */
247
            $e->appendChild(
248
                $e->ownerDocument->createElementNS(AbstractSamlpElement::NS, 'saml:SessionIndex', $sessionIndex)
249
            );
250
        }
251
252
        return $this->signElement($e);
253
    }
254
}
255