Completed
Pull Request — 6.0 (#2115)
by nhzex
06:13
created

Driver::setMultiple()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 10
1
<?php
2
// +----------------------------------------------------------------------
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 Closure;
16
use DateInterval;
17
use DateTime;
18
use DateTimeInterface;
19
use Exception;
20
use Psr\SimpleCache\CacheInterface;
21
use think\contract\CacheHandlerInterface;
22
use think\exception\InvalidArgumentException;
23
use throwable;
24
25
/**
26
 * 缓存基础类
27
 */
28
abstract class Driver implements CacheInterface, CacheHandlerInterface
29
{
30
    /**
31
     * 驱动句柄
32
     * @var object
33
     */
34
    protected $handler = null;
35
36
    /**
37
     * 缓存读取次数
38
     * @var integer
39
     */
40
    protected $readTimes = 0;
41
42
    /**
43
     * 缓存写入次数
44
     * @var integer
45
     */
46
    protected $writeTimes = 0;
47
48
    /**
49
     * 缓存参数
50
     * @var array
51
     */
52
    protected $options = [];
53
54
    /**
55
     * 缓存标签
56
     * @var array
57
     */
58
    protected $tag = [];
59
60
    /**
61
     * 获取有效期
62
     * @access protected
63
     * @param integer|DateTimeInterface|DateInterval $expire 有效期
64
     * @return int
65
     */
66 1
    protected function getExpireTime($expire): int
67
    {
68 1
        if ($expire instanceof DateTimeInterface) {
69
            $expire = $expire->getTimestamp() - time();
70 1
        } elseif ($expire instanceof DateInterval) {
71
            $expire = DateTime::createFromFormat('U', (string) time())
72
                ->add($expire)
73
                ->format('U') - time();
74
        }
75
76 1
        return (int) $expire;
77
    }
78
79
    /**
80
     * 获取实际的缓存标识
81
     * @access public
82
     * @param string $name 缓存名
83
     * @return string
84
     */
85
    public function getCacheKey(string $name): string
86
    {
87
        return $this->options['prefix'] . $name;
88
    }
89
90
    /**
91
     * 读取缓存并删除
92
     * @access public
93
     * @param string $name 缓存变量名
94
     * @return mixed
95
     */
96
    public function pull(string $name)
97
    {
98
        $result = $this->get($name, false);
99
100
        if ($result) {
101
            $this->delete($name);
102
            return $result;
103
        }
104
    }
105
106
    /**
107
     * 追加(数组)缓存
108
     * @access public
109
     * @param string $name  缓存变量名
110
     * @param mixed  $value 存储数据
111
     * @return void
112
     */
113 1
    public function push(string $name, $value): void
114
    {
115 1
        $item = $this->get($name, []);
116
117 1
        if (!is_array($item)) {
118
            throw new InvalidArgumentException('only array cache can be push');
119
        }
120
121 1
        $item[] = $value;
122
123 1
        if (count($item) > 1000) {
124
            array_shift($item);
125
        }
126
127 1
        $item = array_unique($item);
128
129 1
        $this->set($name, $item);
130 1
    }
131
132
    /**
133
     * 如果不存在则写入缓存
134
     * @access public
135
     * @param string $name   缓存变量名
136
     * @param mixed  $value  存储数据
137
     * @param int    $expire 有效时间 0为永久
138
     * @return mixed
139
     */
140
    public function remember(string $name, $value, $expire = null)
141
    {
142
        if ($this->has($name)) {
143
            return $this->get($name);
144
        }
145
146
        $time = time();
147
148
        while ($time + 5 > time() && $this->has($name . '_lock')) {
149
            // 存在锁定则等待
150
            usleep(200000);
151
        }
152
153
        try {
154
            // 锁定
155
            $this->set($name . '_lock', true);
156
157
            if ($value instanceof Closure) {
158
                // 获取缓存数据
159
                $value = $value();
160
            }
161
162
            // 缓存数据
163
            $this->set($name, $value, $expire);
164
165
            // 解锁
166
            $this->delete($name . '_lock');
167
        } catch (Exception | throwable $e) {
168
            $this->delete($name . '_lock');
169
            throw $e;
170
        }
171
172
        return $value;
173
    }
174
175
    /**
176
     * 缓存标签
177
     * @access public
178
     * @param string|array $name 标签名
179
     * @return TagSet
180
     */
181 1
    public function tag($name): TagSet
182
    {
183 1
        $name = (array) $name;
184 1
        $key  = implode('-', $name);
185
186 1
        if (!isset($this->tag[$key])) {
187
            $name = array_map(function ($val) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
188 1
                return $this->getTagKey($val);
189 1
            }, $name);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
190 1
            $this->tag[$key] = new TagSet($name, $this);
191
        }
192
193 1
        return $this->tag[$key];
194
    }
195
196
    /**
197
     * 获取标签包含的缓存标识
198
     * @access public
199
     * @param string $tag 标签标识
200
     * @return array
201
     */
202 1
    public function getTagItems(string $tag): array
203
    {
204 1
        return $this->get($tag, []);
205
    }
206
207
    /**
208
     * 获取实际标签名
209
     * @access public
210
     * @param string $tag 标签名
211
     * @return string
212
     */
213 1
    public function getTagKey(string $tag): string
214
    {
215 1
        return $this->options['tag_prefix'] . md5($tag);
216
    }
217
218
    /**
219
     * 序列化数据
220
     * @access protected
221
     * @param mixed $data 缓存数据
222
     * @return string
223
     */
224 1
    protected function serialize($data): string
225
    {
226 1
        if (is_numeric($data)) {
227 1
            return (string) $data;
228
        }
229
230 1
        $serialize = $this->options['serialize'][0] ?? "serialize";
231
232 1
        return $serialize($data);
233
    }
234
235
    /**
236
     * 反序列化数据
237
     * @access protected
238
     * @param string $data 缓存数据
239
     * @return mixed
240
     */
241 1
    protected function unserialize(string $data)
242
    {
243 1
        if (is_numeric($data)) {
244 1
            return $data;
245
        }
246
247 1
        $unserialize = $this->options['serialize'][1] ?? "unserialize";
248
249 1
        return $unserialize($data);
250
    }
251
252
    /**
253
     * 返回句柄对象,可执行其它高级方法
254
     *
255
     * @access public
256
     * @return object
257
     */
258
    public function handler()
259
    {
260
        return $this->handler;
261
    }
262
263
    /**
264
     * 返回缓存读取次数
265
     * @access public
266
     * @return int
267
     */
268
    public function getReadTimes(): int
269
    {
270
        return $this->readTimes;
271
    }
272
273
    /**
274
     * 返回缓存写入次数
275
     * @access public
276
     * @return int
277
     */
278
    public function getWriteTimes(): int
279
    {
280
        return $this->writeTimes;
281
    }
282
283
    /**
284
     * 读取缓存
285
     * @access public
286
     * @param iterable $keys    缓存变量名
287
     * @param mixed    $default 默认值
288
     * @return iterable
289
     * @throws InvalidArgumentException
290
     */
291 1
    public function getMultiple($keys, $default = null): iterable
292
    {
293 1
        $result = [];
294
295 1
        foreach ($keys as $key) {
296 1
            $result[$key] = $this->get($key, $default);
297
        }
298
299 1
        return $result;
300
    }
301
302
    /**
303
     * 写入缓存
304
     * @access public
305
     * @param iterable               $values 缓存数据
306
     * @param null|int|\DateInterval $ttl    有效时间 0为永久
307
     * @return bool
308
     */
309 1
    public function setMultiple($values, $ttl = null): bool
310
    {
311 1
        foreach ($values as $key => $val) {
312 1
            $result = $this->set($key, $val, $ttl);
313
314 1
            if (false === $result) {
315
                return false;
316
            }
317
        }
318
319 1
        return true;
320
    }
321
322
    /**
323
     * 删除缓存
324
     * @access public
325
     * @param iterable $keys 缓存变量名
326
     * @return bool
327
     * @throws InvalidArgumentException
328
     */
329 1
    public function deleteMultiple($keys): bool
330
    {
331 1
        foreach ($keys as $key) {
332 1
            $result = $this->delete($key);
333
334 1
            if (false === $result) {
335
                return false;
336
            }
337
        }
338
339 1
        return true;
340
    }
341
342
    public function __call($method, $args)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __call()
Loading history...
343
    {
344
        return call_user_func_array([$this->handler, $method], $args);
345
    }
346
}
347