Completed
Branch master (f4cf4a)
by Michal
02:08
created

RedisProxy::hget()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 2
crap 3
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 boolean set(string $key, string $value) Set the string value of a key
13
 * @method array mget(array $keys) Multi get - Returns the values of all specified keys. For every key that does not hold a string value or does not exist, FALSE is returned.
14
 * @method integer hset(string $key, string $field, string $value) Set the string value of a hash field
15
 * @method array hgetall(string $key) Get all fields and values in hash
16
 * @method array hGetAll(string $key) Get all fields and values in hash
17
 * @method integer hlen(string $key) Get the number of fields in hash
18
 * @method integer hLen(string $key) Get the number of fields in hash
19
 * @method boolean flushall() Remove all keys from all databases
20
 * @method boolean flushAll() Remove all keys from all databases
21
 * @method boolean flushdb() Remove all keys from the current database
22
 * @method boolean flushDb() Remove all keys from the current database
23
 */
24
class RedisProxy
25
{
26
    const DRIVER_REDIS = 'redis';
27
28
    const DRIVER_PREDIS = 'predis';
29
30
    private $driver;
31
32
    private $host;
33
34
    private $port;
35
36
    private $database = 0;
37
38
    private $timeout;
39
40
    private $supportedDrivers = [
41
        self::DRIVER_REDIS,
42
        self::DRIVER_PREDIS,
43
    ];
44
45
    private $driversOrder = [];
46
47 48
    public function __construct($host, $port, $timeout = null)
48
    {
49 48
        $this->host = $host;
50 48
        $this->port = $port;
51 48
        $this->timeout = $timeout;
52 48
        $this->driversOrder = $this->supportedDrivers;
53 48
    }
54
55 48
    public function setDriversOrder(array $driversOrder)
56
    {
57 48
        if (empty($driversOrder)) {
58 2
            throw new RedisProxyException('You need to set at least one driver');
59
        }
60 46
        foreach ($driversOrder as $driver) {
61 46
            if (!in_array($driver, $this->supportedDrivers)) {
62 46
                throw new RedisProxyException('Driver "' . $driver . '" is not supported');
63
            }
64
        }
65 44
        $this->driversOrder = $driversOrder;
66 44
        return $this;
67
    }
68
69 44
    private function init()
70
    {
71 44
        $this->prepareDriver();
72 44
        $this->select($this->database);
73 44
    }
74
75 44
    private function prepareDriver()
76
    {
77 44
        if ($this->driver !== null) {
78 44
            return;
79
        }
80
81 44
        foreach ($this->driversOrder as $preferredDriver) {
82 44
            if ($preferredDriver === self::DRIVER_REDIS && extension_loaded('redis')) {
83 22
                $this->driver = new Redis();
84 22
                return;
85
            }
86 22
            if ($preferredDriver === self::DRIVER_PREDIS && class_exists('Predis\Client')) {
87 22
                $this->driver = new Client();
88 22
                return;
89
            }
90
        }
91
        throw new RedisProxyException('No redis library loaded (ext-redis or predis)');
92
    }
93
94 44
    private function connect($host, $port, $timeout = null)
95
    {
96 44
        return $this->driver->connect($host, $port, $timeout);
97
    }
98
99 44
    private function isConnected()
100
    {
101 44
        return $this->driver->isConnected();
102
    }
103
104 44
    public function __call($name, $arguments)
105
    {
106 44
        $this->init();
107 44
        $result = call_user_func_array([$this->driver, $name], $arguments);
108 44
        if ($this->driver instanceof Client && $result instanceof Status) {
109 22
            $result = $result->getPayload() === 'OK';
110
        }
111 44
        return $result;
112
    }
113
114
    /**
115
     * @param integer $database
116
     * @return boolean true on success
117
     * @throws RedisProxyException on failure
118
     */
119 44
    public function select($database)
120
    {
121 44
        $this->prepareDriver();
122 44
        if (!$this->isConnected()) {
123 44
            $this->connect($this->host, $this->port, $this->timeout);
124
        }
125
        try {
126 44
            $result = $this->driver->select($database);
127 2
        } catch (Exception $e) {
128 2
            throw new RedisProxyException('Invalid DB index');
129
        }
130 44
        if ($this->driver instanceof Client) {
131 22
            $result = $result->getPayload() === 'OK';
132
        }
133 44
        if ($result === false) {
134 2
            throw new RedisProxyException('Invalid DB index');
135
        }
136 44
        $this->database = $database;
137 44
        return $result;
138
    }
139
140
    /**
141
     * @param string|null $section
142
     * @return array
143
     */
144 8
    public function info($section = null)
145
    {
146 8
        $this->init();
147 8
        if ($section === null) {
148 4
            $result = $this->driver->info();
149
        } else {
150 8
            $section = strtolower($section);
151 8
            $result = $this->driver->info($section);
152
        }
153
154 8
        $databases = $section === null || $section === 'keyspace' ? $this->config('get', 'databases')['databases'] : null;
155 8
        $groupedResult = InfoHelper::createInfoArray($this->driver, $result, $databases);
156 8
        if ($section === null) {
157 4
            return $groupedResult;
158
        }
159 8
        if (isset($groupedResult[$section])) {
160 4
            return $groupedResult[$section];
161
        }
162 4
        throw new RedisProxyException('Info section "' . $section . '" doesn\'t exist');
163
    }
164
165
    /**
166
     * @param string $key
167
     * @return string
168
     */
169 12
    public function get($key)
170
    {
171 12
        $this->init();
172 12
        $result = $this->driver->get($key);
173 12
        if ($this->driver instanceof Client) {
174 6
            $result = $result === null ? false : $result;
175
        }
176 12
        return $result;
177
    }
178
179 12
    public function del(...$key)
180
    {
181 12
        $this->init();
182 12
        return $this->driver->del(...$key);
183
    }
184
185 8
    public function delete(...$key)
186
    {
187 8
        return $this->del(...$key);
188
    }
189
190 View Code Duplication
    public function scan(&$iterator, $pattern = null, $count = null)
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...
191
    {
192
        $this->init();
193
        if ($this->driver instanceof Client) {
194
            $returned = $this->driver->scan($iterator, ['match' => $pattern, 'count' => $count]);
195
            $iterator = $returned[0];
196
            return $returned[1];
197
        }
198
        return $this->driver->scan($iterator, $pattern, $count);
199
    }
200
201
    /**
202
     * Get the value of a hash field
203
     * @param string $key
204
     * @param string $field
205
     * @return string|boolean false if hash field is not set
206
     */
207 4
    public function hget($key, $field)
208
    {
209 4
        $this->init();
210 4
        $result = $this->driver->hget($key, $field);
211 4
        if ($this->driver instanceof Client) {
212 2
            $result = $result === null ? false : $result;
213
        }
214 4
        return $result;
215
    }
216
217
    /**
218
     * Delete one or more hash fields, returns number of deleted fields
219
     * @param string $key
220
     * @param array $fields
221
     * @return integer
222
     */
223 8
    public function hdel($key, ...$fields)
224
    {
225 8
        if (is_array($fields[0])) {
226 4
            $fields = $fields[0];
227
        }
228 8
        $res = $this->driver->hdel($key, ...$fields);
229
230 8
        return $res;
231
    }
232
233 View Code Duplication
    public function hscan($key, &$iterator, $pattern = null, $count = null)
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...
234
    {
235
        $this->init();
236
        if ($this->driver instanceof Client) {
237
            $returned = $this->driver->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
238
            $iterator = $returned[0];
239
            return $returned[1];
240
        }
241
        return $this->driver->hscan($key, $iterator, $pattern, $count);
242
    }
243
244 View Code Duplication
    public function zscan($key, &$iterator, $pattern = null, $count = null)
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...
245
    {
246
        $this->init();
247
        if ($this->driver instanceof Client) {
248
            $returned = $this->driver->zscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
249
            $iterator = $returned[0];
250
            return $returned[1];
251
        }
252
        return $this->driver->zscan($key, $iterator, $pattern, $count);
253
    }
254
255 View Code Duplication
    public function sscan($key, &$iterator, $pattern = null, $count = null)
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...
256
    {
257
        $this->init();
258
        if ($this->driver instanceof Client) {
259
            $returned = $this->driver->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
260
            $iterator = $returned[0];
261
            return $returned[1];
262
        }
263
        return $this->driver->sscan($key, $iterator, $pattern, $count);
264
    }
265
}
266