Passed
Push — 6.0 ( 88644f...134599 )
by liu
03:12 queued 10s
created

Session::unserialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
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
class Session
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
16
{
17
    /**
18
     * 配置参数
19
     * @var array
20
     */
21
    protected $config = [];
22
23
    /**
24
     * Session数据
25
     * @var array
26
     */
27
    protected $data = [];
28
29
    /**
30
     * 是否初始化
31
     * @var bool
32
     */
33
    protected $init = null;
34
35
    /**
36
     * 记录Session name
37
     * @var string
38
     */
39
    protected $sessionName = 'PHPSESSID';
40
41
    /**
42
     * 记录Session Id
43
     * @var string
44
     */
45
    protected $sessionId;
46
47
    /**
48
     * Session有效期
49
     * @var int
50
     */
51
    protected $expire = 0;
52
53
    /**
54
     * App实例
55
     * @var App
56
     */
57
    protected $app;
58
59
    /**
60
     * Session写入对象
61
     * @var object
62
     */
63
    protected $handler;
64
65
    public function __construct(App $app, array $config = [])
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
66
    {
67
        $this->config = $config;
68
        $this->app    = $app;
69
    }
70
71
    public static function __make(App $app, Config $config)
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
Coding Style introduced by
Method name "Session::__make" is invalid; only PHP magic methods should be prefixed with a double underscore
Loading history...
72
    {
73
        return new static($app, $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

73
        return new static($app, /** @scrutinizer ignore-type */ $config->get('session'));
Loading history...
74
    }
75
76
    /**
77
     * 配置
78
     * @access public
79
     * @param  array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
80
     * @return void
81
     */
82
    public function setConfig(array $config = []): void
83
    {
84
        $this->config = array_merge($this->config, array_change_key_case($config));
85
    }
86
87
    /**
88
     * 设置数据
89
     * @access public
90
     * @param  array $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
91
     * @return void
92
     */
93
    public function setData(array $data): void
94
    {
95
        $this->data = $data;
96
    }
97
98
    /**
99
     * session初始化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
100
     * @access public
101
     * @return void
102
     * @throws \think\Exception
103
     */
104
    public function init(): void
105
    {
106
        if (!empty($this->config['name'])) {
107
            $this->sessionName = $this->config['name'];
108
        }
109
110
        if (!empty($this->config['expire'])) {
111
            $this->expire = $this->config['expire'];
112
        }
113
114
        // 初始化session写入驱动
115
        $type = !empty($this->config['type']) ? $this->config['type'] : 'File';
116
117
        $this->handler = $this->app->factory($type, '\\think\\session\\driver\\', $this->config);
118
119
        if (!empty($this->config['auto_start'])) {
120
            $this->start();
121
        } else {
122
            $this->init = false;
123
        }
124
    }
125
126
    /**
127
     * session自动启动或者初始化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
128
     * @access public
129
     * @return void
130
     */
131
    public function boot(): void
132
    {
133
        if (is_null($this->init)) {
0 ignored issues
show
introduced by
The condition is_null($this->init) is always false.
Loading history...
134
            $this->init();
135
        }
136
137
        if (false === $this->init) {
138
            $this->start();
139
        }
140
    }
141
142
    public function setName(string $name): void
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
143
    {
144
        $this->sessionName = $name;
145
    }
146
147
    public function getName(): string
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
148
    {
149
        return $this->sessionName;
150
    }
151
152
    /**
153
     * session_id设置
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
154
     * @access public
155
     * @param  string $id session_id
156
     * @return void
157
     */
158
    public function setId(string $id): void
159
    {
160
        $this->sessionId = $id;
161
    }
162
163
    /**
164
     * 获取session_id
165
     * @access public
166
     * @param  bool $regenerate 不存在是否自动生成
167
     * @return string
168
     */
169
    public function getId(bool $regenerate = true): string
170
    {
171
        if ($this->sessionId) {
172
            return $this->sessionId;
173
        }
174
175
        return $regenerate ? $this->regenerate() : '';
176
    }
177
178
    /**
179
     * session设置
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
180
     * @access public
181
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
182
     * @param  mixed  $value session值
183
     * @return void
184
     */
185
    public function set(string $name, $value): void
186
    {
187
        empty($this->init) && $this->boot();
188
189
        $sessionId = $this->getId();
190
191
        if (strpos($name, '.')) {
192
            // 二维数组赋值
193
            list($name1, $name2) = explode('.', $name);
194
195
            $this->data[$sessionId][$name1][$name2] = $value;
196
        } else {
197
            $this->data[$sessionId][$name] = $value;
198
        }
199
    }
200
201
    /**
202
     * session获取
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
203
     * @access public
204
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
205
     * @param  mixed  $default 默认值
206
     * @return mixed
207
     */
208
    public function get(string $name = '', $default = null)
209
    {
210
        empty($this->init) && $this->boot();
211
212
        $sessionId = $this->getId();
213
214
        return $this->readSession($sessionId, $name, $default);
215
    }
216
217
    /**
218
     * session获取
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
219
     * @access protected
220
     * @param  string $sessionId session_id
221
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 1 found
Loading history...
222
     * @param  mixed  $default 默认值
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
223
     * @return mixed
224
     */
225
    protected function readSession(string $sessionId, string $name = '', $default = null)
226
    {
227
        $value = $this->data[$sessionId] ?? [];
228
229
        if (!is_array($value)) {
230
            $value = [];
231
        }
232
233
        if ('' != $name) {
234
            $name = explode('.', $name);
235
236
            foreach ($name as $val) {
237
                if (isset($value[$val])) {
238
                    $value = $value[$val];
239
                } else {
240
                    $value = $default;
241
                    break;
242
                }
243
            }
244
        }
245
246
        return $value;
247
    }
248
249
    /**
250
     * 删除session数据
251
     * @access public
252
     * @param  string|array $name session名称
253
     * @return void
254
     */
255
    public function delete($name): bool
256
    {
257
        empty($this->init) && $this->boot();
258
259
        $sessionId = $this->getId(false);
260
261
        if (!$sessionId) {
262
            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...
263
        }
264
265
        if (is_array($name)) {
266
            foreach ($name as $key) {
267
                $this->deleteSession($sessionId, $key);
0 ignored issues
show
Bug introduced by
The method deleteSession() does not exist on think\Session. Did you maybe mean delete()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

267
                $this->/** @scrutinizer ignore-call */ 
268
                       deleteSession($sessionId, $key);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
268
            }
269
        } elseif (strpos($name, '.')) {
270
            list($name1, $name2) = explode('.', $name);
271
            unset($this->data[$sessionId][$name1][$name2]);
272
        } else {
273
            unset($this->data[$sessionId][$name]);
274
        }
275
276
        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...
277
    }
278
279
    /**
280
     * 保存session数据
281
     * @access public
282
     * @return void
283
     */
284
    public function save()
285
    {
286
        $sessionId = $this->getId(false);
287
288
        if (!empty($this->data[$sessionId])) {
289
            $data = $this->serialize($this->data[$sessionId]);
290
291
            $this->handler->write($sessionId, $data, $this->expire);
292
        } else {
293
            $this->handler->delete($sessionId);
294
        }
295
    }
296
297
    /**
298
     * 清空session数据
299
     * @access public
300
     * @return void
301
     */
302
    public function clear(): void
303
    {
304
        empty($this->init) && $this->boot();
305
306
        $sessionId = $this->getId(false);
307
308
        if ($sessionId) {
309
            $this->data[$sessionId] = [];
310
        }
311
    }
312
313
    /**
314
     * 判断session数据
315
     * @access public
316
     * @param  string $name session名称
317
     * @return bool
318
     */
319
    public function has(string $name): bool
320
    {
321
        empty($this->init) && $this->boot();
322
323
        $sessionId = $this->getId(false);
324
325
        if ($sessionId) {
326
            return $this->hasSession($sessionId, $name);
327
        }
328
329
        return false;
330
    }
331
332
    /**
333
     * 判断session数据
334
     * @access protected
335
     * @param  string $sessionId session_id
336
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 1 found
Loading history...
337
     * @return bool
338
     */
339
    protected function hasSession(string $sessionId, string $name): bool
340
    {
341
        $value = $this->data[$sessionId] ?? [];
342
343
        $name = explode('.', $name);
344
345
        foreach ($name as $val) {
346
            if (!isset($value[$val])) {
347
                return false;
348
            } else {
349
                $value = $value[$val];
350
            }
351
        }
352
353
        return true;
354
    }
355
356
    /**
357
     * 启动session
358
     * @access public
359
     * @return void
360
     */
361
    public function start(): void
362
    {
363
        $sessionId = $this->getId();
364
365
        // 读取缓存数据
366
        if (empty($this->data[$sessionId])) {
367
            $data = $this->handler->read($sessionId);
368
369
            if (!empty($data)) {
370
                $this->data[$sessionId] = $this->unserialize($data);
371
            }
372
        }
373
374
        $this->init = true;
375
    }
376
377
    /**
378
     * 销毁session
379
     * @access public
380
     * @return void
381
     */
382
    public function destroy(): void
383
    {
384
        $sessionId = $this->getId(false);
385
386
        if ($sessionId && isset($this->data[$sessionId])) {
387
            unset($this->data[$sessionId]);
388
        }
389
390
        $this->init = null;
391
    }
392
393
    /**
394
     * 生成session_id
395
     * @access public
396
     * @param  bool $delete 是否删除关联会话文件
397
     * @return string
398
     */
399
    public function regenerate(bool $delete = false): string
400
    {
401
        if ($delete) {
402
            $this->destroy();
403
        }
404
405
        $sessionId = md5(microtime(true) . uniqid());
406
407
        $this->sessionId = $sessionId;
408
        return $sessionId;
409
    }
410
411
    /**
412
     * 暂停session
413
     * @access public
414
     * @return void
415
     */
416
    public function pause(): void
417
    {
418
        $this->init = false;
419
    }
420
421
    /**
422
     * session获取并删除
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
423
     * @access public
424
     * @param  string $name session名称
425
     * @return mixed
426
     */
427
    public function pull(string $name)
428
    {
429
        $result = $this->get($name);
430
431
        if ($result) {
432
            $this->delete($name);
433
            return $result;
434
        }
435
    }
436
437
    /**
438
     * session设置 下一次请求有效
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
439
     * @access public
440
     * @param  string $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
441
     * @param  mixed  $value session值
442
     * @return void
443
     */
444
    public function flash(string $name, $value): void
445
    {
446
        $this->set($name, $value);
447
448
        if (!$this->has('__flash__.__time__')) {
449
            $this->set('__flash__.__time__', $this->app->request->time(true));
450
        }
451
452
        $this->push('__flash__', $name);
453
    }
454
455
    /**
456
     * 清空当前请求的session数据
457
     * @access public
458
     * @return void
459
     */
460
    public function flush()
461
    {
462
        if (!$this->init) {
463
            return;
464
        }
465
466
        $item = $this->get('__flash__');
467
468
        if (!empty($item)) {
469
            $time = $item['__time__'];
470
471
            if ($this->app->request->time(true) > $time) {
472
                unset($item['__time__']);
473
                $this->delete($item);
474
                $this->set('__flash__', []);
475
            }
476
        }
477
    }
478
479
    /**
480
     * 添加数据到一个session数组
481
     * @access public
482
     * @param  string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
483
     * @param  mixed  $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
484
     * @return void
485
     */
486
    public function push(string $key, $value): void
487
    {
488
        $array = $this->get($key);
489
490
        if (is_null($array)) {
491
            $array = [];
492
        }
493
494
        $array[] = $value;
495
496
        $this->set($key, $array);
497
    }
498
499
    /**
500
     * 序列化数据
501
     * @access protected
502
     * @param  mixed $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
503
     * @return string
504
     */
505
    protected function serialize($data): string
506
    {
507
        $serialize = $this->config['serialize'][0] ?? 'serialize';
508
509
        return $serialize($data);
510
    }
511
512
    /**
513
     * 反序列化数据
514
     * @access protected
515
     * @param  string $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
516
     * @return mixed
517
     */
518
    protected function unserialize(string $data)
519
    {
520
        $unserialize = $this->config['serialize'][1] ?? 'unserialize';
521
522
        return $unserialize($data);
523
    }
524
}
525