This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Dazzle\Cache\Redis; |
||
4 | |||
5 | use Dazzle\Cache\CacheInterface; |
||
6 | use Dazzle\Event\BaseEventEmitter; |
||
7 | use Dazzle\Loop\LoopAwareTrait; |
||
8 | use Dazzle\Loop\LoopInterface; |
||
9 | use Dazzle\Promise\Promise; |
||
10 | use Dazzle\Promise\PromiseInterface; |
||
11 | use Dazzle\Redis\Redis; |
||
12 | use Dazzle\Redis\RedisInterface; |
||
13 | use Dazzle\Throwable\Exception\Runtime\ReadException; |
||
14 | use Dazzle\Throwable\Exception\Runtime\WriteException; |
||
15 | use Error; |
||
16 | use Exception; |
||
17 | |||
18 | class RedisCache extends BaseEventEmitter implements CacheInterface |
||
19 | { |
||
20 | use LoopAwareTrait; |
||
21 | |||
22 | /** |
||
23 | * @var mixed[] |
||
24 | */ |
||
25 | protected $config; |
||
26 | |||
27 | /** |
||
28 | * @var RedisInterface |
||
29 | */ |
||
30 | protected $redis; |
||
31 | |||
32 | /** |
||
33 | * @var int |
||
34 | */ |
||
35 | protected $selected; |
||
36 | |||
37 | /** |
||
38 | * @param LoopInterface $loop |
||
39 | * @param mixed[] $config |
||
40 | */ |
||
41 | 16 | public function __construct(LoopInterface $loop, $config = []) |
|
42 | { |
||
43 | 16 | $this->loop = $loop; |
|
44 | 16 | $this->config = $this->createConfig($config); |
|
45 | 16 | $this->redis = $this->createRedis(); |
|
46 | 16 | $this->selected = 0; |
|
47 | |||
48 | 16 | $this->attachEvents(); |
|
49 | 16 | } |
|
50 | |||
51 | /** |
||
52 | * |
||
53 | */ |
||
54 | public function __destruct() |
||
55 | { |
||
56 | $this->stop(); |
||
57 | parent::__destruct(); |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * @override |
||
62 | * @inheritDoc |
||
63 | */ |
||
64 | 25 | public function isStarted() |
|
65 | { |
||
66 | 25 | return $this->redis->isStarted(); |
|
67 | } |
||
68 | |||
69 | /** |
||
70 | * @override |
||
71 | * @inheritDoc |
||
72 | */ |
||
73 | public function start() |
||
74 | { |
||
75 | return $this->redis->start()->then(function() { return $this; }); |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * @override |
||
80 | * @inheritDoc |
||
81 | */ |
||
82 | public function stop() |
||
83 | { |
||
84 | return $this->redis->stop()->then(function() { return $this; }); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * @override |
||
89 | * @inheritDoc |
||
90 | */ |
||
91 | public function end() |
||
92 | { |
||
93 | return $this->redis->end()->then(function() { return $this; }); |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * @override |
||
98 | * @inheritDoc |
||
99 | */ |
||
100 | public function isPaused() |
||
101 | { |
||
102 | return $this->redis->isPaused(); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * @override |
||
107 | * @inheritDoc |
||
108 | */ |
||
109 | public function pause() |
||
110 | { |
||
111 | return $this->redis->pause(); |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * @override |
||
116 | * @inheritDoc |
||
117 | */ |
||
118 | public function resume() |
||
119 | { |
||
120 | return $this->redis->resume(); |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @override |
||
125 | * @inheritDoc |
||
126 | */ |
||
127 | 15 | public function set($key, $val, $ttl = 0.0) |
|
128 | { |
||
129 | 15 | if (!$this->isStarted()) |
|
130 | { |
||
131 | 1 | return Promise::doReject(new WriteException('Cache object is not open.')); |
|
132 | } |
||
133 | 14 | if (is_object($val)) |
|
134 | { |
||
135 | 1 | return Promise::doReject(new WriteException('Objects are not supported.')); |
|
136 | } |
||
137 | |||
138 | 13 | $promise = $ttl > 0 |
|
139 | 2 | ? $this->redis->setEx($key, round($ttl), json_encode($val)) |
|
140 | 13 | : $this->redis->set($key, json_encode($val)); |
|
141 | |||
142 | return $promise->then(function($result) use($val) { |
||
143 | 13 | if ($result !== 'OK') |
|
144 | { |
||
145 | throw new WriteException('Value could not be set.'); |
||
146 | } |
||
147 | 13 | return $val; |
|
148 | 13 | }); |
|
149 | } |
||
150 | |||
151 | /** |
||
152 | * @override |
||
153 | * @inheritDoc |
||
154 | */ |
||
155 | 6 | View Code Duplication | public function get($key) |
0 ignored issues
–
show
|
|||
156 | { |
||
157 | 6 | if (!$this->isStarted()) |
|
158 | { |
||
159 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
160 | } |
||
161 | return $this->redis->get($key)->then(function($result) { |
||
162 | 5 | return $result === null ? null : json_decode($result, true); |
|
163 | 5 | }); |
|
164 | } |
||
165 | |||
166 | /** |
||
167 | * @override |
||
168 | * @inheritDoc |
||
169 | */ |
||
170 | 2 | View Code Duplication | public function remove($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
171 | { |
||
172 | 2 | if (!$this->isStarted()) |
|
173 | { |
||
174 | 1 | return Promise::doReject(new WriteException('Cache object is not open.')); |
|
175 | } |
||
176 | return $this->redis->del($key)->then(function($count) { |
||
177 | 1 | return $count ? true : false; |
|
178 | 1 | }); |
|
179 | } |
||
180 | |||
181 | /** |
||
182 | * @override |
||
183 | * @inheritDoc |
||
184 | */ |
||
185 | 5 | View Code Duplication | public function exists($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
186 | { |
||
187 | 5 | if (!$this->isStarted()) |
|
188 | { |
||
189 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
190 | } |
||
191 | return $this->redis->exists($key)->then(function($count) { |
||
192 | 4 | return $count ? true : false; |
|
193 | 4 | }); |
|
194 | } |
||
195 | |||
196 | /** |
||
197 | * @override |
||
198 | * @inheritDoc |
||
199 | */ |
||
200 | 4 | public function setTtl($key, $ttl) |
|
201 | { |
||
202 | 4 | if (!$this->isStarted()) |
|
203 | { |
||
204 | 1 | return Promise::doReject(new WriteException('Cache object is not open.')); |
|
205 | } |
||
206 | 3 | if ($ttl <= 0) |
|
207 | { |
||
208 | return Promise::doReject(new WriteException('TTL needs to be higher than 0.')); |
||
209 | } |
||
210 | return $this->redis->expire($key, round($ttl))->then(function($result) { |
||
211 | 3 | if ($result === 0) |
|
212 | { |
||
213 | throw new WriteException('Timeout cannot be set on undefined key.'); |
||
214 | } |
||
215 | 3 | return $result; |
|
216 | 3 | }); |
|
217 | } |
||
218 | |||
219 | /** |
||
220 | * @override |
||
221 | * @inheritDoc |
||
222 | */ |
||
223 | 2 | View Code Duplication | public function getTtl($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
224 | { |
||
225 | 2 | if (!$this->isStarted()) |
|
226 | { |
||
227 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
228 | } |
||
229 | return $this->redis->ttl($key)->then(function($result) { |
||
230 | 1 | return $result > 0 ? $result : 0; |
|
231 | 1 | }); |
|
232 | } |
||
233 | |||
234 | /** |
||
235 | * @override |
||
236 | * @inheritDoc |
||
237 | */ |
||
238 | 2 | View Code Duplication | public function removeTtl($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
239 | { |
||
240 | 2 | if (!$this->isStarted()) |
|
241 | { |
||
242 | 1 | return Promise::doReject(new WriteException('Cache object is not open.')); |
|
243 | } |
||
244 | return $this->redis->persist($key)->then(function($result) { |
||
245 | 1 | return $result > 0; |
|
246 | 1 | }); |
|
247 | } |
||
248 | |||
249 | /** |
||
250 | * @override |
||
251 | * @inheritDoc |
||
252 | */ |
||
253 | 2 | View Code Duplication | public function existsTtl($key) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
254 | { |
||
255 | 2 | if (!$this->isStarted()) |
|
256 | { |
||
257 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
258 | } |
||
259 | return $this->redis->ttl($key)->then(function($result) { |
||
260 | 1 | return $result >= 0; |
|
261 | 1 | }); |
|
262 | } |
||
263 | |||
264 | /** |
||
265 | * @override |
||
266 | * @inheritDoc |
||
267 | */ |
||
268 | 2 | View Code Duplication | public function getKeys() |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
269 | { |
||
270 | 2 | if (!$this->isStarted()) |
|
271 | { |
||
272 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
273 | } |
||
274 | return $this->redis->keys()->then(function($result) { |
||
275 | 1 | sort($result); |
|
276 | 1 | return $result; |
|
277 | 1 | }); |
|
278 | } |
||
279 | |||
280 | /** |
||
281 | * @override |
||
282 | * @inheritDoc |
||
283 | */ |
||
284 | 2 | public function getStats() |
|
285 | { |
||
286 | 2 | if (!$this->isStarted()) |
|
287 | { |
||
288 | 1 | return Promise::doReject(new ReadException('Cache object is not open.')); |
|
289 | } |
||
290 | return $this->redis->info()->then(function($result) { |
||
291 | 1 | preg_match('#keys=([0-9]+)#si', $result['keyspace']['db' . $this->selected], $matches); |
|
292 | 1 | $keys = isset($matches[1]) ? $matches[1] : 0; |
|
293 | return [ |
||
294 | 1 | 'keys' => (int) $keys, |
|
295 | 1 | 'hits' => (int) $result['stats']['keyspace_hits'], |
|
296 | 1 | 'misses' => (int) $result['stats']['keyspace_misses'], |
|
297 | ]; |
||
298 | 1 | }); |
|
299 | } |
||
300 | |||
301 | /** |
||
302 | * @override |
||
303 | * @inheritDoc |
||
304 | */ |
||
305 | 15 | public function flush() |
|
306 | { |
||
307 | 15 | if (!$this->isStarted()) |
|
308 | { |
||
309 | 1 | return Promise::doReject(new WriteException('Cache object is not open.')); |
|
310 | } |
||
311 | 14 | return $this->redis->flushDb(); |
|
312 | } |
||
313 | |||
314 | /** |
||
315 | * Create configuration. |
||
316 | * |
||
317 | * @return mixed[] |
||
318 | */ |
||
319 | 16 | protected function createConfig($config = []) |
|
320 | { |
||
321 | 16 | return array_merge([ 'endpoint' => 'redis://127.0.0.1:6379' ], $config); |
|
322 | } |
||
323 | |||
324 | /** |
||
325 | * Create Redis client. |
||
326 | * |
||
327 | * @return RedisInterface |
||
328 | */ |
||
329 | 16 | protected function createRedis() |
|
330 | { |
||
331 | 16 | return new Redis($this->createEndpoint($this->config['endpoint']), $this->getLoop()); |
|
332 | } |
||
333 | |||
334 | /** |
||
335 | * Parse and return endpoint. |
||
336 | * |
||
337 | * @param string $endpoint |
||
338 | * @return string |
||
339 | */ |
||
340 | 16 | protected function createEndpoint($endpoint) |
|
341 | { |
||
342 | 16 | $endpoint = explode('://', $endpoint, 2); |
|
343 | 16 | $endpoint = explode('/', $endpoint[1]); |
|
344 | 16 | $endpoint = stripos($endpoint[0], ':') === false ? $endpoint[0] . ':6379' : $endpoint[0]; |
|
345 | 16 | $endpoint = 'tcp://' . $endpoint; |
|
346 | 16 | return $endpoint; |
|
347 | } |
||
348 | |||
349 | /** |
||
350 | * Attach events. |
||
351 | */ |
||
352 | 16 | private function attachEvents() |
|
353 | { |
||
354 | $this->redis->on('start', function($redis) { |
||
0 ignored issues
–
show
|
|||
355 | 16 | $this->emit('start', [ $this ]); |
|
356 | 16 | }); |
|
357 | $this->redis->on('stop', function($redis) { |
||
0 ignored issues
–
show
|
|||
358 | 16 | $this->emit('stop', [ $this ]); |
|
359 | 16 | }); |
|
360 | 16 | $this->redis->on('error', function($redis, $ex) { |
|
361 | $this->emit('error', [ $this, $ex ]); |
||
362 | 16 | }); |
|
363 | 16 | } |
|
364 | } |
||
365 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.