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

RedisProxy::type()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
ccs 12
cts 12
cp 1
rs 8.8571
cc 6
eloc 11
nc 5
nop 1
crap 6
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 240
    public function __construct($host, $port, $database = 0, $timeout = null)
83
    {
84 240
        $this->host = $host;
85 240
        $this->port = $port;
86 240
        $this->database = $database;
87 240
        $this->timeout = $timeout;
88 240
        $this->driversOrder = $this->supportedDrivers;
89 240
    }
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 240
    public function setDriversOrder(array $driversOrder)
98
    {
99 240
        foreach ($driversOrder as $driver) {
100 238
            if (!in_array($driver, $this->supportedDrivers)) {
101 120
                throw new RedisProxyException('Driver "' . $driver . '" is not supported');
102
            }
103 119
        }
104 238
        $this->driversOrder = $driversOrder;
105 238
        return $this;
106
    }
107
108 238
    private function init()
109
    {
110 238
        $this->prepareDriver();
111 236
        $this->select($this->database);
112 236
    }
113
114 238
    private function prepareDriver()
115
    {
116 238
        if ($this->driver !== null) {
117 236
            return;
118
        }
119
120 238
        foreach ($this->driversOrder as $preferredDriver) {
121 236
            if ($preferredDriver === self::DRIVER_REDIS && extension_loaded('redis')) {
122 118
                $this->driver = new Redis();
123 118
                return;
124
            }
125 118
            if ($preferredDriver === self::DRIVER_PREDIS && class_exists('Predis\Client')) {
126 118
                $this->driver = new Client();
127 118
                return;
128
            }
129 1
        }
130 2
        throw new RedisProxyException('No driver available');
131
    }
132
133
    /**
134
     * @return string|null
135
     */
136 238
    public function actualDriver()
137
    {
138 238
        if ($this->driver instanceof Redis) {
139 118
            return self::DRIVER_REDIS;
140
        }
141 124
        if ($this->driver instanceof Client) {
142 118
            return self::DRIVER_PREDIS;
143
        }
144 10
        return null;
145
    }
146
147 236
    private function connect($host, $port, $timeout = null)
148
    {
149 236
        return $this->driver->connect($host, $port, $timeout);
150
    }
151
152 236
    private function isConnected()
153
    {
154 236
        return $this->driver->isConnected();
155
    }
156
157 238
    public function __call($name, $arguments)
158
    {
159 238
        $this->init();
160 236
        $name = strtolower($name);
161
        try {
162 236
            $result = call_user_func_array([$this->driver, $name], $arguments);
163 120
        } catch (Exception $e) {
164 4
            throw new RedisProxyException("Error for command '$name', use getPrevious() for more info", 1484162284, $e);
165
        }
166 236
        return $this->transformResult($result);
167
    }
168
169
    /**
170
     * @param int $database
171
     * @return boolean true on success
172
     * @throws RedisProxyException on failure
173
     */
174 236
    public function select($database)
175
    {
176 236
        $this->prepareDriver();
177 236
        if (!$this->isConnected()) {
178 236
            $this->connect($this->host, $this->port, $this->timeout);
179 118
        }
180 236
        if ($database == $this->selectedDatabase) {
181 236
            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 64
    public function get($key)
245
    {
246 64
        $this->init();
247 64
        $result = $this->driver->get($key);
248 64
        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 value of a key, only if the key does not exist
279
     * @param string $key
280
     * @param string $value
281
     * @return boolean true if the key was set, false if the key was not set
282
     */
283 4
    public function setnx($key, $value)
284
    {
285 4
        $this->init();
286 4
        $result = $this->driver->setnx($key, $value);
287 4
        return (bool)$result;
288
    }
289
290
    /**
291
     * Delete a key(s)
292
     * @param array $keys
293
     * @return int number of deleted keys
294
     */
295 28
    public function del(...$keys)
296
    {
297 28
        $this->prepareArguments('del', ...$keys);
298 20
        $this->init();
299 20
        return $this->driver->del(...$keys);
300
    }
301
302
    /**
303
     * Delete a key(s)
304
     * @param array $keys
305
     * @return int number of deleted keys
306
     */
307 12
    public function delete(...$keys)
308
    {
309 12
        return $this->del(...$keys);
310
    }
311
312
    /**
313
     * Increment the integer value of a key by one
314
     * @param string $key
315
     * @return integer
316
     */
317 4
    public function incr($key)
318
    {
319 4
        $this->init();
320 4
        return $this->driver->incr($key);
321
    }
322
323
    /**
324
     * Increment the integer value of a key by the given amount
325
     * @param string $key
326
     * @param integer $increment
327
     * @return integer
328
     */
329 4
    public function incrby($key, $increment = 1)
330
    {
331 4
        $this->init();
332 4
        return $this->driver->incrby($key, (int)$increment);
333
    }
334
335
    /**
336
     * Increment the float value of a key by the given amount
337
     * @param string $key
338
     * @param float $increment
339
     * @return float
340
     */
341 8
    public function incrbyfloat($key, $increment = 1)
342
    {
343 8
        $this->init();
344 8
        return $this->driver->incrbyfloat($key, $increment);
345
    }
346
347
    /**
348
     * Decrement the integer value of a key by one
349
     * @param string $key
350
     * @return integer
351
     */
352 4
    public function decr($key)
353
    {
354 4
        $this->init();
355 4
        return $this->driver->decr($key);
356
    }
357
358
    /**
359
     * Decrement the integer value of a key by the given number
360
     * @param string $key
361
     * @param integer $decrement
362
     * @return integer
363
     */
364 4
    public function decrby($key, $decrement = 1)
365
    {
366 4
        $this->init();
367 4
        return $this->driver->decrby($key, (int)$decrement);
368
    }
369
370
    /**
371
     * Decrement the float value of a key by the given amount
372
     * @param string $key
373
     * @param float $decrement
374
     * @return float
375
     */
376 4
    public function decrbyfloat($key, $decrement = 1)
377
    {
378 4
        return $this->incrbyfloat($key, (-1) * $decrement);
379
    }
380
381
    /**
382
     * Set multiple values to multiple keys
383
     * @param array $dictionary
384
     * @return boolean true on success
385
     * @throws RedisProxyException if number of arguments is wrong
386
     */
387 12 View Code Duplication
    public function mset(...$dictionary)
388
    {
389 12
        $this->init();
390 12
        if (is_array($dictionary[0])) {
391 8
            $result = $this->driver->mset(...$dictionary);
392 8
            return $this->transformResult($result);
393
        }
394 8
        $dictionary = $this->prepareKeyValue($dictionary, 'mset');
395 4
        $result = $this->driver->mset($dictionary);
396 4
        return $this->transformResult($result);
397
    }
398
399
    /**
400
     * Multi get
401
     * @param array $keys
402
     * @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
403
     */
404 4
    public function mget(...$keys)
405
    {
406 4
        $keys = array_unique($this->prepareArguments('mget', ...$keys));
407 4
        $this->init();
408 4
        $values = [];
409 4
        foreach ($this->driver->mget($keys) as $value) {
410 4
            $values[] = $this->convertFalseToNull($value);
411 2
        }
412 4
        return array_combine($keys, $values);
413
    }
414
415
    /**
416
     * Incrementally iterate the keys space
417
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
418
     * @param string $pattern pattern for keys, use * as wild card
419
     * @param int $count
420
     * @return array|boolean|null list of found keys, returns null if $iterator is 0 or '0'
421
     */
422 4 View Code Duplication
    public function scan(&$iterator, $pattern = null, $count = null)
423
    {
424 4
        if ((string)$iterator === '0') {
425 4
            return null;
426
        }
427 4
        $this->init();
428 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
429 2
            $returned = $this->driver->scan($iterator, ['match' => $pattern, 'count' => $count]);
430 2
            $iterator = $returned[0];
431 2
            return $returned[1];
432
        }
433 2
        return $this->driver->scan($iterator, $pattern, $count);
434
    }
435
436
    /**
437
     * Get the value of a hash field
438
     * @param string $key
439
     * @param string $field
440
     * @return string|null null if hash field is not set
441
     */
442 16
    public function hget($key, $field)
443
    {
444 16
        $this->init();
445 16
        $result = $this->driver->hget($key, $field);
446 16
        return $this->convertFalseToNull($result);
447
    }
448
449
    /**
450
     * Delete one or more hash fields, returns number of deleted fields
451
     * @param array $key
452
     * @param array $fields
453
     * @return int
454
     */
455 8
    public function hdel($key, ...$fields)
456
    {
457 8
        $fields = $this->prepareArguments('hdel', ...$fields);
458 8
        $this->init();
459 8
        return $this->driver->hdel($key, ...$fields);
460
    }
461
462
    /**
463
     * Increment the integer value of hash field by given number
464
     * @param string $key
465
     * @param string $field
466
     * @param int $increment
467
     * @return int
468
     */
469 4
    public function hincrby($key, $field, $increment = 1)
470
    {
471 4
        $this->init();
472 4
        return $this->driver->hincrby($key, $field, (int)$increment);
473
    }
474
475
    /**
476
     * Increment the float value of hash field by given amount
477
     * @param string $key
478
     * @param string $field
479
     * @param float $increment
480
     * @return float
481
     */
482 4
    public function hincrbyfloat($key, $field, $increment = 1)
483
    {
484 4
        $this->init();
485 4
        return $this->driver->hincrbyfloat($key, $field, $increment);
486
    }
487
488
    /**
489
     * Set multiple values to multiple hash fields
490
     * @param string $key
491
     * @param array $dictionary
492
     * @return boolean true on success
493
     * @throws RedisProxyException if number of arguments is wrong
494
     */
495 12 View Code Duplication
    public function hmset($key, ...$dictionary)
496
    {
497 12
        $this->init();
498 12
        if (is_array($dictionary[0])) {
499 8
            $result = $this->driver->hmset($key, ...$dictionary);
500 8
            return $this->transformResult($result);
501
        }
502 8
        $dictionary = $this->prepareKeyValue($dictionary, 'hmset');
503 4
        $result = $this->driver->hmset($key, $dictionary);
504 4
        return $this->transformResult($result);
505
    }
506
507
    /**
508
     * Multi hash get
509
     * @param string $key
510
     * @param array $fields
511
     * @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
512
     */
513 4
    public function hmget($key, ...$fields)
514
    {
515 4
        $fields = array_unique($this->prepareArguments('hmget', ...$fields));
516 4
        $this->init();
517 4
        $values = [];
518 4
        foreach ($this->driver->hmget($key, $fields) as $value) {
519 4
            $values[] = $this->convertFalseToNull($value);
520 2
        }
521 4
        return array_combine($fields, $values);
522
    }
523
524
    /**
525
     * Incrementally iterate hash fields and associated values
526
     * @param string $key
527
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
528
     * @param string $pattern pattern for fields, use * as wild card
529
     * @param int $count
530
     * @return array|boolean|null list of found fields with associated values, returns null if $iterator is 0 or '0'
531
     */
532 4 View Code Duplication
    public function hscan($key, &$iterator, $pattern = null, $count = null)
533
    {
534 4
        if ((string)$iterator === '0') {
535 4
            return null;
536
        }
537 4
        $this->init();
538 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
539 2
            $returned = $this->driver->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
540 2
            $iterator = $returned[0];
541 2
            return $returned[1];
542
        }
543 2
        return $this->driver->hscan($key, $iterator, $pattern, $count);
544
    }
545
546
    /**
547
     * Add one or more members to a set
548
     * @param string $key
549
     * @param array $members
550
     * @return int number of new members added to set
551
     */
552 16
    public function sadd($key, ...$members)
553
    {
554 16
        $members = $this->prepareArguments('sadd', ...$members);
555 16
        $this->init();
556 16
        return $this->driver->sadd($key, ...$members);
557
    }
558
559
    /**
560
     * Remove and return one or multiple random members from a set
561
     * @param string $key
562
     * @param int $count number of members
563
     * @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
564
     */
565 4
    public function spop($key, $count = 1)
566
    {
567 4
        $this->init();
568 4
        if ($count == 1 || $count === null) {
569 4
            $result = $this->driver->spop($key);
570 4
            return $this->convertFalseToNull($result);
571
        }
572
573 4
        $members = [];
574 4
        for ($i = 0; $i < $count; ++$i) {
575 4
            $member = $this->driver->spop($key);
576 4
            if (!$member) {
577 4
                break;
578
            }
579 4
            $members[] = $member;
580 2
        }
581 4
        return empty($members) ? null : $members;
582
    }
583
584
    /**
585
     * Incrementally iterate Set elements
586
     * @param string $key
587
     * @param mixed $iterator iterator / cursor, use $iterator = null for start scanning, when $iterator is changed to 0 or '0', scanning is finished
588
     * @param string $pattern pattern for member's values, use * as wild card
589
     * @param int $count
590
     * @return array|boolean|null list of found members, returns null if $iterator is 0 or '0'
591
     */
592 4 View Code Duplication
    public function sscan($key, &$iterator, $pattern = null, $count = null)
593
    {
594 4
        if ((string)$iterator === '0') {
595 4
            return null;
596
        }
597 4
        $this->init();
598 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
599 2
            $returned = $this->driver->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
600 2
            $iterator = $returned[0];
601 2
            return $returned[1];
602
        }
603 2
        return $this->driver->sscan($key, $iterator, $pattern, $count);
604
    }
605
606
    /**
607
     * Prepend one or multiple values to a list
608
     * @param string $key
609
     * @param array $elements
610
     * @return int the length of the list after the push operations
611
     */
612 28
    public function lpush($key, ...$elements)
613
    {
614 28
        $elements = $this->prepareArguments('lpush', ...$elements);
615 28
        $this->init();
616 28
        return $this->driver->lpush($key, ...$elements);
617
    }
618
619
    /**
620
     * Append one or multiple values to a list
621
     * @param string $key
622
     * @param array $elements
623
     * @return int the length of the list after the push operations
624
     */
625 12
    public function rpush($key, ...$elements)
626
    {
627 12
        $elements = $this->prepareArguments('rpush', ...$elements);
628 12
        $this->init();
629 12
        return $this->driver->rpush($key, ...$elements);
630
    }
631
632
    /**
633
     * Remove and get the first element in a list
634
     * @param string $key
635
     * @return string|null
636
     */
637 4
    public function lpop($key)
638
    {
639 4
        $this->init();
640 4
        $result = $this->driver->lpop($key);
641 4
        return $this->convertFalseToNull($result);
642
    }
643
644
    /**
645
     * Remove and get the last element in a list
646
     * @param string $key
647
     * @return string|null
648
     */
649 4
    public function rpop($key)
650
    {
651 4
        $this->init();
652 4
        $result = $this->driver->rpop($key);
653 4
        return $this->convertFalseToNull($result);
654
    }
655
656
    /**
657
     * Get an element from a list by its index
658
     * @param string $key
659
     * @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
660
     * @return string|null
661
     */
662 12
    public function lindex($key, $index)
663
    {
664 12
        $this->init();
665 12
        $result = $this->driver->lindex($key, $index);
666 12
        return $this->convertFalseToNull($result);
667
    }
668
669
    /**
670
     * Add one or more members to a sorted set, or update its score if it already exists
671
     * @param string $key
672
     * @param array $dictionary (score1, member1[, score2, member2]) or associative array: [member1 => score1, member2 => score2]
673
     * @return int
674
     */
675 20
    public function zadd($key, ...$dictionary)
676
    {
677 20
        $this->init();
678 20
        if (is_array($dictionary[0])) {
679 12
            $return = 0;
680 12
            foreach ($dictionary[0] as $member => $score) {
681 12
                $res = $this->zadd($key, $score, $member);
682 12
                $return += $res;
683 6
            }
684 12
            return $return;
685
        }
686 20
        return $this->driver->zadd($key, ...$dictionary);
687
    }
688
689
    /**
690
     * Return a range of members in a sorted set, by index
691
     * @param string $key
692
     * @param int $start
693
     * @param int $stop
694
     * @param boolean $withscores
695
     * @return array
696
     */
697 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...
698
    {
699 4
        $this->init();
700 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
701 2
            return $this->driver->zrange($key, $start, $stop, ['WITHSCORES' => $withscores]);
702
        }
703 2
        return $this->driver->zrange($key, $start, $stop, $withscores);
704
    }
705
706
    /**
707
     * Return a range of members in a sorted set, by index, with scores ordered from high to low
708
     * @param string $key
709
     * @param int $start
710
     * @param int $stop
711
     * @param boolean $withscores
712
     * @return array
713
     */
714 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...
715
    {
716 4
        $this->init();
717 4
        if ($this->actualDriver() === self::DRIVER_PREDIS) {
718 2
            return $this->driver->zrevrange($key, $start, $stop, ['WITHSCORES' => $withscores]);
719
        }
720 2
        return $this->driver->zrevrange($key, $start, $stop, $withscores);
721
    }
722
723
    /**
724
     * Returns null instead of false for Redis driver
725
     * @param mixed $result
726
     * @return mixed
727
     */
728 104
    private function convertFalseToNull($result)
729
    {
730 104
        return $this->actualDriver() === self::DRIVER_REDIS && $result === false ? null : $result;
731
    }
732
733
    /**
734
     * Transforms Predis result Payload to boolean
735
     * @param mixed $result
736
     * @return mixed
737
     */
738 236
    private function transformResult($result)
739
    {
740 236
        if ($this->actualDriver() === self::DRIVER_PREDIS && $result instanceof Status) {
741 118
            $result = $result->getPayload() === 'OK';
742 59
        }
743 236
        return $result;
744
    }
745
746
    /**
747
     * Create array from input array - odd keys are used as keys, even keys are used as values
748
     * @param array $dictionary
749
     * @param string $command
750
     * @return array
751
     * @throws RedisProxyException if number of keys is not the same as number of values
752
     */
753 16
    private function prepareKeyValue(array $dictionary, $command)
754
    {
755
        $keys = array_values(array_filter($dictionary, function ($key) {
756 16
            return $key % 2 == 0;
757 16
        }, ARRAY_FILTER_USE_KEY));
758 16
        $values = array_values(array_filter($dictionary, function ($key) {
759 16
            return $key % 2 == 1;
760 16
        }, ARRAY_FILTER_USE_KEY));
761
762 16
        if (count($keys) != count($values)) {
763 8
            throw new RedisProxyException("Wrong number of arguments for $command command");
764
        }
765 8
        return array_combine($keys, $values);
766
    }
767
768 84
    private function prepareArguments($command, ...$params)
769
    {
770 84
        if (!isset($params[0])) {
771 8
            throw new RedisProxyException("Wrong number of arguments for $command command");
772
        }
773 76
        if (is_array($params[0])) {
774 32
            $params = $params[0];
775 16
        }
776 76
        return $params;
777
    }
778
}
779