Passed
Push — 6.0 ( f409e2...e26961 )
by liu
02:35
created

File::read()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 27
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 5
nop 1
dl 0
loc 27
rs 8.8333
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\session\driver;
14
15
use think\App;
16
use think\session\SessionHandler;
17
18
class File implements SessionHandler
1 ignored issue
show
Coding Style introduced by
Missing class doc comment
Loading history...
19
{
20
    protected $config = [
21
        'path'          => '',
22
        'expire'        => 0,
23
        'cache_subdir'  => true,
24
        'data_compress' => false,
25
        'serialize'     => ['serialize', 'unserialize'],
26
    ];
27
28
    public function __construct(App $app, array $config = [])
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
29
    {
30
        $this->config = array_merge($this->config, $config);
31
32
        if (empty($this->config['path'])) {
33
            $this->config['path'] = $app->getRuntimePath() . 'session' . DIRECTORY_SEPARATOR;
34
        } elseif (substr($this->config['path'], -1) != DIRECTORY_SEPARATOR) {
35
            $this->config['path'] .= DIRECTORY_SEPARATOR;
36
        }
37
38
        $this->init();
39
    }
40
41
    /**
42
     * 初始化检查
43
     * @access private
44
     * @return bool
45
     */
46
    private function init(): bool
0 ignored issues
show
Coding Style introduced by
Private method name "File::init" must be prefixed with an underscore
Loading history...
47
    {
48
        // 创建项目缓存目录
49
        try {
50
            if (!is_dir($this->config['path']) && mkdir($this->config['path'], 0755, true)) {
51
                return true;
52
            }
53
        } catch (\Exception $e) {
54
            // 写入失败
55
        }
56
57
        return false;
58
    }
59
60
    /**
61
     * 取得变量的存储文件名
62
     * @access protected
63
     * @param  string $name 缓存变量名
64
     * @param  bool   $auto 是否自动创建目录
65
     * @return string
66
     */
67
    protected function getFileName(string $name, bool $auto = false): string
68
    {
69
        if ($this->config['cache_subdir']) {
70
            // 使用子目录
71
            $name = substr($name, 0, 2) . DIRECTORY_SEPARATOR . 'sess_' . $name;
72
        } else {
73
            $name = 'sess_' . $name;
74
        }
75
76
        $filename = $this->config['path'] . $name . '.php';
77
        $dir      = dirname($filename);
78
79
        if ($auto && !is_dir($dir)) {
80
            try {
81
                mkdir($dir, 0755, true);
82
            } catch (\Exception $e) {
83
                // 创建失败
84
            }
85
        }
86
87
        return $filename;
88
    }
89
90
    /**
91
     * 读取Session
92
     * @access public
93
     * @param  string $sessionId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
94
     * @return array
95
     */
96
    public function read(string $sessionId): array
97
    {
98
        $filename = $this->getFileName($sessionId);
99
100
        if (!is_file($filename)) {
101
            return [];
102
        }
103
104
        $content = file_get_contents($filename);
105
106
        if (false !== $content) {
107
            $expire = (int) substr($content, 8, 12);
108
            if (0 != $expire && time() > filemtime($filename) + $expire) {
109
                //缓存过期删除缓存文件
110
                $this->unlink($filename);
111
                return [];
112
            }
113
114
            $content = substr($content, 32);
115
116
            if ($this->config['data_compress'] && function_exists('gzcompress')) {
117
                //启用数据压缩
118
                $content = gzuncompress($content);
119
            }
120
            return $this->unserialize($content);
121
        } else {
122
            return [];
123
        }
124
    }
125
126
    /**
127
     * 写入Session
128
     * @access public
129
     * @param  string $sessionId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
130
     * @param  array  $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
131
     * @return array
132
     */
133
    public function write(string $sessionId, array $data): bool
134
    {
135
        $expire = $this->config['expire'];
136
137
        $expire   = $this->getExpireTime($expire);
138
        $filename = $this->getFileName($sessionId, true);
139
140
        $data = $this->serialize($data);
141
142
        if ($this->config['data_compress'] && function_exists('gzcompress')) {
143
            //数据压缩
144
            $data = gzcompress($data, 3);
145
        }
146
147
        $data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
148
        $result = file_put_contents($filename, $data);
149
150
        if ($result) {
151
            clearstatcache();
152
            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 array.
Loading history...
153
        }
154
155
        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 array.
Loading history...
156
    }
157
158
    /**
159
     * 删除Session
160
     * @access public
161
     * @param  string $sessionId
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
162
     * @return array
163
     */
164
    public function delete(string $sessionId): bool
165
    {
166
        try {
167
            return $this->unlink($this->getFileName($sessionId));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->unlink($th...etFileName($sessionId)) returns the type boolean which is incompatible with the documented return type array.
Loading history...
168
        } catch (\Exception $e) {
169
            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 array.
Loading history...
170
        }
171
    }
172
173
    /**
174
     * 获取有效期
175
     * @access protected
176
     * @param  integer|\DateTimeInterface $expire 有效期
177
     * @return int
178
     */
179
    protected function getExpireTime($expire): int
180
    {
181
        if ($expire instanceof \DateTimeInterface) {
182
            $expire = $expire->getTimestamp() - time();
183
        }
184
185
        return (int) $expire;
186
    }
187
188
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $file should have a doc-comment as per coding-style.
Loading history...
189
     * 判断文件是否存在后,删除
190
     * @access private
191
     * @param  string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $path does not match actual variable name $file
Loading history...
192
     * @return bool
193
     */
194
    private function unlink(string $file): bool
0 ignored issues
show
Coding Style introduced by
Private method name "File::unlink" must be prefixed with an underscore
Loading history...
195
    {
196
        return is_file($file) && unlink($file);
197
    }
198
199
    /**
200
     * 序列化数据
201
     * @access protected
202
     * @param  mixed $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
203
     * @return string
204
     */
205
    protected function serialize($data): string
206
    {
207
        $serialize = $this->config['serialize'][0];
208
209
        return $serialize($data);
210
    }
211
212
    /**
213
     * 反序列化数据
214
     * @access protected
215
     * @param  string $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
216
     * @return mixed
217
     */
218
    protected function unserialize(string $data)
219
    {
220
        $unserialize = $this->config['serialize'][1];
221
222
        return $unserialize($data);
223
    }
224
225
}
226