SimpleCacheAdapter::clear()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://github.com/flipbox/craft-psr16/blob/master/LICENSE
6
 * @link       https://github.com/flipbox/craft-psr16
7
 */
8
9
namespace flipbox\craft\psr16;
10
11
use Craft;
12
use DateInterval;
13
use DateTime;
14
use Psr\SimpleCache\CacheInterface;
15
use yii\base\Component;
16
use yii\base\InvalidArgumentException;
17
use yii\caching\CacheInterface as YiiCacheInterface;
18
use yii\di\Instance;
19
use yii\helpers\StringHelper;
20
21
/**
22
 * @author Flipbox Factory <[email protected]>
23
 * @since 1.0.0
24
 */
25
class SimpleCacheAdapter extends Component implements CacheInterface
26
{
27
    /**
28
     * @var YiiCacheInterface
29
     */
30
    public $cache;
31
32
    /**
33
     * @throws \yii\base\InvalidConfigException
34
     */
35
    public function init()
36
    {
37
        parent::init();
38
39
        if ($this->cache === null) {
40
            $this->cache = Craft::$app->getCache();
41
        }
42
43
        $this->cache = Instance::ensure(
44
            $this->cache instanceof \Closure ?
45
            call_user_func($this->cache) :
46
            $this->cache,
47
            YiiCacheInterface::class
48
        );
49
    }
50
51
    /**
52
     * @return YiiCacheInterface
53
     */
54
    protected function getCache(): YiiCacheInterface
55
    {
56
        return $this->cache;
57
    }
58
59
    /**
60
     * Cache::get() return false if the value is not in the cache or expired, but PSR-16 return $default(null)
61
     *
62
     * @param string $key
63
     * @param null $default
64
     * @return bool|mixed|null
65
     * @throws InvalidArgumentException
66
     */
67
    public function get($key, $default = null)
68
    {
69
        $key = $this->buildKey($key);
70
71
        $data = $this->getCache()->get($key);
72
73
        if ($data === false) {
74
            return $default;
75
        }
76
77
        if ($data === null) {
78
            return false;
79
        }
80
81
        return $data;
82
    }
83
84
    /**
85
     * @param string $key
86
     * @param mixed $value
87
     * @param null $ttl
88
     * @param null $dependency
89
     * @return bool
90
     * @throws InvalidArgumentException
91
     */
92
    public function set($key, $value, $ttl = null, $dependency = null)
93
    {
94
        $key = $this->buildKey($key);
95
96
        $duration = $this->dateIntervalToSeconds($ttl);
97
98
        return $this->getCache()->set($key, $value, $duration, $dependency);
99
    }
100
101
    /**
102
     * @param string $key
103
     * @return bool
104
     */
105
    public function delete($key)
106
    {
107
        $key = $this->buildKey($key);
108
        return $this->has($key) ? $this->getCache()->delete($key) : true;
109
    }
110
111
    /**
112
     * @return bool
113
     */
114
    public function clear()
115
    {
116
        return $this->getCache()->flush();
117
    }
118
119
    /**
120
     * @param iterable $keys
121
     * @param null $default
122
     * @return array|iterable
123
     */
124
    public function getMultiple($keys, $default = null)
125
    {
126
        if (!$keys instanceof \Traversable && !is_array($keys)) {
127
            throw new InvalidArgumentException(
128
                'Invalid keys: ' . var_export($keys, true) . '. Keys should be an array or Traversable of strings.'
129
            );
130
        }
131
        $data = [];
132
        foreach ($keys as $key) {
133
            $data[$key] = $this->get($key, $default);
134
        }
135
        return $data;
136
    }
137
138
    /**
139
     * @param iterable $values
140
     * @param null $ttl
141
     * @return bool
142
     */
143
    public function setMultiple($values, $ttl = null)
144
    {
145
        if (!$values instanceof \Traversable && !is_array($values)) {
146
            throw new InvalidArgumentException(
147
                'Invalid keys: ' . var_export($values, true) . '. Keys should be an array or Traversable of strings.'
148
            );
149
        }
150
        $pairs = [];
151
        foreach ($values as $key => $value) {
152
            $key = $this->buildKey($key);
153
            $pairs[$key] = $value;
154
        }
155
        $res = true;
156
        foreach ($pairs as $key => $value) {
157
            $res = $res && $this->set($key, $value, $ttl);
158
        }
159
        return $res;
160
    }
161
162
    /**
163
     * @param iterable $keys
164
     * @return bool
165
     */
166
    public function deleteMultiple($keys)
167
    {
168
        if ($keys instanceof \Traversable) {
169
            $keys = iterator_to_array($keys, false);
170
        } else {
171
            if (!is_array($keys)) {
172
                throw new InvalidArgumentException(
173
                    'Invalid keys: ' . var_export($keys, true) . '. Keys should be an array or Traversable of strings.'
174
                );
175
            }
176
        }
177
        $res = true;
178
        array_map(function ($key) use (&$res) {
179
            $res = $res && $this->delete($key);
180
        }, $keys);
181
        return $res;
182
    }
183
184
    /**
185
     * @param string $key
186
     * @return bool
187
     */
188
    public function has($key)
189
    {
190
        $key = $this->buildKey($key);
191
        return $this->getCache()->exists($key);
192
    }
193
194
    /**
195
     * @param $ttl
196
     * @return null|int
197
     */
198
    protected function dateIntervalToSeconds($ttl)
199
    {
200
        if ($ttl === null || !is_int($ttl)) {
201
            return $ttl;
202
        }
203
204
        if ($ttl instanceof DateInterval) {
205
            return ((new DateTime())->add($ttl))->getTimestamp() - (new DateTime())->getTimestamp();
206
        }
207
208
        return null;
209
    }
210
211
212
    /**
213
     * Builds a normalized cache key from a given key.
214
     *
215
     * If the given key is a string containing alphanumeric characters only and no more than 32 characters,
216
     * then the key will be returned back as it is. Otherwise, a normalized key is generated by serializing
217
     * the given key and applying MD5 hashing.
218
     *
219
     * @param mixed $key the key to be normalized
220
     * @return string the generated cache key
221
     */
222
    protected function buildKey($key)
223
    {
224
        if (is_string($key)) {
225
            return ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key);
226
        }
227
        return md5(json_encode($key));
228
    }
229
}
230