Completed
Pull Request — master (#226)
by Jaime Pérez
08:39
created

LogoutRequest::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 5
c 1
b 1
f 0
nc 1
nop 11
dl 0
loc 19
rs 10

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

235
        $this->identifier->/** @scrutinizer ignore-call */ 
236
                           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...
236
237
        foreach ($this->sessionIndexes as $sessionIndex) {
238
            $e->appendChild(
239
                $e->ownerDocument->createElementNS(AbstractSamlpElement::NS, 'samlp:SessionIndex', $sessionIndex)
240
            );
241
        }
242
243
        return $this->signElement($e);
244
    }
245
}
246