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

LogoutRequest::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 10
dl 0
loc 18
rs 10
c 1
b 1
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 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 int|null $issueInstant
61
     * @param string|null $destination
62
     * @param string|null $consent
63
     * @param \SAML2\XML\samlp\Extensions $extensions
64
     * @throws \Exception
65
     */
66
    public function __construct(
67
        IdentifierInterface $identifier,
68
        ?int $notOnOrAfter = null,
69
        ?string $reason = null,
70
        array $sessionIndexes = [],
71
        ?Issuer $issuer = null,
72
        ?string $id = null,
73
        ?int $issueInstant = null,
74
        ?string $destination = null,
75
        ?string $consent = null,
76
        ?Extensions $extensions = null
77
    ) {
78
        parent::__construct($issuer, $id, $issueInstant, $destination, $consent, $extensions);
79
80
        $this->setIdentifier($identifier);
81
        $this->setNotOnOrAfter($notOnOrAfter);
82
        $this->setReason($reason);
83
        $this->setSessionIndexes($sessionIndexes);
84
    }
85
86
87
    /**
88
     * Retrieve the expiration time of this request.
89
     *
90
     * @return int|null The expiration time of this request.
91
     */
92
    public function getNotOnOrAfter(): ?int
93
    {
94
        return $this->notOnOrAfter;
95
    }
96
97
98
    /**
99
     * Set the expiration time of this request.
100
     *
101
     * @param int|null $notOnOrAfter The expiration time of this request.
102
     * @return void
103
     */
104
    public function setNotOnOrAfter(?int $notOnOrAfter = null): void
105
    {
106
        $this->notOnOrAfter = $notOnOrAfter;
107
    }
108
109
    /**
110
     * Retrieve the reason for this request.
111
     *
112
     * @return string|null The reason for this request.
113
     */
114
    public function getReason(): ?string
115
    {
116
        return $this->reason;
117
    }
118
119
120
    /**
121
     * Set the reason for this request.
122
     *
123
     * @param string|null $reason The optional reason for this request in URN format
124
     * @return void
125
     */
126
    public function setReason(?string $reason = null): void
127
    {
128
        $this->reason = $reason;
129
    }
130
131
132
    /**
133
     * Retrieve the SessionIndexes of the sessions that should be terminated.
134
     *
135
     * @return string[] The SessionIndexes, or an empty array if all sessions should be terminated.
136
     */
137
    public function getSessionIndexes(): array
138
    {
139
        return $this->sessionIndexes;
140
    }
141
142
143
    /**
144
     * Set the SessionIndexes of the sessions that should be terminated.
145
     *
146
     * @param string[] $sessionIndexes The SessionIndexes, or an empty array if all sessions should be terminated.
147
     * @return void
148
     */
149
    public function setSessionIndexes(array $sessionIndexes): void
150
    {
151
        Assert::allStringNotEmpty($sessionIndexes);
152
        $this->sessionIndexes = $sessionIndexes;
153
    }
154
155
156
    /**
157
     * Convert XML into a LogoutRequest
158
     *
159
     * @param \DOMElement $xml The XML element we should load
160
     * @return \SAML2\XML\samlp\LogoutRequest
161
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
162
     * @throws \Exception
163
     */
164
    public static function fromXML(DOMElement $xml): object
165
    {
166
        Assert::same($xml->localName, 'LogoutRequest');
167
        Assert::same($xml->namespaceURI, LogoutRequest::NS);
168
        Assert::same('2.0', self::getAttribute($xml, 'Version'));
169
170
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
171
172
        $notOnOrAfter = self::getAttribute($xml, 'NotOnOrAfter', null);
173
        if ($notOnOrAfter !== null) {
174
            $notOnOrAfter = Utils::xsDateTimeToTimestamp($notOnOrAfter);
175
        }
176
177
        $issuer = Issuer::getChildrenOfClass($xml);
178
        Assert::countBetween($issuer, 0, 1);
179
180
        $extensions = Extensions::getChildrenOfClass($xml);
181
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
182
183
        $identifier = self::getIdentifierFromXML($xml);
184
        Assert::notNull($identifier, 'Missing <saml:NameID>, <saml:BaseID> or <saml:EncryptedID> in <samlp:LogoutRequest>.');
185
        Assert::isInstanceOfAny($identifier, [BaseID::class, NameID::class, EncryptedID::class]);
186
187
        $signature = Signature::getChildrenOfClass($xml);
188
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
189
190
        $request = new self(
191
            $identifier,
192
            $notOnOrAfter,
193
            self::getAttribute($xml, 'Reason', null),
194
            Utils::extractStrings($xml, AbstractSamlpElement::NS, 'SessionIndex'),
195
            array_pop($issuer),
196
            self::getAttribute($xml, 'ID'),
197
            $issueInstant,
198
            self::getAttribute($xml, 'Destination', null),
199
            self::getAttribute($xml, 'Consent', null),
200
            array_pop($extensions)
201
        );
202
203
        if (!empty($signature)) {
204
            $request->setSignature($signature[0]);
205
            $request->messageContainedSignatureUponConstruction = true;
206
        }
207
208
        return $request;
209
    }
210
211
212
    /**
213
     * @inheritDoc
214
     * @throws \Exception
215
     */
216
    public function toXML(?DOMElement $parent = null): DOMElement
217
    {
218
        $e = parent::toXML($parent);
219
220
        if ($this->notOnOrAfter !== null) {
221
            $e->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter));
222
        }
223
224
        if ($this->reason !== null) {
225
            $e->setAttribute('Reason', $this->reason);
226
        }
227
228
        $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

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