Passed
Push — 6.0 ( 2f4a30...06cc73 )
by liu
02:46
created

Driver   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 276
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 64
dl 0
loc 276
ccs 0
cts 73
cp 0
rs 9.84
c 0
b 0
f 0
wmc 32

15 Methods

Rating   Name   Duplication   Size   Complexity  
A tag() 0 7 2
A getCacheKey() 0 3 1
A setTagItem() 0 23 5
A remember() 0 33 6
A pull() 0 7 2
A getExpireTime() 0 7 2
A getTagKey() 0 3 1
A getReadTimes() 0 3 1
A serialize() 0 9 3
A handler() 0 3 1
A unserialize() 0 8 3
A getTagItems() 0 6 2
A registerSerialize() 0 3 1
A getWriteTimes() 0 3 1
A __call() 0 3 1
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;
14
15
use think\Container;
16
17
/**
18
 * 缓存基础类
19
 */
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...
20
abstract class Driver extends SimpleCache
21
{
22
    /**
23
     * 驱动句柄
24
     * @var object
25
     */
26
    protected $handler = null;
27
28
    /**
29
     * 缓存读取次数
30
     * @var integer
31
     */
32
    protected $readTimes = 0;
33
34
    /**
35
     * 缓存写入次数
36
     * @var integer
37
     */
38
    protected $writeTimes = 0;
39
40
    /**
41
     * 缓存参数
42
     * @var array
43
     */
44
    protected $options = [];
45
46
    /**
47
     * 缓存标签
48
     * @var array
49
     */
50
    protected $tag;
51
52
    /**
53
     * 序列化方法
54
     * @var array
55
     */
56
    protected static $serialize = ['\think\App::serialize', '\think\App::unserialize', 'think_serialize:', 16];
57
58
    /**
59
     * 获取有效期
60
     * @access protected
61
     * @param  integer|\DateTimeInterface $expire 有效期
62
     * @return int
63
     */
64
    protected function getExpireTime($expire): int
65
    {
66
        if ($expire instanceof \DateTimeInterface) {
67
            $expire = $expire->getTimestamp() - time();
68
        }
69
70
        return (int) $expire;
71
    }
72
73
    /**
74
     * 获取实际的缓存标识
75
     * @access protected
76
     * @param  string $name 缓存名
77
     * @return string
78
     */
79
    protected function getCacheKey(string $name): string
80
    {
81
        return $this->options['prefix'] . $name;
82
    }
83
84
    /**
85
     * 读取缓存并删除
86
     * @access public
87
     * @param  string $name 缓存变量名
88
     * @return mixed
89
     */
90
    public function pull(string $name)
91
    {
92
        $result = $this->get($name, false);
93
94
        if ($result) {
95
            $this->rm($name);
96
            return $result;
97
        }
98
    }
99
100
    /**
101
     * 如果不存在则写入缓存
102
     * @access public
103
     * @param  string $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
104
     * @param  mixed  $value  存储数据
105
     * @param  int    $expire  有效时间 0为永久
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
106
     * @return mixed
107
     */
108
    public function remember(string $name, $value, $expire = null)
109
    {
110
        if ($this->has($name)) {
111
            return $this->get($name);
112
        }
113
114
        $time = time();
115
116
        while ($time + 5 > time() && $this->has($name . '_lock')) {
117
            // 存在锁定则等待
118
            usleep(200000);
119
        }
120
121
        try {
122
            // 锁定
123
            $this->set($name . '_lock', true);
124
125
            if ($value instanceof \Closure) {
126
                // 获取缓存数据
127
                $value = Container::getInstance()->invokeFunction($value);
128
            }
129
130
            // 缓存数据
131
            $this->set($name, $value, $expire);
132
133
            // 解锁
134
            $this->rm($name . '_lock');
135
        } catch (\Exception | \throwable $e) {
136
            $this->rm($name . '_lock');
137
            throw $e;
138
        }
139
140
        return $value;
141
    }
142
143
    /**
144
     * 缓存标签
145
     * @access public
146
     * @param  string|array $name 标签名
147
     * @return $this
148
     */
149
    public function tag($name)
150
    {
151
        if ($name) {
152
            $this->tag = (array) $name;
153
        }
154
155
        return $this;
156
    }
157
158
    /**
159
     * 更新标签
160
     * @access protected
161
     * @param  string $name 缓存标识
162
     * @return void
163
     */
164
    protected function setTagItem(string $name): void
165
    {
166
        if (!empty($this->tag)) {
167
            $tags      = $this->tag;
168
            $this->tag = null;
169
170
            foreach ($tags as $tag) {
171
                $key = $this->getTagKey($tag);
172
173
                if ($this->has($key)) {
174
                    $value   = explode(',', $this->get($key));
175
                    $value[] = $name;
176
177
                    if (count($value) > 1000) {
178
                        array_shift($value);
179
                    }
180
181
                    $value = implode(',', array_unique($value));
182
                } else {
183
                    $value = $name;
184
                }
185
186
                $this->set($key, $value, 0);
187
            }
188
        }
189
    }
190
191
    /**
192
     * 获取标签包含的缓存标识
193
     * @access protected
194
     * @param  string $tag 缓存标签
195
     * @return array
196
     */
197
    protected function getTagItems(string $tag): array
198
    {
199
        $key   = $this->getTagkey($tag);
200
        $value = $this->get($key);
201
202
        return $value ? array_filter(explode(',', $value)) : [];
203
    }
204
205
    /**
206
     * 获取实际标签名
207
     * @access protected
208
     * @param  string $tag 标签名
209
     * @return string
210
     */
211
    protected function getTagKey(string $tag): string
212
    {
213
        return $this->options['tag_prefix'] . md5($tag);
214
    }
215
216
    /**
217
     * 序列化数据
218
     * @access protected
219
     * @param  mixed $data 缓存数据
220
     * @return string
221
     */
222
    protected function serialize($data)
223
    {
224
        if (is_scalar($data) || !$this->options['serialize']) {
225
            return $data;
226
        }
227
228
        $serialize = self::$serialize[0];
229
230
        return self::$serialize[2] . $serialize($data);
231
    }
232
233
    /**
234
     * 反序列化数据
235
     * @access protected
236
     * @param  string $data 缓存数据
237
     * @return mixed
238
     */
239
    protected function unserialize($data)
240
    {
241
        if ($this->options['serialize'] && 0 === strpos($data, self::$serialize[2])) {
242
            $unserialize = self::$serialize[1];
243
            return $unserialize(substr($data, self::$serialize[3]));
244
        }
245
246
        return $data;
247
    }
248
249
    /**
250
     * 注册序列化机制
251
     * @access public
252
     * @param  callable $serialize   序列化方法
253
     * @param  callable $unserialize 反序列化方法
254
     * @param  string   $prefix      序列化前缀标识
255
     * @return void
256
     */
257
    public static function registerSerialize(callable $serialize, callable $unserialize, string $prefix = 'think_serialize:'): void
258
    {
259
        self::$serialize = [$serialize, $unserialize, $prefix, strlen($prefix)];
260
    }
261
262
    /**
263
     * 返回句柄对象,可执行其它高级方法
264
     *
265
     * @access public
266
     * @return object
267
     */
268
    public function handler()
269
    {
270
        return $this->handler;
271
    }
272
273
    /**
274
     * 返回缓存读取次数
275
     * @access public
276
     * @return int
277
     */
278
    public function getReadTimes(): int
279
    {
280
        return $this->readTimes;
281
    }
282
283
    /**
284
     * 返回缓存写入次数
285
     * @access public
286
     * @return int
287
     */
288
    public function getWriteTimes(): int
289
    {
290
        return $this->writeTimes;
291
    }
292
293
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __call()
Loading history...
294
    {
295
        return call_user_func_array([$this->handler, $method], $args);
296
    }
297
}
298