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