Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / session / SessionInfo.php
blob911b9d0c3c7a8aee20b86d3b2cf08e964c611fe4
1 <?php
2 /**
3 * MediaWiki session info
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
21 * @ingroup Session
24 namespace MediaWiki\Session;
26 use InvalidArgumentException;
27 use Stringable;
29 /**
30 * Value object returned by SessionProvider
32 * This holds the data necessary to construct a Session.
33 * May require services to be injected into the constructor.
35 * @newable
37 * @ingroup Session
38 * @since 1.27
40 class SessionInfo implements Stringable {
41 /** Minimum allowed priority */
42 public const MIN_PRIORITY = 1;
44 /** Maximum allowed priority */
45 public const MAX_PRIORITY = 100;
47 /** @var SessionProvider|null */
48 private $provider;
50 /** @var string */
51 private $id;
53 /** @var int */
54 private $priority;
56 /** @var UserInfo|null */
57 private $userInfo = null;
59 /** @var bool */
60 private $persisted = false;
62 /** @var bool */
63 private $remembered = false;
65 /** @var bool */
66 private $forceHTTPS = false;
68 /** @var bool */
69 private $idIsSafe = false;
71 /** @var bool */
72 private $forceUse = false;
74 /** @var array|null */
75 private $providerMetadata = null;
77 /**
78 * @stable to call
80 * @param int $priority Session priority
81 * @param array $data
82 * - provider: (SessionProvider|null) If not given, the provider will be
83 * determined from the saved session data.
84 * - id: (string|null) Session ID
85 * - userInfo: (UserInfo|null) User known from the request. If
86 * $provider->canChangeUser() is false, a verified user
87 * must be provided.
88 * - persisted: (bool) Whether this session was persisted
89 * - remembered: (bool) Whether the verified user was remembered.
90 * Defaults to true.
91 * - forceHTTPS: (bool) Whether to force HTTPS for this session. This is
92 * ignored if $wgForceHTTPS is true.
93 * - metadata: (array) Provider metadata, to be returned by
94 * Session::getProviderMetadata(). See SessionProvider::mergeMetadata()
95 * and SessionProvider::refreshSessionInfo().
96 * - idIsSafe: (bool) Set true if the 'id' did not come from the user.
97 * Generally you'll use this from SessionProvider::newEmptySession(),
98 * and not from any other method.
99 * - forceUse: (bool) Set true if the 'id' is from
100 * SessionProvider::hashToSessionId() to delete conflicting session
101 * store data instead of discarding this SessionInfo. Ignored unless
102 * both 'provider' and 'id' are given.
103 * - copyFrom: (SessionInfo) SessionInfo to copy other data items from.
105 public function __construct( $priority, array $data ) {
106 if ( $priority < self::MIN_PRIORITY || $priority > self::MAX_PRIORITY ) {
107 throw new InvalidArgumentException( 'Invalid priority' );
110 if ( isset( $data['copyFrom'] ) ) {
111 $from = $data['copyFrom'];
112 if ( !$from instanceof SessionInfo ) {
113 throw new InvalidArgumentException( 'Invalid copyFrom' );
115 $data += [
116 'provider' => $from->provider,
117 'id' => $from->id,
118 'userInfo' => $from->userInfo,
119 'persisted' => $from->persisted,
120 'remembered' => $from->remembered,
121 'forceHTTPS' => $from->forceHTTPS,
122 'metadata' => $from->providerMetadata,
123 'idIsSafe' => $from->idIsSafe,
124 'forceUse' => $from->forceUse,
125 // @codeCoverageIgnoreStart
127 // @codeCoverageIgnoreEnd
128 } else {
129 $data += [
130 'provider' => null,
131 'id' => null,
132 'userInfo' => null,
133 'persisted' => false,
134 'remembered' => true,
135 'forceHTTPS' => false,
136 'metadata' => null,
137 'idIsSafe' => false,
138 'forceUse' => false,
139 // @codeCoverageIgnoreStart
141 // @codeCoverageIgnoreEnd
144 if ( $data['id'] !== null && !SessionManager::validateSessionId( $data['id'] ) ) {
145 throw new InvalidArgumentException( 'Invalid session ID' );
148 if ( $data['userInfo'] !== null && !$data['userInfo'] instanceof UserInfo ) {
149 throw new InvalidArgumentException( 'Invalid userInfo' );
152 if ( !$data['provider'] && $data['id'] === null ) {
153 throw new InvalidArgumentException(
154 'Must supply an ID when no provider is given'
158 if ( $data['metadata'] !== null && !is_array( $data['metadata'] ) ) {
159 throw new InvalidArgumentException( 'Invalid metadata' );
162 $this->provider = $data['provider'];
163 if ( $data['id'] !== null ) {
164 $this->id = $data['id'];
165 $this->idIsSafe = $data['idIsSafe'];
166 $this->forceUse = $data['forceUse'] && $this->provider;
167 } else {
168 $this->id = $this->provider->getManager()->generateSessionId();
169 $this->idIsSafe = true;
170 $this->forceUse = false;
172 $this->priority = (int)$priority;
173 $this->userInfo = $data['userInfo'];
174 $this->persisted = (bool)$data['persisted'];
175 if ( $data['provider'] !== null ) {
176 if ( $this->userInfo !== null && !$this->userInfo->isAnon() && $this->userInfo->isVerified() ) {
177 $this->remembered = (bool)$data['remembered'];
179 $this->providerMetadata = $data['metadata'];
181 $this->forceHTTPS = (bool)$data['forceHTTPS'];
185 * Return the provider
186 * @return SessionProvider|null
188 final public function getProvider() {
189 return $this->provider;
193 * Return the session ID
194 * @return string
196 final public function getId() {
197 return $this->id;
201 * Indicate whether the ID is "safe"
203 * The ID is safe in the following cases:
204 * - The ID was randomly generated by the constructor.
205 * - The ID was found in the backend data store.
206 * - $this->getProvider()->persistsSessionId() is false.
207 * - The constructor was explicitly told it's safe using the 'idIsSafe'
208 * parameter.
210 * @return bool
212 final public function isIdSafe() {
213 return $this->idIsSafe;
217 * Force use of this SessionInfo if validation fails
219 * The normal behavior is to discard the SessionInfo if validation against
220 * the data stored in the session store fails. If this returns true,
221 * SessionManager will instead delete the session store data so this
222 * SessionInfo may still be used. This is important for providers which use
223 * deterministic IDs and so cannot just generate a random new one.
225 * @return bool
227 final public function forceUse() {
228 return $this->forceUse;
232 * Return the priority
233 * @return int
235 final public function getPriority() {
236 return $this->priority;
240 * Return the user
241 * @return UserInfo|null
243 final public function getUserInfo() {
244 return $this->userInfo;
248 * Return whether the session is persisted
249 * @return bool
251 final public function wasPersisted() {
252 return $this->persisted;
256 * Return provider metadata
257 * @return array|null
259 final public function getProviderMetadata() {
260 return $this->providerMetadata;
264 * Return whether the user was remembered
266 * For providers that can persist the user separately from the session,
267 * the human using it may not actually *want* that to be done. For example,
268 * a cookie-based provider can set cookies that are longer-lived than the
269 * backend session data, but on a public terminal the human likely doesn't
270 * want those cookies set.
272 * This is false unless a non-anonymous verified user was passed to
273 * the SessionInfo constructor by the provider, and the provider didn't
274 * pass false for the 'remembered' data item.
276 * @return bool
278 final public function wasRemembered() {
279 return $this->remembered;
283 * Whether this session should only be used over HTTPS. This should be
284 * ignored if $wgForceHTTPS is true.
286 * @return bool
288 final public function forceHTTPS() {
289 return $this->forceHTTPS;
292 public function __toString() {
293 return '[' . $this->getPriority() . ']' .
294 ( $this->getProvider() ?: 'null' ) .
295 ( $this->userInfo ?: '<null>' ) . $this->getId();
299 * Compare two SessionInfo objects by priority
300 * @param SessionInfo $a
301 * @param SessionInfo $b
302 * @return int Negative if $a < $b, positive if $a > $b, zero if equal
304 public static function compare( $a, $b ) {
305 return $a->getPriority() <=> $b->getPriority();