Issues (33)

src/Session.php (4 issues)

1
<?php
2
declare(strict_types=1);
3
4
namespace Utilities\Router;
5
6
use Utilities\Common\Common;
7
8
/**
9
 * Session class
10
 *
11
 * @link    https://github.com/utilities-php/router
12
 * @author  Shahrad Elahi (https://github.com/shahradelahi)
13
 * @license https://github.com/utilities-php/router/blob/master/LICENSE (MIT License)
14
 */
15
class Session
16
{
17
18
    /**
19
     * @var User
20
     */
21
    public static User $user;
22
    /**
23
     * @var array
24
     */
25
    private static array $cookieParams = [];
26
27
    /**
28
     * Set session value
29
     *
30
     * @param string $key
31
     * @param mixed $value
32
     * @return void
33
     */
34
    public static function set(string $key, mixed $value): void
35
    {
36
        $_SESSION[$key] = $value;
37
    }
38
39
    /**
40
     * Get session value
41
     *
42
     * @param string $key
43
     * @return mixed
44
     */
45
    public static function get(string $key): mixed
46
    {
47
        return $_SESSION[$key] ?? null;
48
    }
49
50
    /**
51
     * Check if session value exists
52
     *
53
     * @param string $key
54
     * @return bool
55
     */
56
    public static function has(string $key): bool
57
    {
58
        return isset($_SESSION[$key]);
59
    }
60
61
    /**
62
     * Delete session value
63
     *
64
     * @param string $key
65
     * @return void
66
     */
67
    public static function delete(string $key): void
68
    {
69
        unset($_SESSION[$key]);
70
    }
71
72
    /**
73
     * Destroy session
74
     *
75
     * @return void
76
     */
77
    public static function destroy(): void
78
    {
79
        session_destroy();
80
    }
81
82
    /**
83
     * Set flash value
84
     *
85
     * @param string $key
86
     * @param mixed $value
87
     * @return void
88
     */
89
    public static function flash(string $key, mixed $value): void
90
    {
91
        $_SESSION['_flash'][$key] = $value;
92
    }
93
94
    /**
95
     * Get old value
96
     *
97
     * @param string $key
98
     * @return mixed
99
     */
100
    public static function old(string $key): mixed
101
    {
102
        return $_SESSION['_old'][$key] ?? null;
103
    }
104
105
    /**
106
     * Check if old value exists
107
     *
108
     * @param string $key
109
     * @return bool
110
     */
111
    public static function hasOld(string $key): bool
112
    {
113
        return isset($_SESSION['_old'][$key]);
114
    }
115
116
    /**
117
     * Delete old value
118
     *
119
     * @param string $key
120
     * @return void
121
     */
122
    public static function deleteOld(string $key): void
123
    {
124
        unset($_SESSION['_old'][$key]);
125
    }
126
127
    /**
128
     * Destroy old values
129
     *
130
     * @return void
131
     */
132
    public static function destroyOld(): void
133
    {
134
        $_SESSION['_old'] = [];
135
    }
136
137
    /**
138
     * Regenerate session id (keeps session alive)
139
     *
140
     * @return void
141
     */
142
    public static function regenerateId(): void
143
    {
144
        session_regenerate_id(false);
145
    }
146
147
    /**
148
     * Regenerate session token
149
     *
150
     * @return void
151
     */
152
    public static function regenerateToken(): void
153
    {
154
        $_SESSION['_token'] = bin2hex(Common::randomString(32));
155
    }
156
157
    /**
158
     * Refresh session lifetime
159
     *
160
     * @param int|null $lifetime (optional) default: ini_get('session.gc_maxlifetime')
161
     * @return void
162
     */
163
    public static function refresh(int $lifetime = null): void
164
    {
165
        if ($lifetime === null) {
166
            $lifetime = intval(ini_get('session.gc_maxlifetime'));
167
        }
168
169
        static::setCookieParams([
170
            'lifetime' => $lifetime,
171
        ]);
172
173
        static::start();
174
    }
175
176
    /**
177
     * Start session
178
     *
179
     * @param array $params (optional) session cookie params
180
     * @return void
181
     */
182
    public static function start(array $params = []): void
183
    {
184
        if ($params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $params of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
185
            self::setCookieParams($params);
186
        }
187
188
        if (session_status() === PHP_SESSION_NONE) {
189
            session_set_cookie_params(static::$cookieParams);
0 ignored issues
show
Since $cookieParams is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $cookieParams to at least protected.
Loading history...
190
            session_start();
191
        }
192
193
        if (empty($_SESSION)) {
194
            $_SESSION = [];
195
        }
196
197
        $initialKeys = [
198
            '_flash' => [],
199
            '_old' => [],
200
            '_log' => [],
201
        ];
202
203
        foreach ($initialKeys as $key => $value) {
204
            if (empty($_SESSION[$key])) {
205
                $_SESSION[$key] = $value;
206
            }
207
        }
208
209
        if (empty($_SESSION['_token'])) {
210
            $_SESSION['_token'] = bin2hex(Common::randomString(32));
211
        }
212
    }
213
214
    /**
215
     * move session to another session_name
216
     *
217
     * @param string $sessionName
218
     * @return void
219
     */
220
    public static function move(string $sessionName): void
221
    {
222
        self::regenerate();
223
        session_name($sessionName);
224
        self::start();
225
    }
226
227
    /**
228
     * Regenerate session (destroy and start)
229
     *
230
     * @return void
231
     */
232
    public static function regenerate(): void
233
    {
234
        session_regenerate_id(true);
235
    }
236
237
    /**
238
     * set session id
239
     *
240
     * @param string $id
241
     * @return void
242
     */
243
    public static function setId(string $id): void
244
    {
245
        session_id($id);
246
    }
247
248
    /**
249
     * get session id
250
     *
251
     * @return string
252
     */
253
    public static function getId(): string
254
    {
255
        return session_id();
256
    }
257
258
    /**
259
     * get session name
260
     *
261
     * @return string
262
     */
263
    public static function getName(): string
264
    {
265
        return session_name();
266
    }
267
268
    /**
269
     * get session status
270
     *
271
     * @return int (0 = disabled, 1 = none, 2 = active)
272
     */
273
    public static function getStatus(): int
274
    {
275
        return session_status();
276
    }
277
278
    /**
279
     * get session cookie params
280
     *
281
     * @return array
282
     */
283
    public static function getCookieParams(): array
284
    {
285
        return static::$cookieParams;
0 ignored issues
show
Since $cookieParams is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $cookieParams to at least protected.
Loading history...
286
    }
287
288
    /**
289
     * Set session cookie params
290
     *
291
     * @param array $params
292
     * @return void
293
     */
294
    public static function setCookieParams(array $params): void
295
    {
296
        $defaults = [
297
            'lifetime' => intval(ini_get('session.gc_maxlifetime')),
298
            'path' => ini_get('session.save_path'),
299
            'domain' => ini_get('session.cookie_domain'),
300
            'secure' => ini_get('session.cookie_secure'),
301
            'httponly' => ini_get('session.cookie_httponly'),
302
        ];
303
304
        foreach ($defaults as $key => $value) {
305
            if (!isset(static::$cookieParams[$key]) && !is_null($value)) {
0 ignored issues
show
Since $cookieParams is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $cookieParams to at least protected.
Loading history...
306
                static::$cookieParams[$key] = $value;
307
            }
308
        }
309
310
        static::$cookieParams = array_merge(static::$cookieParams, $params);
311
    }
312
313
    /**
314
     * set session save path
315
     *
316
     * @param string $path
317
     * @return void
318
     */
319
    public static function setSavePath(string $path): void
320
    {
321
        session_save_path($path);
322
    }
323
324
    /**
325
     * get session save path
326
     *
327
     * @return string
328
     */
329
    public static function getSavePath(): string
330
    {
331
        return session_save_path();
332
    }
333
334
    /**
335
     * set session cache limiter
336
     *
337
     * @param string $cache_limiter
338
     * @return void
339
     */
340
    public static function setCacheLimiter(string $cache_limiter): void
341
    {
342
        session_cache_limiter($cache_limiter);
343
    }
344
345
    /**
346
     * get session cache limiter
347
     *
348
     * @return string
349
     */
350
    public static function getCacheLimiter(): string
351
    {
352
        return session_cache_limiter();
353
    }
354
355
    /**
356
     * set session cache expire
357
     *
358
     * @param int $expire
359
     * @return void
360
     */
361
    public static function setCacheExpire(int $expire): void
362
    {
363
        session_cache_expire($expire);
364
    }
365
366
    /**
367
     * get session cache expire
368
     *
369
     * @return int
370
     */
371
    public static function getCacheExpire(): int
372
    {
373
        return session_cache_expire();
374
    }
375
376
    /**
377
     * log session data
378
     *
379
     * @param string $data
380
     * @return void
381
     */
382
    public static function log(string $data): void
383
    {
384
        $_SESSION['_log'][] = $data;
385
    }
386
387
    /**
388
     * get session log
389
     *
390
     * @param string|null $key (optional) Key a specific log or all logs
391
     * @return mixed
392
     */
393
    public static function getLog(string $key = null): mixed
394
    {
395
        if ($key === null) {
396
            return $_SESSION['_log'] ?? [];
397
        }
398
399
        return $_SESSION['_log'][$key] ?? null;
400
    }
401
402
    /**
403
     * clear session log
404
     *
405
     * @return void
406
     */
407
    public static function clearLog(): void
408
    {
409
        $_SESSION['_log'] = [];
410
    }
411
412
    /**
413
     * check if there's any session log
414
     *
415
     * @return bool
416
     */
417
    public static function hasLog(): bool
418
    {
419
        return isset($_SESSION['_log']) && count($_SESSION['_log']) > 0;
420
    }
421
422
    /**
423
     * delete session log
424
     *
425
     * @param string $key
426
     * @return void
427
     */
428
    public static function deleteLog(string $key): void
429
    {
430
        unset($_SESSION['_log'][$key]);
431
    }
432
433
    /**
434
     * destroy session log
435
     *
436
     * @return void
437
     */
438
    public static function destroyLog(): void
439
    {
440
        unset($_SESSION['_log']);
441
        $_SESSION['_log'] = [];
442
    }
443
444
    /**
445
     * @param string $name
446
     * @param array $arguments
447
     * @return mixed
448
     */
449
    public static function __callStatic(string $name, array $arguments): mixed
450
    {
451
        if ($name === 'user') {
452
            return static::getUser();
453
        }
454
455
        return call_user_func_array([static::getUser(), $name], $arguments);
456
    }
457
458
    /**
459
     * get user and initiate it if it doesn't exist
460
     *
461
     * @return User
462
     */
463
    private static function getUser(): User
464
    {
465
        if (!isset($_SESSION['_user'])) {
466
            $_SESSION['_user'] = new User();
467
        }
468
469
        return $_SESSION['_user'];
470
    }
471
472
}