Passed
Pull Request — 5.1 (#1748)
by guanguans
09:27
created

Session::inited()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
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~2018 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
12
namespace think;
13
14
use think\exception\ClassNotFoundException;
15
16
class Session
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
17
{
18
    /**
19
     * 配置参数
20
     * @var array
21
     */
22
    protected $config = [];
23
24
    /**
25
     * 前缀
26
     * @var string
27
     */
28
    protected $prefix = '';
29
30
    /**
31
     * 是否初始化
32
     * @var bool
33
     */
34
    protected $init = null;
35
36
    /**
37
     * 锁驱动
38
     * @var object
39
     */
40
    protected $lockDriver = null;
41
42
    /**
43
     * 锁key
44
     * @var string
45
     */
46
    protected $sessKey = 'PHPSESSID';
47
48
    /**
49
     * 锁超时时间
50
     * @var integer
51
     */
52
    protected $lockTimeout = 3;
53
54
    /**
55
     * 是否启用锁机制
56
     * @var bool
57
     */
58
    protected $lock = false;
59
60
    public function __construct(array $config = [])
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
61
    {
62
        $this->config = $config;
63
    }
64
65
    /**
66
     * 设置或者获取session作用域(前缀)
67
     * @access public
68
     * @param  string $prefix
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
69
     * @return string|void
70
     */
71
    public function prefix($prefix = '')
72
    {
73
        empty($this->init) && $this->boot();
74
75
        if (empty($prefix) && null !== $prefix) {
76
            return $this->prefix;
77
        } else {
78
            $this->prefix = $prefix;
79
        }
80
    }
81
82
    public static function __make(Config $config)
1 ignored issue
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
Missing function doc comment
Loading history...
83
    {
84
        return new static($config->pull('session'));
85
    }
86
87
    /**
88
     * 配置
89
     * @access public
90
     * @param  array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
91
     * @return void
92
     */
93
    public function setConfig(array $config = [])
94
    {
95
        $this->config = array_merge($this->config, array_change_key_case($config));
96
97
        if (isset($config['prefix'])) {
98
            $this->prefix = $config['prefix'];
99
        }
100
101
        if (isset($config['use_lock'])) {
102
            $this->lock = $config['use_lock'];
103
        }
104
    }
105
106
    /**
107
     * 设置已经初始化
108
     * @access public
109
     * @return void
110
     */
111
    public function inited()
112
    {
113
        $this->init = true;
114
    }
115
116
    /**
117
     * session初始化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
118
     * @access public
119
     * @param  array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
120
     * @return void
121
     * @throws \think\Exception
122
     */
123
    public function init(array $config = [])
124
    {
125
        $config = $config ?: $this->config;
126
127
        $isDoStart = false;
128
        if (isset($config['use_trans_sid'])) {
129
            ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
130
        }
131
132
        // 启动session
133
        if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) {
134
            ini_set('session.auto_start', 0);
135
            $isDoStart = true;
136
        }
137
138
        if (isset($config['prefix'])) {
139
            $this->prefix = $config['prefix'];
140
        }
141
142
        if (isset($config['use_lock'])) {
143
            $this->lock = $config['use_lock'];
144
        }
145
146
        if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) {
147
            session_id($_REQUEST[$config['var_session_id']]);
148
        } elseif (isset($config['id']) && !empty($config['id'])) {
149
            session_id($config['id']);
150
        }
151
152
        if (isset($config['name'])) {
153
            session_name($config['name']);
154
        }
155
156
        if (isset($config['path'])) {
157
            session_save_path($config['path']);
158
        }
159
160
        if (isset($config['domain'])) {
161
            ini_set('session.cookie_domain', $config['domain']);
162
        }
163
164
        if (isset($config['expire'])) {
165
            ini_set('session.gc_maxlifetime', $config['expire']);
166
            ini_set('session.cookie_lifetime', $config['expire']);
167
        }
168
169
        if (isset($config['secure'])) {
170
            ini_set('session.cookie_secure', $config['secure']);
171
        }
172
173
        if (isset($config['httponly'])) {
174
            ini_set('session.cookie_httponly', $config['httponly']);
175
        }
176
177
        if (isset($config['use_cookies'])) {
178
            ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0);
179
        }
180
181
        if (isset($config['cache_limiter'])) {
182
            session_cache_limiter($config['cache_limiter']);
183
        }
184
185
        if (isset($config['cache_expire'])) {
186
            session_cache_expire($config['cache_expire']);
187
        }
188
189
        if (!empty($config['type'])) {
190
            // 读取session驱动
191
            $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);
192
193
            // 检查驱动类
194
            if (!class_exists($class) || !session_set_save_handler(new $class($config))) {
195
                throw new ClassNotFoundException('error session handler:' . $class, $class);
196
            }
197
        }
198
199
        if ($isDoStart) {
200
            $this->start();
201
        } else {
202
            $this->init = false;
203
        }
204
205
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type think\Session which is incompatible with the documented return type void.
Loading history...
206
    }
207
208
    /**
209
     * session自动启动或者初始化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
210
     * @access public
211
     * @return void
212
     */
213
    public function boot()
214
    {
215
        if (is_null($this->init)) {
0 ignored issues
show
introduced by
The condition is_null($this->init) is always false.
Loading history...
216
            $this->init();
217
        }
218
219
        if (false === $this->init) {
220
            if (PHP_SESSION_ACTIVE != session_status()) {
221
                $this->start();
222
            }
223
            $this->init = true;
224
        }
225
    }
226
227
    /**
228
     * session设置
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
229
     * @access public
230
     * @param  string        $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
231
     * @param  mixed         $value session值
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
232
     * @param  string|null   $prefix 作用域(前缀)
233
     * @return void
234
     */
235
    public function set($name, $value, $prefix = null)
236
    {
237
        $this->lock();
238
239
        empty($this->init) && $this->boot();
240
241
        $prefix = !is_null($prefix) ? $prefix : $this->prefix;
242
243
        if (strpos($name, '.')) {
244
            // 二维数组赋值
245
            list($name1, $name2) = explode('.', $name);
246
            if ($prefix) {
247
                $_SESSION[$prefix][$name1][$name2] = $value;
248
            } else {
249
                $_SESSION[$name1][$name2] = $value;
250
            }
251
        } elseif ($prefix) {
252
            $_SESSION[$prefix][$name] = $value;
253
        } else {
254
            $_SESSION[$name] = $value;
255
        }
256
257
        $this->unlock();
258
    }
259
260
    /**
261
     * session获取
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
262
     * @access public
263
     * @param  string        $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
264
     * @param  string|null   $prefix 作用域(前缀)
265
     * @return mixed
266
     */
267
    public function get($name = '', $prefix = null)
268
    {
269
        $this->lock();
270
271
        empty($this->init) && $this->boot();
272
273
        $prefix = !is_null($prefix) ? $prefix : $this->prefix;
274
275
        $value = $prefix ? (!empty($_SESSION[$prefix]) ? $_SESSION[$prefix] : []) : $_SESSION;
276
277
        if ('' != $name) {
278
            $name = explode('.', $name);
279
280
            foreach ($name as $val) {
281
                if (isset($value[$val])) {
282
                    $value = $value[$val];
283
                } else {
284
                    $value = null;
285
                    break;
286
                }
287
            }
288
        }
289
290
        $this->unlock();
291
292
        return $value;
293
    }
294
295
    /**
296
     * session 读写锁驱动实例化
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
297
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
298
    protected function initDriver()
299
    {
300
        $config = $this->config;
301
302
        if (!empty($config['type']) && isset($config['use_lock']) && $config['use_lock']) {
303
            // 读取session驱动
304
            $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);
305
306
            // 检查驱动类及类中是否存在 lock 和 unlock 函数
307
            if (class_exists($class) && method_exists($class, 'lock') && method_exists($class, 'unlock')) {
308
                $this->lockDriver = new $class($config);
309
            }
310
        }
311
312
        // 通过cookie获得session_id
313
        if (isset($config['name']) && $config['name']) {
314
            $this->sessKey = $config['name'];
315
        }
316
317
        if (isset($config['lock_timeout']) && $config['lock_timeout'] > 0) {
318
            $this->lockTimeout = $config['lock_timeout'];
319
        }
320
    }
321
322
    /**
323
     * session 读写加锁
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
324
     * @access protected
325
     * @return void
326
     */
327
    protected function lock()
328
    {
329
        if (empty($this->lock)) {
330
            return;
331
        }
332
333
        $this->initDriver();
334
335
        if (null !== $this->lockDriver && method_exists($this->lockDriver, 'lock')) {
336
            $t = time();
337
            // 使用 session_id 作为互斥条件,即只对同一 session_id 的会话互斥。第一次请求没有 session_id
338
            $sessID = isset($_COOKIE[$this->sessKey]) ? $_COOKIE[$this->sessKey] : '';
339
340
            do {
341
                if (time() - $t > $this->lockTimeout) {
342
                    $this->unlock();
343
                }
344
            } while (!$this->lockDriver->lock($sessID, $this->lockTimeout));
345
        }
346
    }
347
348
    /**
349
     * session 读写解锁
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
350
     * @access protected
351
     * @return void
352
     */
353
    protected function unlock()
354
    {
355
        if (empty($this->lock)) {
356
            return;
357
        }
358
359
        $this->pause();
360
361
        if ($this->lockDriver && method_exists($this->lockDriver, 'unlock')) {
362
            $sessID = isset($_COOKIE[$this->sessKey]) ? $_COOKIE[$this->sessKey] : '';
363
            $this->lockDriver->unlock($sessID);
364
        }
365
    }
366
367
    /**
368
     * session获取并删除
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
369
     * @access public
370
     * @param  string        $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
371
     * @param  string|null   $prefix 作用域(前缀)
372
     * @return mixed
373
     */
374
    public function pull($name, $prefix = null)
375
    {
376
        $result = $this->get($name, $prefix);
377
378
        if ($result) {
379
            $this->delete($name, $prefix);
380
            return $result;
381
        } else {
382
            return;
383
        }
384
    }
385
386
    /**
387
     * session设置 下一次请求有效
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
388
     * @access public
389
     * @param  string        $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
390
     * @param  mixed         $value session值
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
391
     * @param  string|null   $prefix 作用域(前缀)
0 ignored issues
show
Coding Style introduced by
Superfluous parameter comment
Loading history...
392
     * @return void
393
     */
394
    public function flash($name, $value)
395
    {
396
        $this->set($name, $value);
397
398
        if (!$this->has('__flash__.__time__')) {
399
            $this->set('__flash__.__time__', $_SERVER['REQUEST_TIME_FLOAT']);
400
        }
401
402
        $this->push('__flash__', $name);
403
    }
404
405
    /**
406
     * 清空当前请求的session数据
407
     * @access public
408
     * @return void
409
     */
410
    public function flush()
411
    {
412
        if (!$this->init) {
413
            return;
414
        }
415
416
        $item = $this->get('__flash__');
417
418
        if (!empty($item)) {
419
            $time = $item['__time__'];
420
421
            if ($_SERVER['REQUEST_TIME_FLOAT'] > $time) {
422
                unset($item['__time__']);
423
                $this->delete($item);
424
                $this->set('__flash__', []);
425
            }
426
        }
427
    }
428
429
    /**
430
     * 删除session数据
431
     * @access public
432
     * @param  string|array  $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
433
     * @param  string|null   $prefix 作用域(前缀)
434
     * @return void
435
     */
436
    public function delete($name, $prefix = null)
437
    {
438
        empty($this->init) && $this->boot();
439
440
        $prefix = !is_null($prefix) ? $prefix : $this->prefix;
441
442
        if (is_array($name)) {
443
            foreach ($name as $key) {
444
                $this->delete($key, $prefix);
445
            }
446
        } elseif (strpos($name, '.')) {
447
            list($name1, $name2) = explode('.', $name);
448
            if ($prefix) {
449
                unset($_SESSION[$prefix][$name1][$name2]);
450
            } else {
451
                unset($_SESSION[$name1][$name2]);
452
            }
453
        } else {
454
            if ($prefix) {
455
                unset($_SESSION[$prefix][$name]);
456
            } else {
457
                unset($_SESSION[$name]);
458
            }
459
        }
460
    }
461
462
    /**
463
     * 清空session数据
464
     * @access public
465
     * @param  string|null   $prefix 作用域(前缀)
466
     * @return void
467
     */
468
    public function clear($prefix = null)
469
    {
470
        empty($this->init) && $this->boot();
471
        $prefix = !is_null($prefix) ? $prefix : $this->prefix;
472
473
        if ($prefix) {
474
            unset($_SESSION[$prefix]);
475
        } else {
476
            $_SESSION = [];
477
        }
478
    }
479
480
    /**
481
     * 判断session数据
482
     * @access public
483
     * @param  string        $name session名称
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
484
     * @param  string|null   $prefix
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
485
     * @return bool
486
     */
487
    public function has($name, $prefix = null)
488
    {
489
        empty($this->init) && $this->boot();
490
491
        $prefix = !is_null($prefix) ? $prefix : $this->prefix;
492
        $value  = $prefix ? (!empty($_SESSION[$prefix]) ? $_SESSION[$prefix] : []) : $_SESSION;
493
494
        $name = explode('.', $name);
495
496
        foreach ($name as $val) {
497
            if (!isset($value[$val])) {
498
                return false;
499
            } else {
500
                $value = $value[$val];
501
            }
502
        }
503
504
        return true;
505
    }
506
507
    /**
508
     * 添加数据到一个session数组
509
     * @access public
510
     * @param  string  $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
511
     * @param  mixed   $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
512
     * @return void
513
     */
514
    public function push($key, $value)
515
    {
516
        $array = $this->get($key);
517
518
        if (is_null($array)) {
519
            $array = [];
520
        }
521
522
        $array[] = $value;
523
524
        $this->set($key, $array);
525
    }
526
527
    /**
528
     * 启动session
529
     * @access public
530
     * @return void
531
     */
532
    public function start()
533
    {
534
        session_start();
535
536
        $this->init = true;
537
    }
538
539
    /**
540
     * 销毁session
541
     * @access public
542
     * @return void
543
     */
544
    public function destroy()
545
    {
546
        if (!empty($_SESSION)) {
547
            $_SESSION = [];
548
        }
549
550
        session_unset();
551
        session_destroy();
552
553
        $this->init       = null;
554
        $this->lockDriver = null;
555
    }
556
557
    /**
558
     * 重新生成session_id
559
     * @access public
560
     * @param  bool $delete 是否删除关联会话文件
561
     * @return void
562
     */
563
    public function regenerate($delete = false)
564
    {
565
        session_regenerate_id($delete);
566
    }
567
568
    /**
569
     * 暂停session
570
     * @access public
571
     * @return void
572
     */
573
    public function pause()
574
    {
575
        // 暂停session
576
        session_write_close();
577
        $this->init = false;
578
    }
579
}
580