Passed
Pull Request — master (#226)
by Jaime Pérez
02:37
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 = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
172
173
        $notOnOrAfter = self::getAttribute($xml, 'NotOnOrAfter', null);
174
        if ($notOnOrAfter !== null) {
175
            $notOnOrAfter = Utils::xsDateTimeToTimestamp($notOnOrAfter);
176
        }
177
178
        $issuer = Issuer::getChildrenOfClass($xml);
179
        Assert::countBetween($issuer, 0, 1);
180
181
        $extensions = Extensions::getChildrenOfClass($xml);
182
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
183
184
        $identifier = self::getIdentifierFromXML($xml);
185
        Assert::notNull($identifier, 'Missing <saml:NameID>, <saml:BaseID> or <saml:EncryptedID> in <samlp:LogoutRequest>.');
186
        Assert::isInstanceOfAny($identifier, [BaseID::class, NameID::class, EncryptedID::class]);
187
188
        $signature = Signature::getChildrenOfClass($xml);
189
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
190
191
        $request = new self(
192
            $identifier,
193
            $notOnOrAfter,
194
            self::getAttribute($xml, 'Reason', null),
195
            Utils::extractStrings($xml, AbstractSamlpElement::NS, 'SessionIndex'),
196
            array_pop($issuer),
197
            self::getAttribute($xml, 'ID'),
198
            self::getAttribute($xml, 'Version'),
199
            $issueInstant,
200
            self::getAttribute($xml, 'Destination', null),
201
            self::getAttribute($xml, 'Consent', null),
202
            array_pop($extensions)
203
        );
204
205
        if (!empty($signature)) {
206
            $request->setSignature($signature[0]);
207
            $request->messageContainedSignatureUponConstruction = true;
208
        }
209
210
        return $request;
211
    }
212
213
214
    /**
215
     * @inheritDoc
216
     * @throws \Exception
217
     */
218
    public function toXML(?DOMElement $parent = null): DOMElement
219
    {
220
        Assert::null($parent);
221
222
        $e = parent::toXML($parent);
223
224
        if ($this->notOnOrAfter !== null) {
225
            $e->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter));
226
        }
227
228
        if ($this->reason !== null) {
229
            $e->setAttribute('Reason', $this->reason);
230
        }
231
232
        $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

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