Passed
Push — 6.0 ( 631ba1...9e1241 )
by liu
04:02
created

Session::boot()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 4
nop 0
dl 0
loc 8
ccs 0
cts 5
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
// +----------------------------------------------------------------------
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: liu21st <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
/**
16
 * Session管理类
17
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
18
class Session
19
{
20
    /**
21
     * 配置参数
22
     * @var array
23
     */
24
    protected $config = [];
25
26
    /**
27
     * Session数据
28
     * @var array
29
     */
30
    protected $data = [];
31
32
    /**
33
     * 是否初始化
34
     * @var bool
35
     */
36
    protected $init = null;
37
38
    /**
39
     * 记录Session name
40
     * @var string
41
     */
42
    protected $sessionName = 'PHPSESSID';
43
44
    /**
45
     * 记录Session Id
46
     * @var string
47
     */
48
    protected $sessionId;
49
50
    /**
51
     * Session有效期
52
     * @var int
53
     */
54
    protected $expire = 0;
55
56
    /**
57
     * Request实例
58
     * @var Request
59
     */
60
    protected $request;
61
62
    /**
63
     * Session写入对象
64
     * @var object
65
     */
66
    protected $handler;
67
68
    public function __construct(Request $request, array $config = [])
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
69
    {
70
        $this->config  = $config;
71
        $this->request = $request;
72
    }
73
74
    public static function __make(Request $request, Config $config)
2 ignored issues
show
Coding Style introduced by
Method name "Session::__make" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
Coding Style introduced by
Public method name "Session::__make" must not be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing doc comment for function __make()
Loading history...
75
    {
76
        return new static($request, $config->get('session'));
0 ignored issues
show
Bug introduced by
It seems like $config->get('session') can also be of type null; however, parameter $config of think\Session::__construct() does only seem to accept array, 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 ignore-type  annotation

76
        return new static($request, /** @scrutinizer ignore-type */ $config->get('session'));
Loading history...
77
    }
78
79
    /**
80
     * 配置
81
     * @access public
82
     * @param  array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
83
     * @return void
84
     */
85
    public function setConfig(array $config = []): void
86
    {
87
        $this->config = array_merge($this->config, array_change_key_case($config));
88
    }
89
90
    /**
91
     * 设置数据
92
     * @access public
93
     * @param  array $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
94
     * @return void
95
     */
96
    public function setData(array $data): void
97
    {
98
        $this->data = $data;
99
    }
100
101
    /**
102
     * session初始化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
103
     * @access public
104
     * @return void
105
     * @throws \think\Exception
106
     */
107
    public function init(): void
108
    {
109
        if (!empty($this->config['name'])) {
110
            $this->sessionName = $this->config['name'];
111
        }
112
113
        if (!empty($this->config['expire'])) {
114
            $this->expire = $this->config['expire'];
115
        }
116
117
        // 初始化session写入驱动
118
        $type = !empty($this->config['type']) ? $this->config['type'] : 'File';
119
120
        $this->handler = App::factory($type, '\\think\\session\\driver\\', $this->config);
121
122
        $this->start();
123
    }
124
125
    /**
126
     * 设置SessionName
127
     * @access public
128
     * @param  string $name session_name
129
     * @return void
130
     */
131
    public function setName(string $name): void
132
    {
133
        $this->sessionName = $name;
134
    }
135
136
    /**
137
     * 获取sessionName
138
     * @access public
139
     * @return string
140
     */
141
    public function getName(): string
142
    {
143
        return $this->sessionName;
144
    }
145
146
    /**
147
     * session_id设置
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
148
     * @access public
149
     * @param  string $id session_id
150
     * @return void
151
     */
152
    public function setId(string $id): void
153
    {
154
        $this->sessionId = $id;
155
    }
156
157
    /**
158
     * 获取session_id
159
     * @access public
160
     * @param  bool $regenerate 不存在是否自动生成
161
     * @return string
162
     */
163
    public function getId(bool $regenerate = true): string
164
    {
165
        if ($this->sessionId) {
166
            return $this->sessionId;
167
        }
168
169
        return $regenerate ? $this->regenerate() : '';
170
    }
171
172
    /**
173
     * session设置
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
174
     * @access public
175
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
176
     * @param  mixed  $value session值
177
     * @return void
178
     */
179
    public function set(string $name, $value): void
180
    {
181
        empty($this->init) && $this->init();
182
183
        if (strpos($name, '.')) {
184
            // 二维数组赋值
185
            list($name1, $name2) = explode('.', $name);
186
187
            $this->data[$name1][$name2] = $value;
188
        } else {
189
            $this->data[$name] = $value;
190
        }
191
    }
192
193
    /**
194
     * session获取
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
195
     * @access public
196
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
197
     * @param  mixed  $default 默认值
198
     * @return mixed
199
     */
200
    public function get(string $name = '', $default = null)
201
    {
202
        empty($this->init) && $this->init();
203
204
        $sessionId = $this->getId();
0 ignored issues
show
Unused Code introduced by
The assignment to $sessionId is dead and can be removed.
Loading history...
205
206
        return $this->readSession($name, $default);
207
    }
208
209
    /**
210
     * session获取
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
211
     * @access protected
212
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
213
     * @param  mixed  $default 默认值
214
     * @return mixed
215
     */
216
    protected function readSession(string $name = '', $default = null)
217
    {
218
        $value = $this->data;
219
220
        if ('' != $name) {
221
            $name = explode('.', $name);
222
223
            foreach ($name as $val) {
224
                if (isset($value[$val])) {
225
                    $value = $value[$val];
226
                } else {
227
                    $value = $default;
228
                    break;
229
                }
230
            }
231
        }
232
233
        return $value;
234
    }
235
236
    /**
237
     * 删除session数据
238
     * @access public
239
     * @param  string $name session名称
240
     * @return void
241
     */
242
    public function delete(string $name): bool
243
    {
244
        empty($this->init) && $this->init();
245
246
        $sessionId = $this->getId(false);
247
248
        if (!$sessionId) {
249
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
250
        }
251
252
        if (strpos($name, '.')) {
253
            list($name1, $name2) = explode('.', $name);
254
            unset($this->data[$name1][$name2]);
255
        } else {
256
            unset($this->data[$name]);
257
        }
258
259
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type void.
Loading history...
260
    }
261
262
    /**
263
     * 保存session数据
264
     * @access public
265
     * @return void
266
     */
267
    public function save()
268
    {
269
        if ($this->handler) {
270
            $sessionId = $this->getId(false);
271
272
            if (!empty($this->data)) {
273
                $data = $this->serialize($this->data);
274
275
                $this->handler->write($sessionId, $data, $this->expire);
276
            } else {
277
                $this->handler->delete($sessionId);
278
            }
279
        }
280
    }
281
282
    /**
283
     * 清空session数据
284
     * @access public
285
     * @return void
286
     */
287
    public function clear(): void
288
    {
289
        empty($this->init) && $this->init();
290
291
        $sessionId = $this->getId(false);
292
293
        if ($sessionId) {
294
            $this->data = [];
295
        }
296
    }
297
298
    /**
299
     * 判断session数据
300
     * @access public
301
     * @param  string $name session名称
302
     * @return bool
303
     */
304
    public function has(string $name): bool
305
    {
306
        empty($this->init) && $this->init();
307
308
        $sessionId = $this->getId(false);
309
310
        if ($sessionId) {
311
            return $this->hasSession($name);
312
        }
313
314
        return false;
315
    }
316
317
    /**
318
     * 判断session数据
319
     * @access protected
320
     * @param  string $name session名称
321
     * @return bool
322
     */
323
    protected function hasSession(string $name): bool
324
    {
325
        $value = $this->data ?: [];
326
327
        $name = explode('.', $name);
328
329
        foreach ($name as $val) {
330
            if (!isset($value[$val])) {
331
                return false;
332
            } else {
333
                $value = $value[$val];
334
            }
335
        }
336
337
        return true;
338
    }
339
340
    /**
341
     * 启动session
342
     * @access public
343
     * @return void
344
     */
345
    public function start(): void
346
    {
347
        $sessionId = $this->getId();
348
349
        // 读取缓存数据
350
        if (empty($this->data)) {
351
            $data = $this->handler->read($sessionId);
352
353
            if (!empty($data)) {
354
                $this->data = $this->unserialize($data);
355
            }
356
        }
357
358
        $this->init = true;
359
    }
360
361
    /**
362
     * 销毁session
363
     * @access public
364
     * @return void
365
     */
366
    public function destroy(): void
367
    {
368
        $sessionId = $this->getId(false);
369
370
        if ($sessionId && !empty($this->data)) {
371
            $this->data = [];
372
            $this->save();
373
        }
374
    }
375
376
    /**
377
     * 重新生成session_id
378
     * @access protected
379
     * @param  bool $delete 是否删除关联会话文件
380
     * @return string
381
     */
382
    protected function regenerate(bool $delete = false): string
383
    {
384
        if ($delete) {
385
            $data = $this->data;
386
            $this->destroy();
387
            $this->data = $data;
388
        }
389
390
        $sessionId = md5(microtime(true) . uniqid());
391
392
        $this->setId($sessionId);
393
        return $sessionId;
394
    }
395
396
    /**
397
     * session获取并删除
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
398
     * @access public
399
     * @param  string $name session名称
400
     * @return mixed
401
     */
402
    public function pull(string $name)
403
    {
404
        $result = $this->get($name);
405
406
        if ($result) {
407
            $this->delete($name);
408
            return $result;
409
        }
410
    }
411
412
    /**
413
     * session设置 下一次请求有效
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
414
     * @access public
415
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
416
     * @param  mixed  $value session值
417
     * @return void
418
     */
419
    public function flash(string $name, $value): void
420
    {
421
        $this->set($name, $value);
422
423
        if (!$this->has('__flash__.__time__')) {
424
            $this->set('__flash__.__time__', $this->request->time(true));
425
        }
426
427
        $this->push('__flash__', $name);
428
    }
429
430
    /**
431
     * 清空当前请求的session数据
432
     * @access public
433
     * @return void
434
     */
435
    public function flush()
436
    {
437
        if (!$this->init) {
438
            return;
439
        }
440
441
        $items = $this->get('__flash__');
442
443
        if (!empty($items)) {
444
            $time = $items['__time__'];
445
446
            if ($this->request->time(true) > $time) {
447
                unset($items['__time__']);
448
449
                foreach ($items as $item) {
450
                    $this->delete($item);
451
                }
452
453
                $this->set('__flash__', []);
454
            }
455
        }
456
    }
457
458
    /**
459
     * 添加数据到一个session数组
460
     * @access public
461
     * @param  string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
462
     * @param  mixed  $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
463
     * @return void
464
     */
465
    public function push(string $key, $value): void
466
    {
467
        $array = $this->get($key);
468
469
        if (is_null($array)) {
470
            $array = [];
471
        }
472
473
        $array[] = $value;
474
475
        $this->set($key, $array);
476
    }
477
478
    /**
479
     * 序列化数据
480
     * @access protected
481
     * @param  mixed $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
482
     * @return string
483
     */
484
    protected function serialize($data): string
485
    {
486
        $serialize = $this->config['serialize'][0] ?? 'serialize';
487
488
        return $serialize($data);
489
    }
490
491
    /**
492
     * 反序列化数据
493
     * @access protected
494
     * @param  string $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
495
     * @return array
496
     */
497
    protected function unserialize(string $data): array
498
    {
499
        $unserialize = $this->config['serialize'][1] ?? 'unserialize';
500
501
        return (array) $unserialize($data);
502
    }
503
}
504