Completed
Push — 2.0 ( aed067...b26523 )
by Marco
04:31
created

PhpRedis   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 363
Duplicated Lines 14.05 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 59.44%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 38
c 1
b 0
f 0
lcom 1
cbo 4
dl 51
loc 363
ccs 85
cts 143
cp 0.5944
rs 8.3999

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getRedisStatus() 0 5 1
B __construct() 0 42 4
C set() 19 66 9
B get() 0 52 7
B delete() 9 42 6
B flush() 0 26 3
B status() 6 44 3
A setNamespaceKey() 17 17 3
A getNamespaceKey() 0 15 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php namespace Comodojo\Cache\Providers;
2
3
use \Comodojo\Cache\Components\InstanceTrait;
4
use \Comodojo\Cache\Providers\AbstractProvider;
5
use \Psr\Log\LoggerInterface;
6
use \Redis;
7
use \Comodojo\Exception\CacheException;
8
use \RedisException;
9
use \Exception;
10
11
/**
12
 * Redis cache class using PhpRedis extension
13
 *
14
 * @package     Comodojo Spare Parts
15
 * @author      Marco Giovinazzi <[email protected]>
16
 * @license     MIT
17
 *
18
 * LICENSE:
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
 * THE SOFTWARE.
27
 */
28
29
class PhpRedis extends AbstractProvider {
30
31
    use InstanceTrait;
32
33
    /**
34
     * Class constructor
35
     *
36
     * @param   string          $server         Server address (or IP)
37
     * @param   integer         $port           (optional) Server port
38
     * @param   integer         $timeout        (optional) Timeout
39
     * @param   \Monolog\Logger $logger         Logger instance
40
     *
41
     * @throws \Comodojo\Exception\CacheException
42
     */
43 18
    public function __construct( $server, $port=6379, $timeout=0, LoggerInterface $logger=null ) {
44
45 18
        if ( empty($server) ) throw new CacheException("Invalid or unspecified memcached server");
46
47 18
        parent::__construct($logger);
48
49 18
        if ( self::getRedisStatus() === false ) {
50
51
            $this->logger->error("PhpRedis extension not available, disabling PhpRedisProvider administratively");
52
53
            $this->disable();
54
55
            return;
56
57
        }
58
59 18
        $this->setInstance(new Redis());
60
61 18
        $port = filter_var($port, FILTER_VALIDATE_INT, array(
62
            "options" => array(
63 18
                "min_range" => 1,
64 18
                "max_range" => 65535,
65 18
                "default" => 6379 )
66 18
            )
67 18
        );
68
69 18
        $weight = filter_var($timeout, FILTER_VALIDATE_INT, array(
70
            "options" => array(
71 18
                "min_range" => 0,
72 18
                "default" => 0 )
73 18
            )
74 18
        );
75
76 18
        if ( $this->instance->connect($server, $port, $weight) === false ) {
77
78
            $this->logger->error("Error communicating with Redis server, disabling PhpRedisProvider administratively", array( $this->instance->getLastError() ) );
79
80
            $this->disable();
81
82
        }
83
84 18
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 32
    public function set($name, $data, $ttl=null) {
90
91 32
        if ( empty($name) ) throw new CacheException("Name of object cannot be empty");
92
93 32
        if ( is_null($data) ) throw new CacheException("Object content cannot be null");
94
95 32
        if ( !$this->isEnabled() ) return false;
96
97 32
        $this->resetErrorState();
98
99
        try {
100
101 32
            $this->setTtl($ttl);
102
103 32
            $namespace = $this->getNamespaceKey();
104
105 32
            if ( $namespace === false ) $namespace = $this->setNamespaceKey();
106
107 32
            if ( $namespace === false ) {
108
109
                $this->logger->error("Error writing cache (PhpRedis), exiting gracefully", array( $this->instance->getLastError()));
110
111
                $this->setErrorState("Error writing cache (PhpRedis)");
112
113
                $return = false;
114
115 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
116
117 32
                $shadowName = $namespace."-".md5($name);
118
119 32
                $shadowTtl = $this->ttl;
120
121 32
                $shadowData = serialize($data);
122
123 32
                $return = $this->instance->setex($shadowName, $shadowTtl, $shadowData);
124
125 32
                if ( $return === false ) {
126
127
                    $this->logger->error("Error writing cache (PhpRedis), exiting gracefully", array( $this->instance->getLastError()));
128
129
                    $this->setErrorState("Error writing cache (PhpRedis)");
130
131
                }
132
133
            }
134
135 32
        } catch (RedisException $re ) {
136
137
            $this->logger->error("Server unreachable (PhpRedis), exiting gracefully", array(
138
                "RESULTCODE" => $re->getCode(),
139
                "RESULTMESSAGE" => $re->getMessage()
140
            ));
141
142
            $this->setErrorState("Server unreachable (PhpRedis)");
143
144
            return false;
145
146
        } catch (CacheException $ce) {
147
148
            throw $ce;
149
150
        }
151
152 32
        return $return;
153
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159 33
    public function get($name) {
160
161 33
        if ( empty($name) ) throw new CacheException("Name of object cannot be empty");
162
163 33
        if ( !$this->isEnabled() ) return null;
164
165 33
        $this->resetErrorState();
166
167
        try {
168
169 33
            $namespace = $this->getNamespaceKey();
170
171 33
            if ( $namespace === false ) {
172
173 11
                $return = false;
174
175 11
            } else {
176
177 26
                $shadowName = $namespace."-".md5($name);
178
179 26
                $return = $this->instance->get($shadowName);
180
181
                // if ( $return === false ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
182
                //
183
                //     $this->logger->error( "Error reading cache (PhpRedis), exiting gracefully", array( $this->instance->getLastError() ) );
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
184
                //
185
                //     $this->setErrorState();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
186
                //
187
                // }
188
189
            }
190
191 33
        } catch (RedisException $re ) {
192
193
            $this->logger->error("Server unreachable (PhpRedis), exiting gracefully", array(
194
                "RESULTCODE" => $re->getCode(),
195
                "RESULTMESSAGE" => $re->getMessage()
196
            ));
197
198
            $this->setErrorState("Server unreachable (PhpRedis)");
199
200
            return null;
201
202
        } catch (CacheException $ce) {
203
204
            throw $ce;
205
206
        }
207
208 33
        return $return === false ? null : unserialize($return);
209
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 11
    public function delete($name=null) {
216
217 11
        if ( !$this->isEnabled() ) return false;
218
219 11
        $this->resetErrorState();
220
221
        try {
222
223 11
            $namespace = $this->getNamespaceKey();
224
225 11
            if ( $namespace === false ) return true;
226
227 11 View Code Duplication
            if ( empty($name) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
228
229
                $this->instance->delete($this->getNamespace());
230
231
            } else {
232
233 11
                $this->instance->delete($namespace."-".md5($name));
234
235
            }
236
237 11
        } catch (RedisException $re ) {
238
239
            $this->logger->error("Server unreachable (PhpRedis), exiting gracefully", array(
240
                "RESULTCODE" => $re->getCode(),
241
                "RESULTMESSAGE" => $re->getMessage()
242
            ));
243
244
            $this->setErrorState("Server unreachable (PhpRedis)");
245
246
            return false;
247
248
        } catch (CacheException $ce) {
249
250
            throw $ce;
251
252
        }
253
254 11
        return true;
255
256
    }
257
258
    /**
259
     * {@inheritdoc}
260
     */
261 7
    public function flush() {
262
263 7
        if ( !$this->isEnabled() ) return false;
264
265 7
        $this->resetErrorState();
266
267
        try {
268
269 7
            $this->instance->flushDB();
270
271 7
        } catch (RedisException $re ) {
272
273
            $this->logger->error("Server unreachable (PhpRedis), exiting gracefully", array(
274
                "RESULTCODE" => $re->getCode(),
275
                "RESULTMESSAGE" => $re->getMessage()
276
            ));
277
278
            $this->setErrorState("Server unreachable (PhpRedis)");
279
280
            return false;
281
282
        }
283
284 7
        return true;
285
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291 7
    public function status() {
292
293 7
        $enabled = $this->isEnabled();
294
295 7 View Code Duplication
        if ( !$enabled ) return array(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
296
            "provider"  => "phpredis",
297
            "enabled"   => $enabled,
298
            "objects"   => null,
299
            "options"   => array()
300
        );
301
302 7
        $objects = 0;
303
304 7
        $options = array();
305
306 7
        $this->resetErrorState();
307
308
        try {
309
310 7
            $objects = $this->instance->dbSize();
311
312 7
            $options = $this->instance->info();
313
314 7
        } catch (RedisException $re ) {
315
316
            $this->logger->error("Server unreachable (PhpRedis), exiting gracefully", array(
317
                "RESULTCODE" => $re->getCode(),
318
                "RESULTMESSAGE" => $re->getMessage()
319
            ));
320
321
            $this->setErrorState("Server unreachable (PhpRedis)");
322
323
            $enabled = false;
324
325
        }
326
327
        return array(
328 7
            "provider"  => "phpredis",
329 7
            "enabled"   => $enabled,
330 7
            "objects"   => $objects,
331
            "options"   => $options
332 7
        );
333
334
    }
335
336
    /**
337
     * Set key for namespace
338
     *
339
     * @return  string
340
     */
341 14 View Code Duplication
    private function setNamespaceKey() {
0 ignored issues
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...
342
343 14
        $uId = self::getUniqueId();
344
345
        try {
346
347 14
            $return = $this->instance->set($this->getNamespace(), $uId);
348
349 14
        } catch (RedisException $re ) {
350
351
            throw $re;
352
353
        }
354
355 14
        return $return === false ? false : $uId;
356
357
    }
358
359
    /**
360
     * Get key for namespace
361
     *
362
     * @return  string
363
     */
364 49
    private function getNamespaceKey() {
365
366
        try {
367
368 49
            $return = $this->instance->get($this->getNamespace());
369
370 49
        } catch (RedisException $re ) {
371
372
            throw $re;
373
374
        }
375
376 49
        return $return;
377
378
    }
379
380
    /**
381
     * Check PhpRedis availability
382
     *
383
     * @return  bool
384
     */
385 18
    private static function getRedisStatus() {
386
387 18
        return class_exists('Redis');
388
389
    }
390
391
}
392