Completed
Pull Request — master (#5)
by Michal
02:12
created

RedisProxy::decrby()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
namespace RedisProxy;
4
5
use Exception;
6
use Predis\Client;
7
use Predis\Response\Status;
8
use Redis;
9
10
/**
11
 * @method mixed config(string $command, $argument = null)
12
 * @method int dbsize() Return the number of keys in the selected database
13
 * @method boolean set(string $key, string $value) Set the string value of a key
14
 * @method boolean setex(string $key, int $seconds, string $value) Set the value and expiration of a key
15
 * @method boolean psetex(string $key, int $miliseconds, string $value) Set the value and expiration in milliseconds of a key
16
 * @method int ttl(string $key) Get the time to live for a key, returns TTL in seconds, -2 if the key does not exist, -1 if the key exists but has no associated expire
17
 * @method int pttl(string $key) Get the time to live for a key in milliseconds, returns TTL in miliseconds, -2 if the key does not exist, -1 if the key exists but has no associated expire
18
 * @method array keys(string $pattern) Find all keys matching the given pattern
19
 * @method int hset(string $key, string $field, string $value) Set the string value of a hash field
20
 * @method array hkeys(string $key) Get all fields in a hash (without values)
21
 * @method array hgetall(string $key) Get all fields and values in a hash
22
 * @method int hlen(string $key) Get the number of fields in a hash
23
 * @method array smembers(string $key) Get all the members in a set
24
 * @method int scard(string $key) Get the number of members in a set
25
 * @method int llen(string $key) Get the length of a list
26
 * @method array lrange(string $key, int $start, int $stop) Get a range of elements from a list
27
 * @method int zcard(string $key) Get the number of members in a sorted set
28
 * @method boolean flushall() Remove all keys from all databases
29
 * @method boolean flushdb() Remove all keys from the current database
30
 */
31
class RedisProxy
32
{
33
    const DRIVER_REDIS = 'redis';
34
35
    const DRIVER_PREDIS = 'predis';
36
37
    const TYPE_STRING = 'string';
38
39
    const TYPE_SET = 'set';
40
41
    const TYPE_HASH = 'hash';
42
43
    const TYPE_LIST = 'list';
44
45
    const TYPE_SORTED_SET = 'sorted_set';
46
47
    private $driver;
48
49
    private $host;
50
51
    private $port;
52
53
    private $database = 0;
54
55
    private $selectedDatabase = 0;
56
57
    private $timeout;
58
59
    private $supportedDrivers = [
60
        self::DRIVER_REDIS,
61
        self::DRIVER_PREDIS,
62
    ];
63
64
    private $driversOrder = [];
65
66
    private $redisTypeMap = [
67
        Redis::REDIS_STRING => self::TYPE_STRING,
68
        Redis::REDIS_SET => self::TYPE_SET,
69
        Redis::REDIS_HASH => self::TYPE_HASH,
70
        Redis::REDIS_LIST => self::TYPE_LIST,
71
        Redis::REDIS_ZSET => self::TYPE_SORTED_SET,
72
    ];
73
74
    private $predisTypeMap = [
75
        'string' => self::TYPE_STRING,
76
        'set' => self::TYPE_SET,
77
        'hash' => self::TYPE_HASH,
78
        'list' => self::TYPE_LIST,
79
        'zset' => self::TYPE_SORTED_SET,
80
    ];
81
82 244
    public function __construct($host, $port, $database = 0, $timeout = null)
83
    {
84 244
        $this->host = $host;
85 244
        $this->port = $port;
86 244
        $this->database = $database;
87 244
        $this->timeout = $timeout;
88 244
        $this->driversOrder = $this->supportedDrivers;
89 244
    }
90
91
    /**
92
     * Set driver priorities - default is 1. redis, 2. predis
93
     * @param array $driversOrder
94
     * @return RedisProxy
95
     * @throws RedisProxyException if some driver is not supported
96
     */
97 244
    public function setDriversOrder(array $driversOrder)
98
    {
99 244
        foreach ($driversOrder as $driver) {
100 242
            if (!in_array($driver, $this->supportedDrivers)) {
101 122
                throw new RedisProxyException('Driver "' . $driver . '" is not supported');
102
            }
103 121
        }
104 242
        $this->driversOrder = $driversOrder;
105 242
        return $this;
106
    }
107
108 242
    private function init()
109
    {
110 242
        $this->prepareDriver();
111 240
        $this->select($this->database);
112 240
    }
113
114 242
    private function prepareDriver()
115
    {
116 242
        if ($this->driver !== null) {
117 240
            return;
118
        }
119
120 242
        foreach ($this->driversOrder as $preferredDriver) {
121 240
            if ($preferredDriver === self::DRIVER_REDIS && extension_loaded('redis')) {
122 120
                $this->driver = new Redis();
123 120
                return;
124
            }
125 120
            if ($preferredDriver === self::DRIVER_PREDIS && class_exists('Predis\Client')) {
126 120
                $this->driver = new Client();
127 120
                return;
128
            }
129 1
        }
130 2
        throw new RedisProxyException('No driver available');
131
    }
132
133
    /**
134
     * @return string|null
135
     */
136 242
    public function actualDriver()
137
    {
138 242
        if ($this->driver instanceof Redis) {
139 120
            return self::DRIVER_REDIS;
140
        }
141 126
        if ($this->driver instanceof Client) {
142 120
            return self::DRIVER_PREDIS;
143
        }
144 10
        return null;
145
    }
146
147 240
    private function connect($host, $port, $timeout = null)
148
    {
149 240
        return $this->driver->connect($host, $port, $timeout);
150
    }
151
152 240
    private function isConnected()
153
    {
154 240
        return $this->driver->isConnected();
155
    }
156
157 242
    public function __call($name, $arguments)
158
    {
159 242
        $this->init();
160 240
        $name = strtolower($name);
161
        try {
162 240
            $result = call_user_func_array([$this->driver, $name], $arguments);
163 122
        } catch (Exception $e) {
164 4
            throw new RedisProxyException("Error for command '$name', use getPrevious() for more info", 1484162284, $e);
165
        }
166 240
        return $this->transformResult($result);
167
    }
168
169
    /**
170
     * @param int $database
171
     * @return boolean true on success
172
     * @throws RedisProxyException on failure
173
     */
174 240
    public function select($database)
175
    {
176 240
        $this->prepareDriver();
177 240
        if (!$this->isConnected()) {
178 240
            $this->connect($this->host, $this->port, $this->timeout);
179 120
        }
180 240
        if ($database == $this->selectedDatabase) {
181 240
            return true;
182
        }
183
        try {
184 12
            $result = $this->driver->select($database);
185 7
        } catch (Exception $e) {
186 2
            throw new RedisProxyException('Invalid DB index');
187
        }
188 10
        $result = $this->transformResult($result);
189 10
        if ($result === false) {
190 2
            throw new RedisProxyException('Invalid DB index');
191
        }
192 8
        $this->database = $database;
193 8
        $this->selectedDatabase = $database;
194 8
        return $result;
195
    }
196
197
    /**
198
     * @param string $key
199
     * @return string|null
200
     */
201 4
    public function type($key)
202
    {
203 4
        $this->init();
204 4
        $result = $this->driver->type($key);
205 4
        if ($this->actualDriver() === self::DRIVER_REDIS) {
206 2
            if (isset($this->redisTypeMap[$result])) {
207 2
                return $this->redisTypeMap[$result];
208
            }
209 3
        } elseif ($this->actualDriver() === self::DRIVER_PREDIS && $result instanceof Status) {
210 2
            $result = $result->getPayload();
211 2
            if (isset($this->predisTypeMap[$result])) {
212 2
                return $this->predisTypeMap[$result];
213
            }
214 1
        }
215 4
        return null;
216
    }
217
218
    /**
219
     * @param string|null $section
220
     * @return array
221
     */
222 8
    public function info($section = null)
223
    {
224 8
        $this->init();
225 8
        $section = $section ? strtolower($section) : $section;
226 8
        $result = $section === null ? $this->driver->info() : $this->driver->info($section);
227
228 8
        $databases = $section === null || $section === 'keyspace' ? $this->config('get', 'databases')['databases'] : null;
229 8
        $groupedResult = InfoHelper::createInfoArray($this, $result, $databases);
230 8
        if ($section === null) {
231 4
            return $groupedResult;
232
        }
233 8
        if (isset($groupedResult[$section])) {
234 4
            return $groupedResult[$section];
235
        }
236 4
        throw new RedisProxyException('Info section "' . $section . '" doesn\'t exist');
237
    }
238
239
    /**
240
     * Get the value of a key
241
     * @param string $key
242
     * @return string|null null if key not set
243
     */
244 72
    public function get($key)
245
    {
246 72
        $this->init();
247 72
        $result = $this->driver->get($key);
248 72
        return $this->convertFalseToNull($result);
249
    }
250
251
    /**
252
     * Set the string value of a key and return its old value
253
     * @param string $key
254
     * @param string $value
255
     * @return string|null null if key was not set before
256
     */
257 4
    public function getset($key, $value)
258
    {
259 4
        $this->init();
260 4
        $result = $this->driver->getset($key, $value);
261 4
        return $this->convertFalseToNull($result);
262
    }
263
264
    /**
265
     * Set a key's time to live in seconds
266
     * @param string $key
267
     * @param int $seconds
268
     * @return boolean true if the timeout was set, false if key does not exist or the timeout could not be set
269
     */
270 8
    public function expire($key, $seconds)
271
    {
272 8
        $this->init();
273 8
        $result = $this->driver->expire($key, $seconds);
274 8
        return (bool)$result;
275
    }
276
277
    /**
278
     * Set the expiration for a key as a UNIX timestamp
279
     * @param string $key
280
     * @param int $timestamp
281
     * @return boolean true if the timeout was set, false if key does not exist or the timeout could not be set
282
     */
283 4
    public function expireat($key, $timestamp)
284
    {
285 4
        $this->init();
286 4
        $result = $this->driver->expireat($key, $timestamp);
287 4
        return (bool)$result;
288
    }
289
290
    /**
291
     * Set the expiration for a key as a UNIX timestamp specified in milliseconds
292
     * @param string $key
293
     * @param int $timestamp
294
     * @return boolean true if the timeout was set, false if key does not exist or the timeout could not be set
295
     */
296 4
    public function pexpireat($key, $timestamp)
297
    {
298 4
        $this->init();
299 4
        $result = $this->driver->pexpireat($key, $timestamp);
300 4
        return (bool)$result;
301
    }
302
303
    /**
304
     * Set the value of a key, only if the key does not exist
305
     * @param string $key
306
     * @param string $value
307
     * @return boolean true if the key was set, false if the key was not set
308
     */
309 4
    public function setnx($key, $value)
310
    {
311 4
        $this->init();
312 4
        $result = $this->driver->setnx($key, $value);
313 4
        return (bool)$result;
314
    }
315
316
    /**
317
     * Delete a key(s)
318
     * @param array $keys
319
     * @return int number of deleted keys
320
     */
321 28
    public function del(...$keys)
322
    {
323 28
        $this->prepareArguments('del', ...$keys);
324 20
        $this->init();
325 20
        return $this->driver->del(...$keys);
326
    }
327
328
    /**
329
     * Delete a key(s)
330
     * @param array $keys
331
     * @return int number of deleted keys
332
     */
333 12
    public function delete(...$keys)
334
    {
335 12
        return $this->del(...$keys);
336
    }
337
338
    /**
339
     * Increment the integer value of a key by one
340
     * @param string $key
341
     * @return integer
342
     */
343 4
    public function incr($key)
344
    {
345 4
        $this->init();
346 4
        return $this->driver->incr($key);
347
    }
348
349
    /**
350
     * Increment the integer value of a key by the given amount
351
     * @param string $key
352
     * @param integer $increment
353
     * @return integer
354
     */
355 4
    public function incrby($key, $increment = 1)
356
    {
357 4
        $this->init();
358 4
        return $this->driver->incrby($key, (int)$increment);
359
    }
360
361
    /**
362
     * Increment the float value of a key by the given amount
363
     * @param string $key
364
     * @param float $increment
365
     * @return float
366
     */
367 8
    public function incrbyfloat($key, $increment = 1)
368
    {
369 8
        $this->init();
370 8
        return $this->driver->incrbyfloat($key, $increment);
371
    }
372
373
    /**
374
     * Decrement the integer value of a key by one
375
     * @param string $key
376
     * @return integer
377
     */
378 4
    public function decr($key)
379
    {
380 4
        $this->init();
381 4
        return $this->driver->decr($key);
382
    }
383
384
    /**
385
     * Decrement the integer value of a key by the given number
386
     * @param string $key
387
     * @param integer $decrement
388
     * @return integer
389
     */
390 4
    public function decrby($key, $decrement = 1)
391
    {
392 4
        $this->init();
393 4
        return $this->driver->decrby($key, (int)$decrement);
394
    }
395
396
    /**
397
     * Decrement the float value of a key by the given amount
398
     * @param string $key
399
     * @param float $decrement
400
     * @return float
401
     */
402 4
    public function decrbyfloat($key, $decrement = 1)
403
    {
404 4
        return $this->incrbyfloat($key, (-1) * $decrement);
405
    }
406
407
    /**
408
     * Set multiple values to multiple keys
409
     * @param array $dictionary
410
     * @return boolean true on success
411
     * @throws RedisProxyException if number of arguments is wrong
412
     */
413 12 View Code Duplication
    public function mset(...$dictionary)
414
    {
415 12
        $this->init();
416 12
        if (is_array($dictionary[0])) {
417 8
            $result = $this->driver->mset(...$dictionary);
418 8
            return $this->transformResult($result);
419
        }
420 8
        $dictionary = $this->prepareKeyValue($dictionary, 'mset');
421 4
        $result = $this->driver->mset($dictionary);
422 4
        return $this->transformResult($result);
423
    }
424
425
    /**
426
     * Multi get
427
     * @param array $keys
428
     * @return array Returns the values for all specified keys. For every key that does not hold a string value or does not exist, null is returned
429
     */
430 4
    public function mget(...$keys)
431
    {
432 4
        $keys = array_unique($this->prepareArguments('mget', ...$keys));
433 4
        $this->init();
434 4
        $values = [];
435 4
        foreach ($this->driver->mget($keys) as $value) {
436 4
            $values[] = $this->convertFalseToNull($value);
437 2
        }
438 4
        return array_combine($keys, $values);
439
    }
440
441
    /**
442
     * Incrementally iterate the keys space
443
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
444
     * @param string $pattern pattern for keys, use * as wild card
445
     * @param int $count
446
     * @return array|boolean|null list of found keys, returns null if $iterator is 0 or '0'
447
     */
448 4 View Code Duplication
    public function scan(&$iterator, $pattern = null, $count = null)
449
    {
450 4
        if ((string)$iterator === '0') {
451 4
            return null;
452
        }
453 4
        $this->init();
454 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
455 2
            $returned = $this->driver->scan($iterator, ['match' => $pattern, 'count' => $count]);
456 2
            $iterator = $returned[0];
457 2
            return $returned[1];
458
        }
459 2
        return $this->driver->scan($iterator, $pattern, $count);
460
    }
461
462
    /**
463
     * Get the value of a hash field
464
     * @param string $key
465
     * @param string $field
466
     * @return string|null null if hash field is not set
467
     */
468 16
    public function hget($key, $field)
469
    {
470 16
        $this->init();
471 16
        $result = $this->driver->hget($key, $field);
472 16
        return $this->convertFalseToNull($result);
473
    }
474
475
    /**
476
     * Delete one or more hash fields, returns number of deleted fields
477
     * @param array $key
478
     * @param array $fields
479
     * @return int
480
     */
481 8
    public function hdel($key, ...$fields)
482
    {
483 8
        $fields = $this->prepareArguments('hdel', ...$fields);
484 8
        $this->init();
485 8
        return $this->driver->hdel($key, ...$fields);
486
    }
487
488
    /**
489
     * Increment the integer value of hash field by given number
490
     * @param string $key
491
     * @param string $field
492
     * @param int $increment
493
     * @return int
494
     */
495 4
    public function hincrby($key, $field, $increment = 1)
496
    {
497 4
        $this->init();
498 4
        return $this->driver->hincrby($key, $field, (int)$increment);
499
    }
500
501
    /**
502
     * Increment the float value of hash field by given amount
503
     * @param string $key
504
     * @param string $field
505
     * @param float $increment
506
     * @return float
507
     */
508 4
    public function hincrbyfloat($key, $field, $increment = 1)
509
    {
510 4
        $this->init();
511 4
        return $this->driver->hincrbyfloat($key, $field, $increment);
512
    }
513
514
    /**
515
     * Set multiple values to multiple hash fields
516
     * @param string $key
517
     * @param array $dictionary
518
     * @return boolean true on success
519
     * @throws RedisProxyException if number of arguments is wrong
520
     */
521 12 View Code Duplication
    public function hmset($key, ...$dictionary)
522
    {
523 12
        $this->init();
524 12
        if (is_array($dictionary[0])) {
525 8
            $result = $this->driver->hmset($key, ...$dictionary);
526 8
            return $this->transformResult($result);
527
        }
528 8
        $dictionary = $this->prepareKeyValue($dictionary, 'hmset');
529 4
        $result = $this->driver->hmset($key, $dictionary);
530 4
        return $this->transformResult($result);
531
    }
532
533
    /**
534
     * Multi hash get
535
     * @param string $key
536
     * @param array $fields
537
     * @return array Returns the values for all specified fields. For every field that does not hold a string value or does not exist, null is returned
538
     */
539 4
    public function hmget($key, ...$fields)
540
    {
541 4
        $fields = array_unique($this->prepareArguments('hmget', ...$fields));
542 4
        $this->init();
543 4
        $values = [];
544 4
        foreach ($this->driver->hmget($key, $fields) as $value) {
545 4
            $values[] = $this->convertFalseToNull($value);
546 2
        }
547 4
        return array_combine($fields, $values);
548
    }
549
550
    /**
551
     * Incrementally iterate hash fields and associated values
552
     * @param string $key
553
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
554
     * @param string $pattern pattern for fields, use * as wild card
555
     * @param int $count
556
     * @return array|boolean|null list of found fields with associated values, returns null if $iterator is 0 or '0'
557
     */
558 4 View Code Duplication
    public function hscan($key, &$iterator, $pattern = null, $count = null)
559
    {
560 4
        if ((string)$iterator === '0') {
561 4
            return null;
562
        }
563 4
        $this->init();
564 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
565 2
            $returned = $this->driver->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
566 2
            $iterator = $returned[0];
567 2
            return $returned[1];
568
        }
569 2
        return $this->driver->hscan($key, $iterator, $pattern, $count);
570
    }
571
572
    /**
573
     * Add one or more members to a set
574
     * @param string $key
575
     * @param array $members
576
     * @return int number of new members added to set
577
     */
578 16
    public function sadd($key, ...$members)
579
    {
580 16
        $members = $this->prepareArguments('sadd', ...$members);
581 16
        $this->init();
582 16
        return $this->driver->sadd($key, ...$members);
583
    }
584
585
    /**
586
     * Remove and return one or multiple random members from a set
587
     * @param string $key
588
     * @param int $count number of members
589
     * @return mixed string if $count is null or 1 and $key exists, array if $count > 1 and $key exists, null if $key doesn't exist
590
     */
591 4
    public function spop($key, $count = 1)
592
    {
593 4
        $this->init();
594 4
        if ($count == 1 || $count === null) {
595 4
            $result = $this->driver->spop($key);
596 4
            return $this->convertFalseToNull($result);
597
        }
598
599 4
        $members = [];
600 4
        for ($i = 0; $i < $count; ++$i) {
601 4
            $member = $this->driver->spop($key);
602 4
            if (!$member) {
603 4
                break;
604
            }
605 4
            $members[] = $member;
606 2
        }
607 4
        return empty($members) ? null : $members;
608
    }
609
610
    /**
611
     * Incrementally iterate Set elements
612
     * @param string $key
613
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
614
     * @param string $pattern pattern for member's values, use * as wild card
615
     * @param int $count
616
     * @return array|boolean|null list of found members, returns null if $iterator is 0 or '0'
617
     */
618 4 View Code Duplication
    public function sscan($key, &$iterator, $pattern = null, $count = null)
619
    {
620 4
        if ((string)$iterator === '0') {
621 4
            return null;
622
        }
623 4
        $this->init();
624 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
625 2
            $returned = $this->driver->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
626 2
            $iterator = $returned[0];
627 2
            return $returned[1];
628
        }
629 2
        return $this->driver->sscan($key, $iterator, $pattern, $count);
630
    }
631
632
    /**
633
     * Prepend one or multiple values to a list
634
     * @param string $key
635
     * @param array $elements
636
     * @return int the length of the list after the push operations
637
     */
638 28
    public function lpush($key, ...$elements)
639
    {
640 28
        $elements = $this->prepareArguments('lpush', ...$elements);
641 28
        $this->init();
642 28
        return $this->driver->lpush($key, ...$elements);
643
    }
644
645
    /**
646
     * Append one or multiple values to a list
647
     * @param string $key
648
     * @param array $elements
649
     * @return int the length of the list after the push operations
650
     */
651 12
    public function rpush($key, ...$elements)
652
    {
653 12
        $elements = $this->prepareArguments('rpush', ...$elements);
654 12
        $this->init();
655 12
        return $this->driver->rpush($key, ...$elements);
656
    }
657
658
    /**
659
     * Remove and get the first element in a list
660
     * @param string $key
661
     * @return string|null
662
     */
663 4
    public function lpop($key)
664
    {
665 4
        $this->init();
666 4
        $result = $this->driver->lpop($key);
667 4
        return $this->convertFalseToNull($result);
668
    }
669
670
    /**
671
     * Remove and get the last element in a list
672
     * @param string $key
673
     * @return string|null
674
     */
675 4
    public function rpop($key)
676
    {
677 4
        $this->init();
678 4
        $result = $this->driver->rpop($key);
679 4
        return $this->convertFalseToNull($result);
680
    }
681
682
    /**
683
     * Get an element from a list by its index
684
     * @param string $key
685
     * @param int $index zero-based, so 0 means the first element, 1 the second element and so on. -1 means the last element, -2 means the penultimate and so forth
686
     * @return string|null
687
     */
688 12
    public function lindex($key, $index)
689
    {
690 12
        $this->init();
691 12
        $result = $this->driver->lindex($key, $index);
692 12
        return $this->convertFalseToNull($result);
693
    }
694
695
    /**
696
     * Add one or more members to a sorted set, or update its score if it already exists
697
     * @param string $key
698
     * @param array $dictionary (score1, member1[, score2, member2]) or associative array: [member1 => score1, member2 => score2]
699
     * @return int
700
     */
701 20
    public function zadd($key, ...$dictionary)
702
    {
703 20
        $this->init();
704 20
        if (is_array($dictionary[0])) {
705 12
            $return = 0;
706 12
            foreach ($dictionary[0] as $member => $score) {
707 12
                $res = $this->zadd($key, $score, $member);
708 12
                $return += $res;
709 6
            }
710 12
            return $return;
711
        }
712 20
        return $this->driver->zadd($key, ...$dictionary);
713
    }
714
715
    /**
716
     * Return a range of members in a sorted set, by index
717
     * @param string $key
718
     * @param int $start
719
     * @param int $stop
720
     * @param boolean $withscores
721
     * @return array
722
     */
723 4 View Code Duplication
    public function zrange($key, $start, $stop, $withscores = false)
1 ignored issue
show
Duplication introduced by
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.

Loading history...
724
    {
725 4
        $this->init();
726 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
727 2
            return $this->driver->zrange($key, $start, $stop, ['WITHSCORES' => $withscores]);
728
        }
729 2
        return $this->driver->zrange($key, $start, $stop, $withscores);
730
    }
731
732
    /**
733
     * Return a range of members in a sorted set, by index, with scores ordered from high to low
734
     * @param string $key
735
     * @param int $start
736
     * @param int $stop
737
     * @param boolean $withscores
738
     * @return array
739
     */
740 4 View Code Duplication
    public function zrevrange($key, $start, $stop, $withscores = false)
1 ignored issue
show
Duplication introduced by
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.

Loading history...
741
    {
742 4
        $this->init();
743 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
744 2
            return $this->driver->zrevrange($key, $start, $stop, ['WITHSCORES' => $withscores]);
745
        }
746 2
        return $this->driver->zrevrange($key, $start, $stop, $withscores);
747
    }
748
749
    /**
750
     * Returns null instead of false for Redis driver
751
     * @param mixed $result
752
     * @return mixed
753
     */
754 112
    private function convertFalseToNull($result)
755
    {
756 112
        return $this->actualDriver() === self::DRIVER_REDIS && $result === false ? null : $result;
757
    }
758
759
    /**
760
     * Transforms Predis result Payload to boolean
761
     * @param mixed $result
762
     * @return mixed
763
     */
764 240
    private function transformResult($result)
765
    {
766 240
        if ($this->actualDriver() === self::DRIVER_PREDIS && $result instanceof Status) {
767 120
            $result = $result->getPayload() === 'OK';
768 60
        }
769 240
        return $result;
770
    }
771
772
    /**
773
     * Create array from input array - odd keys are used as keys, even keys are used as values
774
     * @param array $dictionary
775
     * @param string $command
776
     * @return array
777
     * @throws RedisProxyException if number of keys is not the same as number of values
778
     */
779 16
    private function prepareKeyValue(array $dictionary, $command)
780
    {
781
        $keys = array_values(array_filter($dictionary, function ($key) {
782 16
            return $key % 2 == 0;
783 16
        }, ARRAY_FILTER_USE_KEY));
784 16
        $values = array_values(array_filter($dictionary, function ($key) {
785 16
            return $key % 2 == 1;
786 16
        }, ARRAY_FILTER_USE_KEY));
787
788 16
        if (count($keys) != count($values)) {
789 8
            throw new RedisProxyException("Wrong number of arguments for $command command");
790
        }
791 8
        return array_combine($keys, $values);
792
    }
793
794 84
    private function prepareArguments($command, ...$params)
795
    {
796 84
        if (!isset($params[0])) {
797 8
            throw new RedisProxyException("Wrong number of arguments for $command command");
798
        }
799 76
        if (is_array($params[0])) {
800 32
            $params = $params[0];
801 16
        }
802 76
        return $params;
803
    }
804
}
805