Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.75% |
30 / 32 |
|
77.78% |
7 / 9 |
CRAP | |
0.00% |
0 / 1 |
MemcachedDriver | |
93.75% |
30 / 32 |
|
77.78% |
7 / 9 |
23.13 | |
0.00% |
0 / 1 |
__construct | n/a |
0 / 0 |
n/a |
0 / 0 |
4 | |||||
__destruct | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
exists | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
get | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMultiple | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
set | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
setMultiple | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
delete | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
deleteMultiple | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
flush | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
expiresAt | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 |
1 | <?php declare(strict_types=1); |
2 | /** |
3 | * Banker |
4 | * |
5 | * A Caching library implementing psr/cache (PSR 6) and psr/simple-cache (PSR 16) |
6 | * |
7 | * PHP version 8+ |
8 | * |
9 | * @package Banker |
10 | * @author Timothy J. Warren <tim@timshomepage.net> |
11 | * @copyright 2016 - 2023 Timothy J. Warren |
12 | * @license http://www.opensource.org/licenses/mit-license.html MIT License |
13 | * @version 4.1.0 |
14 | * @link https://git.timshomepage.net/timw4mail/banker |
15 | */ |
16 | namespace Aviat\Banker\Driver; |
17 | |
18 | use Aviat\Banker\Exception\CacheException; |
19 | |
20 | use Aviat\Banker\Exception\InvalidArgumentException; |
21 | use DateInterval; |
22 | use Memcached; |
23 | use MemcachedException; |
24 | |
25 | /** |
26 | * Memcached cache backend |
27 | */ |
28 | class MemcachedDriver extends AbstractDriver { |
29 | |
30 | /** |
31 | * The Memcached connection |
32 | */ |
33 | private Memcached $conn; |
34 | |
35 | /** |
36 | * Driver for PHP Memcache extension |
37 | * |
38 | * @codeCoverageIgnore |
39 | * @param array $config |
40 | * @param array $options |
41 | * @throws CacheException |
42 | */ |
43 | public function __construct( |
44 | array $config = ['host' => '127.0.0.1', 'port' => '11211'], |
45 | array $options = [] |
46 | ) |
47 | { |
48 | if ( ! class_exists('Memcached')) |
49 | { |
50 | throw new CacheException('Memcached driver requires memcached extension'); |
51 | } |
52 | |
53 | try |
54 | { |
55 | $this->conn = new Memcached(); |
56 | $this->conn->setOption(Memcached::OPT_BINARY_PROTOCOL, true); |
57 | $this->conn->addServer($config['host'], (int) $config['port']); |
58 | |
59 | if ( ! empty($options)) |
60 | { |
61 | $this->conn->setOptions($options); |
62 | } |
63 | } |
64 | catch (MemcachedException $e) |
65 | { |
66 | // Rewrite MemcachedException as a CacheException to |
67 | // match the requirements of the interface |
68 | throw new CacheException($e->getMessage(), $e->getCode(), $e); |
69 | } |
70 | } |
71 | |
72 | /** |
73 | * Disconnect from memcached server |
74 | * @codeCoverageIgnore |
75 | */ |
76 | public function __destruct() |
77 | { |
78 | $this->conn->quit(); |
79 | } |
80 | |
81 | /** |
82 | * See if a key currently exists in the cache |
83 | * |
84 | * @param string $key |
85 | * @return bool |
86 | */ |
87 | public function exists(string $key): bool |
88 | { |
89 | $this->conn->get($key); |
90 | $resultFlag = $this->conn->getResultCode(); |
91 | |
92 | return ($resultFlag !== Memcached::RES_NOTFOUND); |
93 | } |
94 | |
95 | /** |
96 | * Get the value for the selected cache key |
97 | * |
98 | * @param string $key |
99 | * @return mixed |
100 | */ |
101 | public function get(string $key): mixed |
102 | { |
103 | return $this->conn->get($key); |
104 | } |
105 | |
106 | /** |
107 | * Retrieve a set of values by their cache key |
108 | * |
109 | * @param string[] $keys |
110 | * @return array |
111 | */ |
112 | public function getMultiple(array $keys = []): array |
113 | { |
114 | $this->validateKeys($keys); |
115 | |
116 | $response = $this->conn->getMulti($keys); |
117 | return (is_array($response)) ? $response : []; |
118 | } |
119 | |
120 | /** |
121 | * Set a cached value |
122 | * |
123 | * @param string $key |
124 | * @param mixed $value |
125 | * @param int|DateInterval|null $expires |
126 | * @return bool |
127 | * @throws InvalidArgumentException |
128 | */ |
129 | public function set(string $key, mixed $value, int|DateInterval|null $expires = NULL): bool |
130 | { |
131 | $this->validateKey($key); |
132 | |
133 | if ($expires instanceof DateInterval) |
134 | { |
135 | $expires = time() + $expires->s; |
136 | } |
137 | |
138 | return ($expires === NULL) |
139 | ? $this->conn->set($key, $value) |
140 | : $this->conn->set($key, $value, $expires); |
141 | } |
142 | |
143 | /** |
144 | * Set multiple cache values |
145 | * |
146 | * @param array $items |
147 | * @param DateInterval|int|null $expires |
148 | * @return bool |
149 | */ |
150 | public function setMultiple(array $items, DateInterval|int|null $expires = NULL): bool |
151 | { |
152 | $this->validateKeys($items, TRUE); |
153 | |
154 | if ($expires instanceof DateInterval) |
155 | { |
156 | $expires = $expires->s; |
157 | } |
158 | |
159 | return ($expires === NULL) |
160 | ? $this->conn->setMulti($items) |
161 | : $this->conn->setMulti($items, $expires); |
162 | } |
163 | |
164 | /** |
165 | * Remove an item from the cache |
166 | * |
167 | * @param string $key |
168 | * @return boolean |
169 | */ |
170 | public function delete(string $key): bool |
171 | { |
172 | return $this->conn->delete($key); |
173 | } |
174 | |
175 | /** |
176 | * Remove multiple items from the cache |
177 | * |
178 | * @param string[] $keys |
179 | * @return boolean |
180 | */ |
181 | public function deleteMultiple(array $keys = []): bool |
182 | { |
183 | $this->validateKeys($keys); |
184 | |
185 | $deleted = $this->conn->deleteMulti($keys); |
186 | |
187 | if (is_array($deleted)) |
188 | { |
189 | foreach ($deleted as $key => $status) |
190 | { |
191 | if ($status !== TRUE) |
192 | { |
193 | return FALSE; |
194 | } |
195 | } |
196 | |
197 | return TRUE; |
198 | } |
199 | } |
200 | |
201 | /** |
202 | * Empty the cache |
203 | * |
204 | * @return boolean |
205 | */ |
206 | public function flush(): bool |
207 | { |
208 | return $this->conn->flush(); |
209 | } |
210 | |
211 | /** |
212 | * Set the specified key to expire at the given time |
213 | * |
214 | * @param string $key |
215 | * @param int $expires |
216 | * @return boolean |
217 | */ |
218 | public function expiresAt(string $key, int $expires): bool |
219 | { |
220 | if ($this->exists($key)) |
221 | { |
222 | return $this->conn->touch($key, $expires); |
223 | } |
224 | |
225 | $this->getLogger()->log('warning','Tried to set expiration on a key that does not exist'); |
226 | |
227 | return FALSE; |
228 | } |
229 | } |