Passed
Push — 5.1 ( 4f3592...135eee )
by liu
07:11 queued 19s
created

Driver::unserialize()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 1
dl 0
loc 8
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\cache;
13
14
use think\Container;
15
16
/**
17
 * 缓存基础类
18
 */
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...
19
abstract class Driver
20
{
21
    /**
22
     * 驱动句柄
23
     * @var object
24
     */
25
    protected $handler = null;
26
27
    /**
28
     * 缓存读取次数
29
     * @var integer
30
     */
31
    protected $readTimes = 0;
32
33
    /**
34
     * 缓存写入次数
35
     * @var integer
36
     */
37
    protected $writeTimes = 0;
38
39
    /**
40
     * 缓存参数
41
     * @var array
42
     */
43
    protected $options = [];
44
45
    /**
46
     * 缓存标签
47
     * @var string
48
     */
49
    protected $tag;
50
51
    /**
52
     * 序列化方法
53
     * @var array
54
     */
55
    protected static $serialize = ['serialize', 'unserialize', 'think_serialize:', 16];
56
57
    /**
58
     * 判断缓存是否存在
59
     * @access public
60
     * @param  string $name 缓存变量名
61
     * @return bool
62
     */
63
    abstract public function has($name);
64
65
    /**
66
     * 读取缓存
67
     * @access public
68
     * @param  string $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
69
     * @param  mixed  $default 默认值
70
     * @return mixed
71
     */
72
    abstract public function get($name, $default = false);
73
74
    /**
75
     * 写入缓存
76
     * @access public
77
     * @param  string    $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
78
     * @param  mixed     $value  存储数据
79
     * @param  int       $expire  有效时间 0为永久
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
80
     * @return boolean
81
     */
82
    abstract public function set($name, $value, $expire = null);
83
84
    /**
85
     * 自增缓存(针对数值缓存)
86
     * @access public
87
     * @param  string    $name 缓存变量名
88
     * @param  int       $step 步长
89
     * @return false|int
90
     */
91
    abstract public function inc($name, $step = 1);
92
93
    /**
94
     * 自减缓存(针对数值缓存)
95
     * @access public
96
     * @param  string    $name 缓存变量名
97
     * @param  int       $step 步长
98
     * @return false|int
99
     */
100
    abstract public function dec($name, $step = 1);
101
102
    /**
103
     * 删除缓存
104
     * @access public
105
     * @param  string $name 缓存变量名
106
     * @return boolean
107
     */
108
    abstract public function rm($name);
109
110
    /**
111
     * 清除缓存
112
     * @access public
113
     * @param  string $tag 标签名
114
     * @return boolean
115
     */
116
    abstract public function clear($tag = null);
117
118
    /**
119
     * 获取有效期
120
     * @access protected
121
     * @param  integer|\DateTime $expire 有效期
122
     * @return integer
123
     */
124
    protected function getExpireTime($expire)
125
    {
126
        if ($expire instanceof \DateTime) {
127
            $expire = $expire->getTimestamp() - time();
128
        }
129
130
        return $expire;
131
    }
132
133
    /**
134
     * 获取实际的缓存标识
135
     * @access protected
136
     * @param  string $name 缓存名
137
     * @return string
138
     */
139
    protected function getCacheKey($name)
140
    {
141
        return $this->options['prefix'] . $name;
142
    }
143
144
    /**
145
     * 读取缓存并删除
146
     * @access public
147
     * @param  string $name 缓存变量名
148
     * @return mixed
149
     */
150
    public function pull($name)
151
    {
152
        $result = $this->get($name, false);
153
154
        if ($result) {
155
            $this->rm($name);
156
            return $result;
157
        } else {
158
            return;
159
        }
160
    }
161
162
    /**
163
     * 如果不存在则写入缓存
164
     * @access public
165
     * @param  string    $name 缓存变量名
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
166
     * @param  mixed     $value  存储数据
167
     * @param  int       $expire  有效时间 0为永久
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 2 found
Loading history...
168
     * @return mixed
169
     */
170
    public function remember($name, $value, $expire = null)
171
    {
172
        if (!$this->has($name)) {
173
            $time = time();
174
            while ($time + 5 > time() && $this->has($name . '_lock')) {
175
                // 存在锁定则等待
176
                usleep(200000);
177
            }
178
179
            try {
180
                // 锁定
181
                $this->set($name . '_lock', true);
182
183
                if ($value instanceof \Closure) {
184
                    // 获取缓存数据
185
                    $value = Container::getInstance()->invokeFunction($value);
186
                }
187
188
                // 缓存数据
189
                $this->set($name, $value, $expire);
190
191
                // 解锁
192
                $this->rm($name . '_lock');
193
            } catch (\Exception $e) {
194
                $this->rm($name . '_lock');
195
                throw $e;
196
            } catch (\throwable $e) {
197
                $this->rm($name . '_lock');
198
                throw $e;
199
            }
200
        } else {
201
            $value = $this->get($name);
202
        }
203
204
        return $value;
205
    }
206
207
    /**
208
     * 缓存标签
209
     * @access public
210
     * @param  string        $name 标签名
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
211
     * @param  string|array  $keys 缓存标识
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
212
     * @param  bool          $overlay 是否覆盖
213
     * @return $this
214
     */
215
    public function tag($name, $keys = null, $overlay = false)
216
    {
217
        if (is_null($name)) {
0 ignored issues
show
introduced by
The condition is_null($name) is always false.
Loading history...
218
219
        } elseif (is_null($keys)) {
220
            $this->tag = $name;
221
        } else {
222
            $key = $this->getTagkey($name);
223
224
            if (is_string($keys)) {
225
                $keys = explode(',', $keys);
226
            }
227
228
            $keys = array_map([$this, 'getCacheKey'], $keys);
229
230
            if ($overlay) {
231
                $value = $keys;
232
            } else {
233
                $value = array_unique(array_merge($this->getTagItem($name), $keys));
234
            }
235
236
            $this->set($key, implode(',', $value), 0);
237
        }
238
239
        return $this;
240
    }
241
242
    /**
243
     * 更新标签
244
     * @access protected
245
     * @param  string $name 缓存标识
246
     * @return void
247
     */
248
    protected function setTagItem($name)
249
    {
250
        if ($this->tag) {
251
            $key       = $this->getTagkey($this->tag);
252
            $prev      = $this->tag;
253
            $this->tag = null;
254
255
            if ($this->has($key)) {
256
                $value   = explode(',', $this->get($key));
257
                $value[] = $name;
258
259
                if (count($value) > 1000) {
260
                    array_shift($value);
261
                }
262
263
                $value = implode(',', array_unique($value));
264
            } else {
265
                $value = $name;
266
            }
267
268
            $this->set($key, $value, 0);
269
            $this->tag = $prev;
270
        }
271
    }
272
273
    /**
274
     * 获取标签包含的缓存标识
275
     * @access protected
276
     * @param  string $tag 缓存标签
277
     * @return array
278
     */
279
    protected function getTagItem($tag)
280
    {
281
        $key   = $this->getTagkey($tag);
282
        $value = $this->get($key);
283
284
        if ($value) {
285
            return array_filter(explode(',', $value));
286
        } else {
287
            return [];
288
        }
289
    }
290
291
    protected function getTagKey($tag)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
292
    {
293
        return 'tag_' . md5($tag);
294
    }
295
296
    /**
297
     * 序列化数据
298
     * @access protected
299
     * @param  mixed $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
300
     * @return string
301
     */
302
    protected function serialize($data)
303
    {
304
        if (is_scalar($data) || !$this->options['serialize']) {
305
            return $data;
306
        }
307
308
        $serialize = self::$serialize[0];
309
310
        return self::$serialize[2] . $serialize($data);
311
    }
312
313
    /**
314
     * 反序列化数据
315
     * @access protected
316
     * @param  string $data
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
317
     * @return mixed
318
     */
319
    protected function unserialize($data)
320
    {
321
        if ($this->options['serialize'] && 0 === strpos($data, self::$serialize[2])) {
322
            $unserialize = self::$serialize[1];
323
324
            return $unserialize(substr($data, self::$serialize[3]));
325
        } else {
326
            return $data;
327
        }
328
    }
329
330
    /**
331
     * 注册序列化机制
332
     * @access public
333
     * @param  callable $serialize      序列化方法
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 6 found
Loading history...
334
     * @param  callable $unserialize    反序列化方法
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
335
     * @param  string   $prefix         序列化前缀标识
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter name; 9 found
Loading history...
336
     * @return $this
337
     */
338
    public static function registerSerialize($serialize, $unserialize, $prefix = 'think_serialize:')
339
    {
340
        self::$serialize = [$serialize, $unserialize, $prefix, strlen($prefix)];
341
    }
342
343
    /**
344
     * 返回句柄对象,可执行其它高级方法
345
     *
346
     * @access public
347
     * @return object
348
     */
349
    public function handler()
350
    {
351
        return $this->handler;
352
    }
353
354
    public function getReadTimes()
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
355
    {
356
        return $this->readTimes;
357
    }
358
359
    public function getWriteTimes()
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
360
    {
361
        return $this->writeTimes;
362
    }
363
364
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
365
    {
366
        return call_user_func_array([$this->handler, $method], $args);
367
    }
368
}
369