Completed
Push — 6.0 ( 037a27...bcbbbf )
by liu
02:39
created

File::init()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 0
dl 0
loc 12
ccs 0
cts 5
cp 0
crap 20
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\cache\driver;
14
15
use think\cache\Driver;
16
use think\Container;
17
18
/**
19
 * 文件类型缓存类
20
 * @author    liu21st <[email protected]>
1 ignored issue
show
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 1 spaces but found 4
Loading history...
21
 */
4 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 @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
22
class File extends Driver
23
{
24
    protected $options = [
25
        'expire'        => 0,
26
        'cache_subdir'  => true,
27
        'prefix'        => '',
28
        'path'          => '',
29
        'hash_type'     => 'md5',
30
        'data_compress' => false,
31
        'serialize'     => true,
32
        'tag_prefix'    => 'tag_',
33
    ];
34
35
    protected $expire;
36
37
    /**
38
     * 架构函数
39
     * @param array $options
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
40
     */
41
    public function __construct(array $options = [])
42
    {
43
        if (!empty($options)) {
44
            $this->options = array_merge($this->options, $options);
45
        }
46
47
        $app = Container::pull('app');
48
49
        if (empty($this->options['path'])) {
50
            $this->options['path'] = $app->getRuntimePath() . 'cache' . DIRECTORY_SEPARATOR;
51
        } elseif (substr($this->options['path'], -1) != DIRECTORY_SEPARATOR) {
52
            $this->options['path'] .= DIRECTORY_SEPARATOR;
53
        }
54
    }
55
56
    /**
57
     * 取得变量的存储文件名
58
     * @access protected
59
     * @param  string $name 缓存变量名
60
     * @param  bool   $auto 是否自动创建目录
61
     * @return string
62
     */
63
    protected function getCacheKey(string $name, bool $auto = false): string
64
    {
65
        $name = hash($this->options['hash_type'], $name);
66
67
        if ($this->options['cache_subdir']) {
68
            // 使用子目录
69
            $name = substr($name, 0, 2) . DIRECTORY_SEPARATOR . substr($name, 2);
70
        }
71
72
        if ($this->options['prefix']) {
73
            $name = $this->options['prefix'] . DIRECTORY_SEPARATOR . $name;
74
        }
75
76
        $filename = $this->options['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
     * 判断缓存是否存在
92
     * @access public
93
     * @param  string $name 缓存变量名
94
     * @return bool
95
     */
96
    public function has($name): bool
97
    {
98
        return false !== $this->get($name) ? true : false;
99
    }
100
101
    /**
102
     * 读取缓存
103
     * @access public
104
     * @param  string $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
105
     * @param  mixed  $default 默认值
106
     * @return mixed
107
     */
108
    public function get($name, $default = false)
109
    {
110
        $this->readTimes++;
111
112
        $filename = $this->getCacheKey($name);
113
114
        if (!is_file($filename)) {
115
            return $default;
116
        }
117
118
        $content      = file_get_contents($filename);
119
        $this->expire = null;
120
121
        if (false !== $content) {
122
            $expire = (int) substr($content, 8, 12);
123
            if (0 != $expire && time() > filemtime($filename) + $expire) {
124
                //缓存过期删除缓存文件
125
                $this->unlink($filename);
126
                return $default;
127
            }
128
129
            $this->expire = $expire;
130
            $content      = substr($content, 32);
131
132
            if ($this->options['data_compress'] && function_exists('gzcompress')) {
133
                //启用数据压缩
134
                $content = gzuncompress($content);
135
            }
136
            return $this->unserialize($content);
137
        } else {
138
            return $default;
139
        }
140
    }
141
142
    /**
143
     * 写入缓存
144
     * @access public
145
     * @param  string        $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
146
     * @param  mixed         $value  存储数据
147
     * @param  int|\DateTime $expire  有效时间 0为永久
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
148
     * @return bool
149
     */
150
    public function set($name, $value, $expire = null): bool
151
    {
152
        $this->writeTimes++;
153
154
        if (is_null($expire)) {
155
            $expire = $this->options['expire'];
156
        }
157
158
        $expire   = $this->getExpireTime($expire);
159
        $filename = $this->getCacheKey($name, true);
160
161
        if (!empty($this->tag) && !is_file($filename)) {
162
            $first = true;
163
        }
164
165
        $data = $this->serialize($value);
166
167
        if ($this->options['data_compress'] && function_exists('gzcompress')) {
168
            //数据压缩
169
            $data = gzcompress($data, 3);
170
        }
171
172
        $data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
173
        $result = file_put_contents($filename, $data);
174
175
        if ($result) {
176
            isset($first) && $this->setTagItem($filename);
177
            clearstatcache();
178
            return true;
179
        }
180
181
        return false;
182
    }
183
184
    /**
185
     * 自增缓存(针对数值缓存)
186
     * @access public
187
     * @param  string    $name 缓存变量名
188
     * @param  int       $step 步长
189
     * @return false|int
190
     */
191
    public function inc(string $name, int $step = 1)
192
    {
193
        if ($this->has($name)) {
194
            $value  = $this->get($name) + $step;
195
            $expire = $this->expire;
196
        } else {
197
            $value  = $step;
198
            $expire = 0;
199
        }
200
201
        return $this->set($name, $value, $expire) ? $value : false;
202
    }
203
204
    /**
205
     * 自减缓存(针对数值缓存)
206
     * @access public
207
     * @param  string    $name 缓存变量名
208
     * @param  int       $step 步长
209
     * @return false|int
210
     */
211
    public function dec(string $name, int $step = 1)
212
    {
213
        if ($this->has($name)) {
214
            $value  = $this->get($name) - $step;
215
            $expire = $this->expire;
216
        } else {
217
            $value  = -$step;
218
            $expire = 0;
219
        }
220
221
        return $this->set($name, $value, $expire) ? $value : false;
222
    }
223
224
    /**
225
     * 删除缓存
226
     * @access public
227
     * @param  string $name 缓存变量名
228
     * @return bool
229
     */
230
    public function rm(string $name): bool
231
    {
232
        $this->writeTimes++;
233
234
        try {
235
            return $this->unlink($this->getCacheKey($name));
236
        } catch (\Exception $e) {
237
            return false;
238
        }
239
    }
240
241
    /**
242
     * 清除缓存
243
     * @access public
244
     * @return bool
245
     */
246
    public function clear(): bool
247
    {
248
        if (!empty($this->tag)) {
249
            // 指定标签清除
250
            foreach ($this->tag as $tag) {
251
                $this->clearTag($tag);
252
            }
253
254
            return true;
255
        }
256
257
        $this->writeTimes++;
258
259
        $files = (array) glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DIRECTORY_SEPARATOR : '') . '*');
260
261
        foreach ($files as $path) {
262
            if (is_dir($path)) {
263
                $matches = glob($path . DIRECTORY_SEPARATOR . '*.php');
264
                if (is_array($matches)) {
265
                    array_map('unlink', $matches);
266
                }
267
                rmdir($path);
268
            } else {
269
                unlink($path);
270
            }
271
        }
272
273
        return true;
274
    }
275
276
    public function clearTag(string $tag)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function clearTag()
Loading history...
277
    {
278
        $keys = $this->getTagItems($tag);
279
280
        foreach ($keys as $key) {
281
            $this->unlink($key);
282
        }
283
284
        $this->rm($this->getTagKey($tag));
285
    }
286
287
    /**
288
     * 判断文件是否存在后,删除
289
     * @access private
290
     * @param  string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
291
     * @return bool
292
     */
293
    private function unlink(string $path): bool
0 ignored issues
show
Coding Style introduced by
Private method name "File::unlink" must be prefixed with an underscore
Loading history...
294
    {
295
        return is_file($path) && unlink($path);
296
    }
297
298
}
299