1 | <?php |
||||||
2 | /** |
||||||
3 | * @link https://www.yiiframework.com/ |
||||||
4 | * @copyright Copyright (c) 2008 Yii Software LLC |
||||||
5 | * @license https://www.yiiframework.com/license/ |
||||||
6 | */ |
||||||
7 | |||||||
8 | namespace yii\web; |
||||||
9 | |||||||
10 | use Yii; |
||||||
11 | use yii\base\Component; |
||||||
12 | use yii\base\InvalidArgumentException; |
||||||
13 | use yii\base\InvalidConfigException; |
||||||
14 | |||||||
15 | /** |
||||||
16 | * Session provides session data management and the related configurations. |
||||||
17 | * |
||||||
18 | * Session is a Web application component that can be accessed via `Yii::$app->session`. |
||||||
19 | * |
||||||
20 | * To start the session, call [[open()]]; To complete and send out session data, call [[close()]]; |
||||||
21 | * To destroy the session, call [[destroy()]]. |
||||||
22 | * |
||||||
23 | * Session can be used like an array to set and get session data. For example, |
||||||
24 | * |
||||||
25 | * ```php |
||||||
26 | * $session = new Session; |
||||||
27 | * $session->open(); |
||||||
28 | * $value1 = $session['name1']; // get session variable 'name1' |
||||||
29 | * $value2 = $session['name2']; // get session variable 'name2' |
||||||
30 | * foreach ($session as $name => $value) // traverse all session variables |
||||||
31 | * $session['name3'] = $value3; // set session variable 'name3' |
||||||
32 | * ``` |
||||||
33 | * |
||||||
34 | * Session can be extended to support customized session storage. |
||||||
35 | * To do so, override [[useCustomStorage]] so that it returns true, and |
||||||
36 | * override these methods with the actual logic about using custom storage: |
||||||
37 | * [[openSession()]], [[closeSession()]], [[readSession()]], [[writeSession()]], |
||||||
38 | * [[destroySession()]] and [[gcSession()]]. |
||||||
39 | * |
||||||
40 | * Session also supports a special type of session data, called *flash messages*. |
||||||
41 | * A flash message is available only in the current request and the next request. |
||||||
42 | * After that, it will be deleted automatically. Flash messages are particularly |
||||||
43 | * useful for displaying confirmation messages. To use flash messages, simply |
||||||
44 | * call methods such as [[setFlash()]], [[getFlash()]]. |
||||||
45 | * |
||||||
46 | * For more details and usage information on Session, see the [guide article on sessions](guide:runtime-sessions-cookies). |
||||||
47 | * |
||||||
48 | * @property-read array $allFlashes Flash messages (key => message or key => [message1, message2]). |
||||||
49 | * @property-read string $cacheLimiter Current cache limiter. |
||||||
50 | * @property-read array $cookieParams The session cookie parameters. |
||||||
51 | * @property-read int $count The number of session variables. |
||||||
52 | * @property-write string $flash The key identifying the flash message. Note that flash messages and normal |
||||||
53 | * session variables share the same name space. If you have a normal session variable using the same name, its |
||||||
54 | * value will be overwritten by this method. |
||||||
55 | * @property float $gCProbability The probability (percentage) that the GC (garbage collection) process is |
||||||
56 | * started on every session initialization. |
||||||
57 | * @property bool $hasSessionId Whether the current request has sent the session ID. |
||||||
58 | * @property string $id The current session ID. |
||||||
59 | * @property-read bool $isActive Whether the session has started. |
||||||
60 | * @property-read SessionIterator $iterator An iterator for traversing the session variables. |
||||||
61 | * @property string $name The current session name. |
||||||
62 | * @property string $savePath The current session save path, defaults to '/tmp'. |
||||||
63 | * @property int $timeout The number of seconds after which data will be seen as 'garbage' and cleaned up. The |
||||||
64 | * default value is 1440 seconds (or the value of "session.gc_maxlifetime" set in php.ini). |
||||||
65 | * @property bool|null $useCookies The value indicating whether cookies should be used to store session IDs. |
||||||
66 | * @property-read bool $useCustomStorage Whether to use custom storage. |
||||||
67 | * @property bool $useStrictMode Whether strict mode is enabled or not. |
||||||
68 | * @property bool $useTransparentSessionID Whether transparent sid support is enabled or not, defaults to |
||||||
69 | * false. |
||||||
70 | * |
||||||
71 | * @author Qiang Xue <[email protected]> |
||||||
72 | * @since 2.0 |
||||||
73 | */ |
||||||
74 | class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Countable |
||||||
75 | { |
||||||
76 | /** |
||||||
77 | * @var string|null Holds the original session module (before a custom handler is registered) so that it can be |
||||||
78 | * restored when a Session component without custom handler is used after one that has. |
||||||
79 | */ |
||||||
80 | protected static $_originalSessionModule = null; |
||||||
81 | /** |
||||||
82 | * Polyfill for ini directive session.use-strict-mode for PHP < 5.5.2. |
||||||
83 | */ |
||||||
84 | private static $_useStrictModePolyfill = false; |
||||||
85 | /** |
||||||
86 | * @var string the name of the session variable that stores the flash message data. |
||||||
87 | */ |
||||||
88 | public $flashParam = '__flash'; |
||||||
89 | /** |
||||||
90 | * @var \SessionHandlerInterface|array an object implementing the SessionHandlerInterface or a configuration array. If set, will be used to provide persistency instead of build-in methods. |
||||||
91 | */ |
||||||
92 | public $handler; |
||||||
93 | |||||||
94 | /** |
||||||
95 | * @var string|null Holds the session id in case useStrictMode is enabled and the session id needs to be regenerated |
||||||
96 | */ |
||||||
97 | protected $_forceRegenerateId = null; |
||||||
98 | |||||||
99 | /** |
||||||
100 | * @var array parameter-value pairs to override default session cookie parameters that are used for session_set_cookie_params() function |
||||||
101 | * Array may have the following possible keys: 'lifetime', 'path', 'domain', 'secure', 'httponly' |
||||||
102 | * @see https://www.php.net/manual/en/function.session-set-cookie-params.php |
||||||
103 | */ |
||||||
104 | private $_cookieParams = ['httponly' => true]; |
||||||
105 | /** |
||||||
106 | * @var array|null is used for saving session between recreations due to session parameters update. |
||||||
107 | */ |
||||||
108 | private $_frozenSessionData; |
||||||
109 | |||||||
110 | |||||||
111 | /** |
||||||
112 | * Initializes the application component. |
||||||
113 | * This method is required by IApplicationComponent and is invoked by application. |
||||||
114 | */ |
||||||
115 | 98 | public function init() |
|||||
116 | { |
||||||
117 | 98 | parent::init(); |
|||||
118 | 98 | register_shutdown_function([$this, 'close']); |
|||||
119 | 98 | if ($this->getIsActive()) { |
|||||
120 | 5 | Yii::warning('Session is already started', __METHOD__); |
|||||
121 | 5 | $this->updateFlashCounters(); |
|||||
122 | } |
||||||
123 | } |
||||||
124 | |||||||
125 | /** |
||||||
126 | * Returns a value indicating whether to use custom session storage. |
||||||
127 | * This method should be overridden to return true by child classes that implement custom session storage. |
||||||
128 | * To implement custom session storage, override these methods: [[openSession()]], [[closeSession()]], |
||||||
129 | * [[readSession()]], [[writeSession()]], [[destroySession()]] and [[gcSession()]]. |
||||||
130 | * @return bool whether to use custom storage. |
||||||
131 | */ |
||||||
132 | 69 | public function getUseCustomStorage() |
|||||
133 | { |
||||||
134 | 69 | return false; |
|||||
135 | } |
||||||
136 | |||||||
137 | /** |
||||||
138 | * Starts the session. |
||||||
139 | */ |
||||||
140 | 72 | public function open() |
|||||
141 | { |
||||||
142 | 72 | if ($this->getIsActive()) { |
|||||
143 | 72 | return; |
|||||
144 | } |
||||||
145 | |||||||
146 | 71 | $this->registerSessionHandler(); |
|||||
147 | |||||||
148 | 71 | if ($this->getUseCookies() !== false) { |
|||||
149 | 71 | $this->setCookieParamsInternal(); |
|||||
150 | } |
||||||
151 | |||||||
152 | 71 | YII_DEBUG ? session_start() : @session_start(); |
|||||
153 | |||||||
154 | 71 | if ($this->getUseStrictMode() && $this->_forceRegenerateId) { |
|||||
155 | 1 | $this->regenerateID(); |
|||||
156 | 1 | $this->_forceRegenerateId = null; |
|||||
157 | } |
||||||
158 | |||||||
159 | 71 | if ($this->getIsActive()) { |
|||||
160 | 71 | Yii::info('Session started', __METHOD__); |
|||||
161 | 71 | $this->updateFlashCounters(); |
|||||
162 | } else { |
||||||
163 | $error = error_get_last(); |
||||||
164 | $message = isset($error['message']) ? $error['message'] : 'Failed to start session.'; |
||||||
165 | Yii::error($message, __METHOD__); |
||||||
166 | } |
||||||
167 | } |
||||||
168 | |||||||
169 | /** |
||||||
170 | * Registers session handler. |
||||||
171 | * @throws \yii\base\InvalidConfigException |
||||||
172 | */ |
||||||
173 | 71 | protected function registerSessionHandler() |
|||||
174 | { |
||||||
175 | 71 | $sessionModuleName = session_module_name(); |
|||||
176 | 71 | if (static::$_originalSessionModule === null) { |
|||||
177 | 1 | static::$_originalSessionModule = $sessionModuleName; |
|||||
178 | } |
||||||
179 | |||||||
180 | 71 | if ($this->handler === null && $this->getUseCustomStorage()) { |
|||||
181 | 2 | $this->handler = Yii::createObject( |
|||||
182 | 2 | [ |
|||||
183 | 2 | '__class' => SessionHandler::class, |
|||||
184 | 2 | '__construct()' => [$this], |
|||||
185 | 2 | ] |
|||||
186 | 2 | ); |
|||||
187 | } |
||||||
188 | |||||||
189 | 71 | if ($this->handler !== null) { |
|||||
190 | 2 | if (is_array($this->handler)) { |
|||||
191 | $this->handler = Yii::createObject($this->handler); |
||||||
192 | } |
||||||
193 | 2 | if (!$this->handler instanceof \SessionHandlerInterface) { |
|||||
194 | throw new InvalidConfigException('"' . get_class($this) . '::handler" must implement the SessionHandlerInterface.'); |
||||||
195 | } |
||||||
196 | 2 | YII_DEBUG ? session_set_save_handler($this->handler, false) : @session_set_save_handler($this->handler, false); |
|||||
197 | } elseif ( |
||||||
198 | 69 | $sessionModuleName !== static::$_originalSessionModule |
|||||
199 | 69 | && static::$_originalSessionModule !== null |
|||||
200 | 69 | && static::$_originalSessionModule !== 'user' |
|||||
201 | ) { |
||||||
202 | 1 | session_module_name(static::$_originalSessionModule); |
|||||
203 | } |
||||||
204 | } |
||||||
205 | |||||||
206 | /** |
||||||
207 | * Ends the current session and store session data. |
||||||
208 | */ |
||||||
209 | 94 | public function close() |
|||||
210 | { |
||||||
211 | 94 | if ($this->getIsActive()) { |
|||||
212 | 71 | YII_DEBUG ? session_write_close() : @session_write_close(); |
|||||
213 | } |
||||||
214 | |||||||
215 | 94 | $this->_forceRegenerateId = null; |
|||||
216 | } |
||||||
217 | |||||||
218 | /** |
||||||
219 | * Frees all session variables and destroys all data registered to a session. |
||||||
220 | * |
||||||
221 | * This method has no effect when session is not [[getIsActive()|active]]. |
||||||
222 | * Make sure to call [[open()]] before calling it. |
||||||
223 | * @see open() |
||||||
224 | * @see isActive |
||||||
225 | */ |
||||||
226 | 7 | public function destroy() |
|||||
227 | { |
||||||
228 | 7 | if ($this->getIsActive()) { |
|||||
229 | 7 | $sessionId = session_id(); |
|||||
230 | 7 | $this->close(); |
|||||
231 | 7 | $this->setId($sessionId); |
|||||
232 | 7 | $this->open(); |
|||||
233 | 7 | session_unset(); |
|||||
234 | 7 | session_destroy(); |
|||||
235 | 7 | $this->setId($sessionId); |
|||||
236 | } |
||||||
237 | } |
||||||
238 | |||||||
239 | /** |
||||||
240 | * @return bool whether the session has started |
||||||
241 | */ |
||||||
242 | 98 | public function getIsActive() |
|||||
243 | { |
||||||
244 | 98 | return session_status() === PHP_SESSION_ACTIVE; |
|||||
245 | } |
||||||
246 | |||||||
247 | private $_hasSessionId; |
||||||
248 | |||||||
249 | /** |
||||||
250 | * Returns a value indicating whether the current request has sent the session ID. |
||||||
251 | * The default implementation will check cookie and $_GET using the session name. |
||||||
252 | * If you send session ID via other ways, you may need to override this method |
||||||
253 | * or call [[setHasSessionId()]] to explicitly set whether the session ID is sent. |
||||||
254 | * @return bool whether the current request has sent the session ID. |
||||||
255 | */ |
||||||
256 | 37 | public function getHasSessionId() |
|||||
257 | { |
||||||
258 | 37 | if ($this->_hasSessionId === null) { |
|||||
259 | 37 | $name = $this->getName(); |
|||||
260 | 37 | $request = Yii::$app->getRequest(); |
|||||
261 | 37 | if (!empty($_COOKIE[$name]) && ini_get('session.use_cookies')) { |
|||||
262 | $this->_hasSessionId = true; |
||||||
263 | 37 | } elseif (PHP_VERSION_ID < 80400 && !ini_get('session.use_only_cookies') && ini_get('session.use_trans_sid')) { |
|||||
264 | $this->_hasSessionId = $request->get($name) != ''; |
||||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
265 | } else { |
||||||
266 | 37 | $this->_hasSessionId = false; |
|||||
267 | } |
||||||
268 | } |
||||||
269 | |||||||
270 | 37 | return $this->_hasSessionId; |
|||||
271 | } |
||||||
272 | |||||||
273 | /** |
||||||
274 | * Sets the value indicating whether the current request has sent the session ID. |
||||||
275 | * This method is provided so that you can override the default way of determining |
||||||
276 | * whether the session ID is sent. |
||||||
277 | * @param bool $value whether the current request has sent the session ID. |
||||||
278 | */ |
||||||
279 | public function setHasSessionId($value) |
||||||
280 | { |
||||||
281 | $this->_hasSessionId = $value; |
||||||
282 | } |
||||||
283 | |||||||
284 | /** |
||||||
285 | * Gets the session ID. |
||||||
286 | * This is a wrapper for [PHP session_id()](https://www.php.net/manual/en/function.session-id.php). |
||||||
287 | * @return string the current session ID |
||||||
288 | */ |
||||||
289 | 15 | public function getId() |
|||||
290 | { |
||||||
291 | 15 | return session_id(); |
|||||
292 | } |
||||||
293 | |||||||
294 | /** |
||||||
295 | * Sets the session ID. |
||||||
296 | * This is a wrapper for [PHP session_id()](https://www.php.net/manual/en/function.session-id.php). |
||||||
297 | * @param string $value the session ID for the current session |
||||||
298 | */ |
||||||
299 | 9 | public function setId($value) |
|||||
300 | { |
||||||
301 | 9 | session_id($value); |
|||||
302 | } |
||||||
303 | |||||||
304 | /** |
||||||
305 | * Updates the current session ID with a newly generated one. |
||||||
306 | * |
||||||
307 | * Please refer to <https://www.php.net/session_regenerate_id> for more details. |
||||||
308 | * |
||||||
309 | * This method has no effect when session is not [[getIsActive()|active]]. |
||||||
310 | * Make sure to call [[open()]] before calling it. |
||||||
311 | * |
||||||
312 | * @param bool $deleteOldSession Whether to delete the old associated session file or not. |
||||||
313 | * @see open() |
||||||
314 | * @see isActive |
||||||
315 | */ |
||||||
316 | 46 | public function regenerateID($deleteOldSession = false) |
|||||
317 | { |
||||||
318 | 46 | if ($this->getIsActive()) { |
|||||
319 | // add @ to inhibit possible warning due to race condition |
||||||
320 | // https://github.com/yiisoft/yii2/pull/1812 |
||||||
321 | 33 | if (YII_DEBUG && !headers_sent()) { |
|||||
322 | 33 | session_regenerate_id($deleteOldSession); |
|||||
323 | } else { |
||||||
324 | @session_regenerate_id($deleteOldSession); |
||||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
session_regenerate_id() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||||
325 | } |
||||||
326 | } |
||||||
327 | } |
||||||
328 | |||||||
329 | /** |
||||||
330 | * Gets the name of the current session. |
||||||
331 | * This is a wrapper for [PHP session_name()](https://www.php.net/manual/en/function.session-name.php). |
||||||
332 | * @return string the current session name |
||||||
333 | */ |
||||||
334 | 38 | public function getName() |
|||||
335 | { |
||||||
336 | 38 | return session_name(); |
|||||
337 | } |
||||||
338 | |||||||
339 | /** |
||||||
340 | * Sets the name for the current session. |
||||||
341 | * This is a wrapper for [PHP session_name()](https://www.php.net/manual/en/function.session-name.php). |
||||||
342 | * @param string $value the session name for the current session, must be an alphanumeric string. |
||||||
343 | * It defaults to "PHPSESSID". |
||||||
344 | */ |
||||||
345 | 1 | public function setName($value) |
|||||
346 | { |
||||||
347 | 1 | $this->freeze(); |
|||||
348 | 1 | session_name($value); |
|||||
349 | 1 | $this->unfreeze(); |
|||||
350 | } |
||||||
351 | |||||||
352 | /** |
||||||
353 | * Gets the current session save path. |
||||||
354 | * This is a wrapper for [PHP session_save_path()](https://www.php.net/manual/en/function.session-save-path.php). |
||||||
355 | * @return string the current session save path, defaults to '/tmp'. |
||||||
356 | */ |
||||||
357 | public function getSavePath() |
||||||
358 | { |
||||||
359 | return session_save_path(); |
||||||
360 | } |
||||||
361 | |||||||
362 | /** |
||||||
363 | * Sets the current session save path. |
||||||
364 | * This is a wrapper for [PHP session_save_path()](https://www.php.net/manual/en/function.session-save-path.php). |
||||||
365 | * @param string $value the current session save path. This can be either a directory name or a [path alias](guide:concept-aliases). |
||||||
366 | * @throws InvalidArgumentException if the path is not a valid directory |
||||||
367 | */ |
||||||
368 | public function setSavePath($value) |
||||||
369 | { |
||||||
370 | $path = Yii::getAlias($value); |
||||||
371 | if (is_dir($path)) { |
||||||
0 ignored issues
–
show
It seems like
$path can also be of type false ; however, parameter $filename of is_dir() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
372 | session_save_path($path); |
||||||
0 ignored issues
–
show
It seems like
$path can also be of type false ; however, parameter $path of session_save_path() does only seem to accept null|string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
373 | } else { |
||||||
374 | throw new InvalidArgumentException("Session save path is not a valid directory: $value"); |
||||||
375 | } |
||||||
376 | } |
||||||
377 | |||||||
378 | /** |
||||||
379 | * @return array the session cookie parameters. |
||||||
380 | * @see https://www.php.net/manual/en/function.session-get-cookie-params.php |
||||||
381 | */ |
||||||
382 | 71 | public function getCookieParams() |
|||||
383 | { |
||||||
384 | 71 | return array_merge(session_get_cookie_params(), array_change_key_case($this->_cookieParams)); |
|||||
385 | } |
||||||
386 | |||||||
387 | /** |
||||||
388 | * Sets the session cookie parameters. |
||||||
389 | * The cookie parameters passed to this method will be merged with the result |
||||||
390 | * of `session_get_cookie_params()`. |
||||||
391 | * @param array $value cookie parameters, valid keys include: `lifetime`, `path`, `domain`, `secure` and `httponly`. |
||||||
392 | * Starting with Yii 2.0.21 `sameSite` is also supported. It requires PHP version 7.3.0 or higher. |
||||||
393 | * For security, an exception will be thrown if `sameSite` is set while using an unsupported version of PHP. |
||||||
394 | * To use this feature across different PHP versions check the version first. E.g. |
||||||
395 | * ```php |
||||||
396 | * [ |
||||||
397 | * 'sameSite' => PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX : null, |
||||||
398 | * ] |
||||||
399 | * ``` |
||||||
400 | * See https://owasp.org/www-community/SameSite for more information about `sameSite`. |
||||||
401 | * |
||||||
402 | * @throws InvalidArgumentException if the parameters are incomplete. |
||||||
403 | * @see https://www.php.net/manual/en/function.session-set-cookie-params.php |
||||||
404 | */ |
||||||
405 | public function setCookieParams(array $value) |
||||||
406 | { |
||||||
407 | $this->_cookieParams = $value; |
||||||
408 | } |
||||||
409 | |||||||
410 | /** |
||||||
411 | * Sets the session cookie parameters. |
||||||
412 | * This method is called by [[open()]] when it is about to open the session. |
||||||
413 | * @throws InvalidArgumentException if the parameters are incomplete. |
||||||
414 | * @see https://www.php.net/manual/en/function.session-set-cookie-params.php |
||||||
415 | */ |
||||||
416 | 71 | private function setCookieParamsInternal() |
|||||
417 | { |
||||||
418 | 71 | $data = $this->getCookieParams(); |
|||||
419 | 71 | if (isset($data['lifetime'], $data['path'], $data['domain'], $data['secure'], $data['httponly'])) { |
|||||
420 | 71 | if (PHP_VERSION_ID >= 70300) { |
|||||
421 | 71 | session_set_cookie_params($data); |
|||||
422 | } else { |
||||||
423 | if (!empty($data['samesite'])) { |
||||||
424 | $data['path'] .= '; samesite=' . $data['samesite']; |
||||||
425 | } |
||||||
426 | 71 | session_set_cookie_params($data['lifetime'], $data['path'], $data['domain'], $data['secure'], $data['httponly']); |
|||||
427 | } |
||||||
428 | } else { |
||||||
429 | throw new InvalidArgumentException('Please make sure cookieParams contains these elements: lifetime, path, domain, secure and httponly.'); |
||||||
430 | } |
||||||
431 | } |
||||||
432 | |||||||
433 | /** |
||||||
434 | * Returns the value indicating whether cookies should be used to store session IDs. |
||||||
435 | * @return bool|null the value indicating whether cookies should be used to store session IDs. |
||||||
436 | * @see setUseCookies() |
||||||
437 | */ |
||||||
438 | 71 | public function getUseCookies() |
|||||
439 | { |
||||||
440 | 71 | if (ini_get('session.use_cookies') === '0') { |
|||||
441 | 1 | return false; |
|||||
442 | 71 | } elseif (PHP_VERSION_ID >= 80400 || ini_get('session.use_only_cookies') === '1') { |
|||||
443 | 71 | return true; |
|||||
444 | } |
||||||
445 | |||||||
446 | return null; |
||||||
447 | } |
||||||
448 | |||||||
449 | /** |
||||||
450 | * Sets the value indicating whether cookies should be used to store session IDs. |
||||||
451 | * |
||||||
452 | * Three states are possible: |
||||||
453 | * |
||||||
454 | * - true: cookies and only cookies will be used to store session IDs. |
||||||
455 | * - false: cookies will not be used to store session IDs. |
||||||
456 | * - null: if possible, cookies will be used to store session IDs; if not, other mechanisms will be used (e.g. GET parameter) |
||||||
457 | * |
||||||
458 | * @param bool|null $value the value indicating whether cookies should be used to store session IDs. |
||||||
459 | */ |
||||||
460 | 1 | public function setUseCookies($value) |
|||||
461 | { |
||||||
462 | 1 | $this->freeze(); |
|||||
463 | 1 | if ($value === false) { |
|||||
464 | 1 | ini_set('session.use_cookies', '0'); |
|||||
465 | 1 | if (PHP_VERSION_ID < 80400) { |
|||||
466 | 1 | ini_set('session.use_only_cookies', '0'); |
|||||
467 | } |
||||||
468 | 1 | } elseif ($value === true) { |
|||||
0 ignored issues
–
show
|
|||||||
469 | 1 | ini_set('session.use_cookies', '1'); |
|||||
470 | 1 | if (PHP_VERSION_ID < 80400) { |
|||||
471 | 1 | ini_set('session.use_only_cookies', '1'); |
|||||
472 | } |
||||||
473 | } else { |
||||||
474 | ini_set('session.use_cookies', '1'); |
||||||
475 | if (PHP_VERSION_ID < 80400) { |
||||||
476 | ini_set('session.use_only_cookies', '0'); |
||||||
477 | } |
||||||
478 | } |
||||||
479 | 1 | $this->unfreeze(); |
|||||
480 | } |
||||||
481 | |||||||
482 | /** |
||||||
483 | * @return float the probability (percentage) that the GC (garbage collection) process is started on every session initialization. |
||||||
484 | */ |
||||||
485 | 1 | public function getGCProbability() |
|||||
486 | { |
||||||
487 | 1 | return (float) (ini_get('session.gc_probability') / ini_get('session.gc_divisor') * 100); |
|||||
488 | } |
||||||
489 | |||||||
490 | /** |
||||||
491 | * @param float $value the probability (percentage) that the GC (garbage collection) process is started on every session initialization. |
||||||
492 | * @throws InvalidArgumentException if the value is not between 0 and 100. |
||||||
493 | */ |
||||||
494 | 1 | public function setGCProbability($value) |
|||||
495 | { |
||||||
496 | 1 | $this->freeze(); |
|||||
497 | 1 | if ($value >= 0 && $value <= 100) { |
|||||
498 | // percent * 21474837 / 2147483647 ≈ percent * 0.01 |
||||||
499 | 1 | ini_set('session.gc_probability', floor($value * 21474836.47)); |
|||||
500 | 1 | ini_set('session.gc_divisor', 2147483647); |
|||||
501 | } else { |
||||||
502 | throw new InvalidArgumentException('GCProbability must be a value between 0 and 100.'); |
||||||
503 | } |
||||||
504 | 1 | $this->unfreeze(); |
|||||
505 | } |
||||||
506 | |||||||
507 | /** |
||||||
508 | * @return bool whether transparent sid support is enabled or not, defaults to false. |
||||||
509 | */ |
||||||
510 | 1 | public function getUseTransparentSessionID() |
|||||
511 | { |
||||||
512 | 1 | if (PHP_VERSION_ID < 80400) { |
|||||
513 | 1 | return ini_get('session.use_trans_sid') == 1; |
|||||
514 | } |
||||||
515 | return false; |
||||||
516 | } |
||||||
517 | |||||||
518 | /** |
||||||
519 | * @param bool $value whether transparent sid support is enabled or not. |
||||||
520 | */ |
||||||
521 | 1 | public function setUseTransparentSessionID($value) |
|||||
522 | { |
||||||
523 | 1 | $this->freeze(); |
|||||
524 | 1 | if (PHP_VERSION_ID < 80400) { |
|||||
525 | 1 | ini_set('session.use_trans_sid', $value ? '1' : '0'); |
|||||
526 | } |
||||||
527 | 1 | $this->unfreeze(); |
|||||
528 | } |
||||||
529 | |||||||
530 | /** |
||||||
531 | * @return int the number of seconds after which data will be seen as 'garbage' and cleaned up. |
||||||
532 | * The default value is 1440 seconds (or the value of "session.gc_maxlifetime" set in php.ini). |
||||||
533 | */ |
||||||
534 | 4 | public function getTimeout() |
|||||
535 | { |
||||||
536 | 4 | return (int) ini_get('session.gc_maxlifetime'); |
|||||
537 | } |
||||||
538 | |||||||
539 | /** |
||||||
540 | * @param int $value the number of seconds after which data will be seen as 'garbage' and cleaned up |
||||||
541 | */ |
||||||
542 | 1 | public function setTimeout($value) |
|||||
543 | { |
||||||
544 | 1 | $this->freeze(); |
|||||
545 | 1 | ini_set('session.gc_maxlifetime', $value); |
|||||
546 | 1 | $this->unfreeze(); |
|||||
547 | } |
||||||
548 | |||||||
549 | /** |
||||||
550 | * @param bool $value Whether strict mode is enabled or not. |
||||||
551 | * When `true` this setting prevents the session component to use an uninitialized session ID. |
||||||
552 | * Note: Enabling `useStrictMode` on PHP < 5.5.2 is only supported with custom storage classes. |
||||||
553 | * Warning! Although enabling strict mode is mandatory for secure sessions, the default value of 'session.use-strict-mode' is `0`. |
||||||
554 | * @see https://www.php.net/manual/en/session.configuration.php#ini.session.use-strict-mode |
||||||
555 | * @since 2.0.38 |
||||||
556 | */ |
||||||
557 | 4 | public function setUseStrictMode($value) |
|||||
558 | { |
||||||
559 | 4 | if (PHP_VERSION_ID < 50502) { |
|||||
560 | if ($this->getUseCustomStorage() || !$value) { |
||||||
561 | self::$_useStrictModePolyfill = $value; |
||||||
562 | } else { |
||||||
563 | throw new InvalidConfigException('Enabling `useStrictMode` on PHP < 5.5.2 is only supported with custom storage classes.'); |
||||||
564 | } |
||||||
565 | } else { |
||||||
566 | 4 | $this->freeze(); |
|||||
567 | 4 | ini_set('session.use_strict_mode', $value ? '1' : '0'); |
|||||
568 | 4 | $this->unfreeze(); |
|||||
569 | } |
||||||
570 | } |
||||||
571 | |||||||
572 | /** |
||||||
573 | * @return bool Whether strict mode is enabled or not. |
||||||
574 | * @see setUseStrictMode() |
||||||
575 | * @since 2.0.38 |
||||||
576 | */ |
||||||
577 | 74 | public function getUseStrictMode() |
|||||
578 | { |
||||||
579 | 74 | if (PHP_VERSION_ID < 50502) { |
|||||
580 | return self::$_useStrictModePolyfill; |
||||||
581 | } |
||||||
582 | |||||||
583 | 74 | return (bool)ini_get('session.use_strict_mode'); |
|||||
584 | } |
||||||
585 | |||||||
586 | /** |
||||||
587 | * Session open handler. |
||||||
588 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
589 | * @internal Do not call this method directly. |
||||||
590 | * @param string $savePath session save path |
||||||
591 | * @param string $sessionName session name |
||||||
592 | * @return bool whether session is opened successfully |
||||||
593 | */ |
||||||
594 | 3 | public function openSession($savePath, $sessionName) |
|||||
0 ignored issues
–
show
The parameter
$savePath is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$sessionName is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
595 | { |
||||||
596 | 3 | return true; |
|||||
597 | } |
||||||
598 | |||||||
599 | /** |
||||||
600 | * Session close handler. |
||||||
601 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
602 | * @internal Do not call this method directly. |
||||||
603 | * @return bool whether session is closed successfully |
||||||
604 | */ |
||||||
605 | 2 | public function closeSession() |
|||||
606 | { |
||||||
607 | 2 | return true; |
|||||
608 | } |
||||||
609 | |||||||
610 | /** |
||||||
611 | * Session read handler. |
||||||
612 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
613 | * @internal Do not call this method directly. |
||||||
614 | * @param string $id session ID |
||||||
615 | * @return string|false the session data, or false on failure |
||||||
616 | */ |
||||||
617 | public function readSession($id) |
||||||
0 ignored issues
–
show
The parameter
$id is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
618 | { |
||||||
619 | return ''; |
||||||
620 | } |
||||||
621 | |||||||
622 | /** |
||||||
623 | * Session write handler. |
||||||
624 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
625 | * @internal Do not call this method directly. |
||||||
626 | * @param string $id session ID |
||||||
627 | * @param string $data session data |
||||||
628 | * @return bool whether session write is successful |
||||||
629 | */ |
||||||
630 | public function writeSession($id, $data) |
||||||
0 ignored issues
–
show
The parameter
$id is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$data is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
631 | { |
||||||
632 | return true; |
||||||
633 | } |
||||||
634 | |||||||
635 | /** |
||||||
636 | * Session destroy handler. |
||||||
637 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
638 | * @internal Do not call this method directly. |
||||||
639 | * @param string $id session ID |
||||||
640 | * @return bool whether session is destroyed successfully |
||||||
641 | */ |
||||||
642 | 1 | public function destroySession($id) |
|||||
0 ignored issues
–
show
The parameter
$id is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
643 | { |
||||||
644 | 1 | return true; |
|||||
645 | } |
||||||
646 | |||||||
647 | /** |
||||||
648 | * Session GC (garbage collection) handler. |
||||||
649 | * This method should be overridden if [[useCustomStorage]] returns true. |
||||||
650 | * @internal Do not call this method directly. |
||||||
651 | * @param int $maxLifetime the number of seconds after which data will be seen as 'garbage' and cleaned up. |
||||||
652 | * @return int|false the number of deleted sessions on success, or false on failure |
||||||
653 | */ |
||||||
654 | public function gcSession($maxLifetime) |
||||||
0 ignored issues
–
show
The parameter
$maxLifetime is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
655 | { |
||||||
656 | return 0; |
||||||
657 | } |
||||||
658 | |||||||
659 | /** |
||||||
660 | * Returns an iterator for traversing the session variables. |
||||||
661 | * This method is required by the interface [[\IteratorAggregate]]. |
||||||
662 | * @return SessionIterator an iterator for traversing the session variables. |
||||||
663 | */ |
||||||
664 | #[\ReturnTypeWillChange] |
||||||
665 | public function getIterator() |
||||||
666 | { |
||||||
667 | $this->open(); |
||||||
668 | return new SessionIterator(); |
||||||
669 | } |
||||||
670 | |||||||
671 | /** |
||||||
672 | * Returns the number of items in the session. |
||||||
673 | * @return int the number of session variables |
||||||
674 | */ |
||||||
675 | public function getCount() |
||||||
676 | { |
||||||
677 | $this->open(); |
||||||
678 | return count($_SESSION); |
||||||
679 | } |
||||||
680 | |||||||
681 | /** |
||||||
682 | * Returns the number of items in the session. |
||||||
683 | * This method is required by [[\Countable]] interface. |
||||||
684 | * @return int number of items in the session. |
||||||
685 | */ |
||||||
686 | #[\ReturnTypeWillChange] |
||||||
687 | public function count() |
||||||
688 | { |
||||||
689 | return $this->getCount(); |
||||||
690 | } |
||||||
691 | |||||||
692 | /** |
||||||
693 | * Returns the session variable value with the session variable name. |
||||||
694 | * If the session variable does not exist, the `$defaultValue` will be returned. |
||||||
695 | * @param string $key the session variable name |
||||||
696 | * @param mixed $defaultValue the default value to be returned when the session variable does not exist. |
||||||
697 | * @return mixed the session variable value, or $defaultValue if the session variable does not exist. |
||||||
698 | */ |
||||||
699 | 72 | public function get($key, $defaultValue = null) |
|||||
700 | { |
||||||
701 | 72 | $this->open(); |
|||||
702 | 72 | return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue; |
|||||
703 | } |
||||||
704 | |||||||
705 | /** |
||||||
706 | * Adds a session variable. |
||||||
707 | * If the specified name already exists, the old value will be overwritten. |
||||||
708 | * @param string $key session variable name |
||||||
709 | * @param mixed $value session variable value |
||||||
710 | */ |
||||||
711 | 54 | public function set($key, $value) |
|||||
712 | { |
||||||
713 | 54 | $this->open(); |
|||||
714 | 54 | $_SESSION[$key] = $value; |
|||||
715 | } |
||||||
716 | |||||||
717 | /** |
||||||
718 | * Removes a session variable. |
||||||
719 | * @param string $key the name of the session variable to be removed |
||||||
720 | * @return mixed the removed value, null if no such session variable. |
||||||
721 | */ |
||||||
722 | 45 | public function remove($key) |
|||||
723 | { |
||||||
724 | 45 | $this->open(); |
|||||
725 | 45 | if (isset($_SESSION[$key])) { |
|||||
726 | 37 | $value = $_SESSION[$key]; |
|||||
727 | 37 | unset($_SESSION[$key]); |
|||||
728 | |||||||
729 | 37 | return $value; |
|||||
730 | } |
||||||
731 | |||||||
732 | 45 | return null; |
|||||
733 | } |
||||||
734 | |||||||
735 | /** |
||||||
736 | * Removes all session variables. |
||||||
737 | */ |
||||||
738 | 22 | public function removeAll() |
|||||
739 | { |
||||||
740 | 22 | $this->open(); |
|||||
741 | 22 | foreach (array_keys($_SESSION) as $key) { |
|||||
742 | 22 | unset($_SESSION[$key]); |
|||||
743 | } |
||||||
744 | } |
||||||
745 | |||||||
746 | /** |
||||||
747 | * @param mixed $key session variable name |
||||||
748 | * @return bool whether there is the named session variable |
||||||
749 | */ |
||||||
750 | public function has($key) |
||||||
751 | { |
||||||
752 | $this->open(); |
||||||
753 | return isset($_SESSION[$key]); |
||||||
754 | } |
||||||
755 | |||||||
756 | /** |
||||||
757 | * Updates the counters for flash messages and removes outdated flash messages. |
||||||
758 | * This method should only be called once in [[init()]]. |
||||||
759 | */ |
||||||
760 | 72 | protected function updateFlashCounters() |
|||||
761 | { |
||||||
762 | 72 | $counters = $this->get($this->flashParam, []); |
|||||
763 | 72 | if (is_array($counters)) { |
|||||
764 | 72 | foreach ($counters as $key => $count) { |
|||||
765 | if ($count > 0) { |
||||||
766 | unset($counters[$key], $_SESSION[$key]); |
||||||
767 | } elseif ($count == 0) { |
||||||
768 | $counters[$key]++; |
||||||
769 | } |
||||||
770 | } |
||||||
771 | 72 | $_SESSION[$this->flashParam] = $counters; |
|||||
772 | } else { |
||||||
773 | // fix the unexpected problem that flashParam doesn't return an array |
||||||
774 | unset($_SESSION[$this->flashParam]); |
||||||
775 | } |
||||||
776 | } |
||||||
777 | |||||||
778 | /** |
||||||
779 | * Returns a flash message. |
||||||
780 | * @param string $key the key identifying the flash message |
||||||
781 | * @param mixed $defaultValue value to be returned if the flash message does not exist. |
||||||
782 | * @param bool $delete whether to delete this flash message right after this method is called. |
||||||
783 | * If false, the flash message will be automatically deleted in the next request. |
||||||
784 | * @return mixed the flash message or an array of messages if addFlash was used |
||||||
785 | * @see setFlash() |
||||||
786 | * @see addFlash() |
||||||
787 | * @see hasFlash() |
||||||
788 | * @see getAllFlashes() |
||||||
789 | * @see removeFlash() |
||||||
790 | */ |
||||||
791 | public function getFlash($key, $defaultValue = null, $delete = false) |
||||||
792 | { |
||||||
793 | $counters = $this->get($this->flashParam, []); |
||||||
794 | if (isset($counters[$key])) { |
||||||
795 | $value = $this->get($key, $defaultValue); |
||||||
796 | if ($delete) { |
||||||
797 | $this->removeFlash($key); |
||||||
798 | } elseif ($counters[$key] < 0) { |
||||||
799 | // mark for deletion in the next request |
||||||
800 | $counters[$key] = 1; |
||||||
801 | $_SESSION[$this->flashParam] = $counters; |
||||||
802 | } |
||||||
803 | |||||||
804 | return $value; |
||||||
805 | } |
||||||
806 | |||||||
807 | return $defaultValue; |
||||||
808 | } |
||||||
809 | |||||||
810 | /** |
||||||
811 | * Returns all flash messages. |
||||||
812 | * |
||||||
813 | * You may use this method to display all the flash messages in a view file: |
||||||
814 | * |
||||||
815 | * ```php |
||||||
816 | * <?php |
||||||
817 | * foreach (Yii::$app->session->getAllFlashes() as $key => $message) { |
||||||
818 | * echo '<div class="alert alert-' . $key . '">' . $message . '</div>'; |
||||||
819 | * } ?> |
||||||
820 | * ``` |
||||||
821 | * |
||||||
822 | * With the above code you can use the [bootstrap alert][] classes such as `success`, `info`, `danger` |
||||||
823 | * as the flash message key to influence the color of the div. |
||||||
824 | * |
||||||
825 | * Note that if you use [[addFlash()]], `$message` will be an array, and you will have to adjust the above code. |
||||||
826 | * |
||||||
827 | * [bootstrap alert]: https://getbootstrap.com/docs/3.4/components/#alerts |
||||||
828 | * |
||||||
829 | * @param bool $delete whether to delete the flash messages right after this method is called. |
||||||
830 | * If false, the flash messages will be automatically deleted in the next request. |
||||||
831 | * @return array flash messages (key => message or key => [message1, message2]). |
||||||
832 | * @see setFlash() |
||||||
833 | * @see addFlash() |
||||||
834 | * @see getFlash() |
||||||
835 | * @see hasFlash() |
||||||
836 | * @see removeFlash() |
||||||
837 | */ |
||||||
838 | public function getAllFlashes($delete = false) |
||||||
839 | { |
||||||
840 | $counters = $this->get($this->flashParam, []); |
||||||
841 | $flashes = []; |
||||||
842 | foreach (array_keys($counters) as $key) { |
||||||
843 | if (array_key_exists($key, $_SESSION)) { |
||||||
844 | $flashes[$key] = $_SESSION[$key]; |
||||||
845 | if ($delete) { |
||||||
846 | unset($counters[$key], $_SESSION[$key]); |
||||||
847 | } elseif ($counters[$key] < 0) { |
||||||
848 | // mark for deletion in the next request |
||||||
849 | $counters[$key] = 1; |
||||||
850 | } |
||||||
851 | } else { |
||||||
852 | unset($counters[$key]); |
||||||
853 | } |
||||||
854 | } |
||||||
855 | |||||||
856 | $_SESSION[$this->flashParam] = $counters; |
||||||
857 | |||||||
858 | return $flashes; |
||||||
859 | } |
||||||
860 | |||||||
861 | /** |
||||||
862 | * Sets a flash message. |
||||||
863 | * A flash message will be automatically deleted after it is accessed in a request and the deletion will happen |
||||||
864 | * in the next request. |
||||||
865 | * If there is already an existing flash message with the same key, it will be overwritten by the new one. |
||||||
866 | * @param string $key the key identifying the flash message. Note that flash messages |
||||||
867 | * and normal session variables share the same name space. If you have a normal |
||||||
868 | * session variable using the same name, its value will be overwritten by this method. |
||||||
869 | * @param mixed $value flash message |
||||||
870 | * @param bool $removeAfterAccess whether the flash message should be automatically removed only if |
||||||
871 | * it is accessed. If false, the flash message will be automatically removed after the next request, |
||||||
872 | * regardless if it is accessed or not. If true (default value), the flash message will remain until after |
||||||
873 | * it is accessed. |
||||||
874 | * @see getFlash() |
||||||
875 | * @see addFlash() |
||||||
876 | * @see removeFlash() |
||||||
877 | */ |
||||||
878 | public function setFlash($key, $value = true, $removeAfterAccess = true) |
||||||
879 | { |
||||||
880 | $counters = $this->get($this->flashParam, []); |
||||||
881 | $counters[$key] = $removeAfterAccess ? -1 : 0; |
||||||
882 | $_SESSION[$key] = $value; |
||||||
883 | $_SESSION[$this->flashParam] = $counters; |
||||||
884 | } |
||||||
885 | |||||||
886 | /** |
||||||
887 | * Adds a flash message. |
||||||
888 | * If there are existing flash messages with the same key, the new one will be appended to the existing message array. |
||||||
889 | * @param string $key the key identifying the flash message. |
||||||
890 | * @param mixed $value flash message |
||||||
891 | * @param bool $removeAfterAccess whether the flash message should be automatically removed only if |
||||||
892 | * it is accessed. If false, the flash message will be automatically removed after the next request, |
||||||
893 | * regardless if it is accessed or not. If true (default value), the flash message will remain until after |
||||||
894 | * it is accessed. |
||||||
895 | * @see getFlash() |
||||||
896 | * @see setFlash() |
||||||
897 | * @see removeFlash() |
||||||
898 | */ |
||||||
899 | public function addFlash($key, $value = true, $removeAfterAccess = true) |
||||||
900 | { |
||||||
901 | $counters = $this->get($this->flashParam, []); |
||||||
902 | $counters[$key] = $removeAfterAccess ? -1 : 0; |
||||||
903 | $_SESSION[$this->flashParam] = $counters; |
||||||
904 | if (empty($_SESSION[$key])) { |
||||||
905 | $_SESSION[$key] = [$value]; |
||||||
906 | } elseif (is_array($_SESSION[$key])) { |
||||||
907 | $_SESSION[$key][] = $value; |
||||||
908 | } else { |
||||||
909 | $_SESSION[$key] = [$_SESSION[$key], $value]; |
||||||
910 | } |
||||||
911 | } |
||||||
912 | |||||||
913 | /** |
||||||
914 | * Removes a flash message. |
||||||
915 | * @param string $key the key identifying the flash message. Note that flash messages |
||||||
916 | * and normal session variables share the same name space. If you have a normal |
||||||
917 | * session variable using the same name, it will be removed by this method. |
||||||
918 | * @return mixed the removed flash message. Null if the flash message does not exist. |
||||||
919 | * @see getFlash() |
||||||
920 | * @see setFlash() |
||||||
921 | * @see addFlash() |
||||||
922 | * @see removeAllFlashes() |
||||||
923 | */ |
||||||
924 | public function removeFlash($key) |
||||||
925 | { |
||||||
926 | $counters = $this->get($this->flashParam, []); |
||||||
927 | $value = isset($_SESSION[$key], $counters[$key]) ? $_SESSION[$key] : null; |
||||||
928 | unset($counters[$key], $_SESSION[$key]); |
||||||
929 | $_SESSION[$this->flashParam] = $counters; |
||||||
930 | |||||||
931 | return $value; |
||||||
932 | } |
||||||
933 | |||||||
934 | /** |
||||||
935 | * Removes all flash messages. |
||||||
936 | * Note that flash messages and normal session variables share the same name space. |
||||||
937 | * If you have a normal session variable using the same name, it will be removed |
||||||
938 | * by this method. |
||||||
939 | * @see getFlash() |
||||||
940 | * @see setFlash() |
||||||
941 | * @see addFlash() |
||||||
942 | * @see removeFlash() |
||||||
943 | */ |
||||||
944 | public function removeAllFlashes() |
||||||
945 | { |
||||||
946 | $counters = $this->get($this->flashParam, []); |
||||||
947 | foreach (array_keys($counters) as $key) { |
||||||
948 | unset($_SESSION[$key]); |
||||||
949 | } |
||||||
950 | unset($_SESSION[$this->flashParam]); |
||||||
951 | } |
||||||
952 | |||||||
953 | /** |
||||||
954 | * Returns a value indicating whether there are flash messages associated with the specified key. |
||||||
955 | * @param string $key key identifying the flash message type |
||||||
956 | * @return bool whether any flash messages exist under specified key |
||||||
957 | */ |
||||||
958 | public function hasFlash($key) |
||||||
959 | { |
||||||
960 | return $this->getFlash($key) !== null; |
||||||
961 | } |
||||||
962 | |||||||
963 | /** |
||||||
964 | * This method is required by the interface [[\ArrayAccess]]. |
||||||
965 | * @param int|string $offset the offset to check on |
||||||
966 | * @return bool |
||||||
967 | */ |
||||||
968 | #[\ReturnTypeWillChange] |
||||||
969 | public function offsetExists($offset) |
||||||
970 | { |
||||||
971 | $this->open(); |
||||||
972 | |||||||
973 | return isset($_SESSION[$offset]); |
||||||
974 | } |
||||||
975 | |||||||
976 | /** |
||||||
977 | * This method is required by the interface [[\ArrayAccess]]. |
||||||
978 | * @param int|string $offset the offset to retrieve element. |
||||||
979 | * @return mixed the element at the offset, null if no element is found at the offset |
||||||
980 | */ |
||||||
981 | #[\ReturnTypeWillChange] |
||||||
982 | public function offsetGet($offset) |
||||||
983 | { |
||||||
984 | $this->open(); |
||||||
985 | |||||||
986 | return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null; |
||||||
987 | } |
||||||
988 | |||||||
989 | /** |
||||||
990 | * This method is required by the interface [[\ArrayAccess]]. |
||||||
991 | * @param int|string $offset the offset to set element |
||||||
992 | * @param mixed $item the element value |
||||||
993 | */ |
||||||
994 | #[\ReturnTypeWillChange] |
||||||
995 | public function offsetSet($offset, $item) |
||||||
996 | { |
||||||
997 | $this->open(); |
||||||
998 | $_SESSION[$offset] = $item; |
||||||
999 | } |
||||||
1000 | |||||||
1001 | /** |
||||||
1002 | * This method is required by the interface [[\ArrayAccess]]. |
||||||
1003 | * @param int|string $offset the offset to unset element |
||||||
1004 | */ |
||||||
1005 | #[\ReturnTypeWillChange] |
||||||
1006 | public function offsetUnset($offset) |
||||||
1007 | { |
||||||
1008 | $this->open(); |
||||||
1009 | unset($_SESSION[$offset]); |
||||||
1010 | } |
||||||
1011 | |||||||
1012 | /** |
||||||
1013 | * If session is started it's not possible to edit session ini settings. In PHP7.2+ it throws exception. |
||||||
1014 | * This function saves session data to temporary variable and stop session. |
||||||
1015 | * @since 2.0.14 |
||||||
1016 | */ |
||||||
1017 | 7 | protected function freeze() |
|||||
1018 | { |
||||||
1019 | 7 | if ($this->getIsActive()) { |
|||||
1020 | 4 | if (isset($_SESSION)) { |
|||||
1021 | 4 | $this->_frozenSessionData = $_SESSION; |
|||||
1022 | } |
||||||
1023 | 4 | $this->close(); |
|||||
1024 | 4 | Yii::info('Session frozen', __METHOD__); |
|||||
1025 | } |
||||||
1026 | } |
||||||
1027 | |||||||
1028 | /** |
||||||
1029 | * Starts session and restores data from temporary variable |
||||||
1030 | * @since 2.0.14 |
||||||
1031 | */ |
||||||
1032 | 7 | protected function unfreeze() |
|||||
1033 | { |
||||||
1034 | 7 | if (null !== $this->_frozenSessionData) { |
|||||
1035 | 4 | YII_DEBUG ? session_start() : @session_start(); |
|||||
1036 | |||||||
1037 | 4 | if ($this->getIsActive()) { |
|||||
1038 | 4 | Yii::info('Session unfrozen', __METHOD__); |
|||||
1039 | } else { |
||||||
1040 | $error = error_get_last(); |
||||||
1041 | $message = isset($error['message']) ? $error['message'] : 'Failed to unfreeze session.'; |
||||||
1042 | Yii::error($message, __METHOD__); |
||||||
1043 | } |
||||||
1044 | |||||||
1045 | 4 | $_SESSION = $this->_frozenSessionData; |
|||||
1046 | 4 | $this->_frozenSessionData = null; |
|||||
1047 | } |
||||||
1048 | } |
||||||
1049 | |||||||
1050 | /** |
||||||
1051 | * Set cache limiter |
||||||
1052 | * |
||||||
1053 | * @param string $cacheLimiter |
||||||
1054 | * @since 2.0.14 |
||||||
1055 | */ |
||||||
1056 | 1 | public function setCacheLimiter($cacheLimiter) |
|||||
1057 | { |
||||||
1058 | 1 | $this->freeze(); |
|||||
1059 | 1 | session_cache_limiter($cacheLimiter); |
|||||
1060 | 1 | $this->unfreeze(); |
|||||
1061 | } |
||||||
1062 | |||||||
1063 | /** |
||||||
1064 | * Returns current cache limiter |
||||||
1065 | * |
||||||
1066 | * @return string current cache limiter |
||||||
1067 | * @since 2.0.14 |
||||||
1068 | */ |
||||||
1069 | public function getCacheLimiter() |
||||||
1070 | { |
||||||
1071 | return session_cache_limiter(); |
||||||
1072 | } |
||||||
1073 | } |
||||||
1074 |