Completed
Pull Request — master (#1)
by Michal
06:19 queued 01:52
created

RedisProxy::connect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 3
crap 1
1
<?php
2
3
namespace RedisProxy;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Predis\Client;
8
use Redis;
9
10
class RedisProxy
11
{
12
    const DRIVER_REDIS = 'redis';
13
14
    const DRIVER_PREDIS = 'predis';
15
16
    private $driver;
17
18
    private $host;
19
20
    private $port;
21
22
    private $database = 0;
23
24
    private $timeout;
25
26
    private $supportedDrivers = [
27
        self::DRIVER_REDIS,
28
        self::DRIVER_PREDIS,
29
    ];
30
31
    private $driversOrder = [];
32
33 24
    public function __construct($host, $port, $timeout = null)
34
    {
35 24
        $this->host = $host;
36 24
        $this->port = $port;
37 24
        $this->timeout = $timeout;
38 24
        $this->driversOrder = $this->supportedDrivers;
39 24
    }
40
41 24
    public function setDriversOrder(array $driversOrder)
42
    {
43 24
        foreach ($driversOrder as $driver) {
44 24
            if (!in_array($driver, $this->supportedDrivers)) {
45 12
                throw new InvalidArgumentException('Driver "' . $driver . '" is not supported');
46
            }
47 12
        }
48 24
        $this->driversOrder = $driversOrder;
49 24
        return $this;
50
    }
51
52 24
    private function init()
53
    {
54 24
        $this->prepareDriver();
55 24
        $this->select($this->database);
56 24
    }
57
58 24
    private function prepareDriver()
59
    {
60 24
        if ($this->driver !== null) {
61 24
            return;
62
        }
63
64 24
        foreach ($this->driversOrder as $preferredDriver) {
65 24
            if ($preferredDriver === self::DRIVER_REDIS && extension_loaded('redis')) {
66 12
                $this->driver = new Redis();
67 12
                return;
68
            }
69 12
            if ($preferredDriver === self::DRIVER_PREDIS && class_exists('Predis\Client')) {
70 12
                $this->driver = new Client();
71 12
                return;
72
            }
73
        }
74
        throw new RedisProxyException('No redis library loaded (ext-redis or predis)');
75
    }
76
77 24
    private function connect($host, $port, $timeout = null)
78
    {
79 24
        return $this->driver->connect($host, $port, $timeout);
1 ignored issue
show
Unused Code introduced by
The call to Client::connect() has too many arguments starting with $host.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
80
    }
81
82 24
    private function isConnected()
83
    {
84 24
        return $this->driver->isConnected();
1 ignored issue
show
Bug introduced by
The method isConnected does only exist in Predis\Client, but not in Redis.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
85
    }
86
87 24
    public function __call($name, $arguments)
88
    {
89 24
        $this->init();
90 24
        return call_user_func_array([$this->driver, $name], $arguments);
91
    }
92
93
    /**
94
     * @param string $database
95
     * @return type
96
     */
97 24
    public function select($database)
98
    {
99 24
        $this->prepareDriver();
100 24
        if (!$this->isConnected()) {
101 24
            $this->connect($this->host, $this->port, $this->timeout);
102 12
        }
103
        try {
104 24
            $result = $this->driver->select($database);
1 ignored issue
show
Bug introduced by
The method select does only exist in Redis, but not in Predis\Client.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
105 13
        } catch (Exception $e) {
106 2
            throw new RedisProxyException('Invalid DB index');
107
        }
108 24
        if ($this->driver instanceof Client) {
109 12
            $result = $result->getPayload() === 'OK';
110 6
        }
111 24
        if ($result === false) {
112 2
            throw new RedisProxyException('Invalid DB index');
113
        }
114 24
        $this->database = $database;
0 ignored issues
show
Documentation Bug introduced by
The property $database was declared of type integer, but $database is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
115 24
        return $result;
116
    }
117
118
    /**
119
     * @param string $key
120
     * @return string
121
     */
122 12 View Code Duplication
    public function get($key)
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...
123
    {
124 12
        $this->init();
125 12
        $result = $this->driver->get($key);
1 ignored issue
show
Bug introduced by
The method get does only exist in Redis, but not in Predis\Client.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
126 12
        if ($this->driver instanceof Client) {
127 6
            $result = $result === null ? false : $result;
128 3
        }
129 12
        return $result;
130
    }
131
132
    /**
133
     * @param string $key
134
     * @param string $value
135
     * @return boolean
136
     */
137 16
    public function set($key, $value)
138
    {
139 16
        $this->init();
140 16
        $result = $this->driver->set($key, $value);
1 ignored issue
show
Bug introduced by
The method set does only exist in Redis, but not in Predis\Client.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
141 16
        if ($this->driver instanceof Client) {
142 8
            $result = $result->getPayload() === 'OK';
143 4
        }
144 16
        return $result;
145
    }
146
147 8
    public function del(...$key)
148
    {
149 8
        $this->init();
150 8
        return $this->driver->del(...$key);
1 ignored issue
show
Bug introduced by
The method del does only exist in Redis, but not in Predis\Client.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
151
    }
152
153 8
    public function delete(...$key)
154
    {
155 8
        return $this->del(...$key);
156
    }
157
158 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...
159
    {
160
        $this->init();
161
        if ($this->driver instanceof Client) {
162
            $returned = $this->driver->scan($iterator, ['match' => $pattern, 'count' => $count]);
163
            $iterator = $returned[0];
164
            return $returned[1];
165
        }
166
        return $this->driver->scan($iterator, $pattern, $count);
167
    }
168
169 4 View Code Duplication
    public function hget($key, $field)
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...
170
    {
171 4
        $this->init();
172 4
        $result = $this->driver->hget($key, $field);
1 ignored issue
show
Bug introduced by
The method hget does only exist in Redis, but not in Predis\Client.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
173 4
        if ($this->driver instanceof Client) {
174 2
            $result = $result === null ? false : $result;
175 1
        }
176 4
        return $result;
177
    }
178
179 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...
180
    {
181
        $this->init();
182
        if ($this->driver instanceof Client) {
183
            $returned = $this->driver->hscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
184
            $iterator = $returned[0];
185
            return $returned[1];
186
        }
187
        return $this->driver->hscan($key, $iterator, $pattern, $count);
188
    }
189
190 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...
191
    {
192
        $this->init();
193
        if ($this->driver instanceof Client) {
194
            $returned = $this->driver->zscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
195
            $iterator = $returned[0];
196
            return $returned[1];
197
        }
198
        return $this->driver->zscan($key, $iterator, $pattern, $count);
199
    }
200
201 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...
202
    {
203
        $this->init();
204
        if ($this->driver instanceof Client) {
205
            $returned = $this->driver->sscan($key, $iterator, ['match' => $pattern, 'count' => $count]);
206
            $iterator = $returned[0];
207
            return $returned[1];
208
        }
209
        return $this->driver->sscan($key, $iterator, $pattern, $count);
210
    }
211
}
212