Completed
Push — master ( b9da65...b16e40 )
by Marco
04:58
created

AbstractEnhancedProvider::set()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 30
Code Lines 15

Duplication

Lines 3
Ratio 10 %

Code Coverage

Tests 10
CRAP Score 7.6024

Importance

Changes 0
Metric Value
dl 3
loc 30
ccs 10
cts 13
cp 0.7692
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 15
nc 8
nop 3
crap 7.6024
1
<?php namespace Comodojo\SimpleCache\Providers;
2
3
use \Comodojo\Cache\Traits\StatefulTrait;
4
use \Comodojo\Cache\Traits\NamespaceTrait;
5
use \Comodojo\SimpleCache\Interfaces\EnhancedSimpleCacheInterface;
6
use \Comodojo\Cache\Components\UniqueId;
7
use \Psr\Log\LoggerInterface;
8
use \Comodojo\Cache\Components\KeyValidator;
9
use \DateTime;
10
use \DateInterval;
11
use \Traversable;
12
use \Comodojo\Exception\SimpleCacheException;
13
use \Comodojo\Exception\InvalidSimpleCacheArgumentException;
14
use \Exception;
15
16
/**
17
 * Abstract stateful provider implementation
18
 *
19
 * @package     Comodojo Spare Parts
20
 * @author      Marco Giovinazzi <[email protected]>
21
 * @license     MIT
22
 *
23
 * LICENSE:
24
 *
25
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
 * THE SOFTWARE.
32
 */
33
34
abstract class AbstractEnhancedProvider
35
    extends AbstractProvider
0 ignored issues
show
Coding Style introduced by
The extends keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
Expected 0 spaces between "AbstractProvider" and comma; 1 found
Loading history...
36
    implements EnhancedSimpleCacheInterface {
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
37
38
    use StatefulTrait;
39
    use NamespaceTrait;
40
41
    protected $driver;
42
43
    private $queue = [];
0 ignored issues
show
Unused Code introduced by
The property $queue is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
44
45 141
    public function __construct(LoggerInterface $logger = null) {
46
47 141
        parent::__construct($logger);
48
49 141
        $this->setId(UniqueId::get())->test();
50
51 141
    }
52
53 90
    public function get($key, $default = null) {
54
55 90
        if ( KeyValidator::validateKey($key) === false ) {
56
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
57
        }
58
59
        try {
60
61 90
            $data = $this->driver->get($key, $this->getNamespace());
62
63 90
        } catch (Exception $e) {
64
65
            $this->setState(self::CACHE_ERROR, $e->getMessage());
66
            $data = null;
67
68
        }
69
70 90
        if ( $data === null ) return $default;
71
72 61
        return unserialize($data);
73
74
    }
75
76 101
    public function set($key, $value, $ttl = null) {
77
78 101
        if ( KeyValidator::validateKey($key) === false ) {
79
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
80
        }
81
82 101
        if ( $value === null ) {
83 7
            throw new InvalidSimpleCacheArgumentException('Cannot cache a null value');
84
        }
85
86
        $real_ttl;
0 ignored issues
show
Bug introduced by
The variable $real_ttl seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
87
88 94 View Code Duplication
        if ( $ttl == null || $ttl == 0 ) $real_ttl = 0;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $ttl of type null|integer|Psr\SimpleCache\DateInterval against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
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...
89 22
        else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s');
90 22
        else $real_ttl = intval($ttl);
91
92
        try {
93
94 94
            $data = $this->driver->set($key, $this->getNamespace(), serialize($value), $real_ttl);
95
96 94
        } catch (Exception $e) {
97
98
            $this->setState(self::CACHE_ERROR, $e->getMessage());
99
            $data = false;
100
101
        }
102
103 94
        return $data;
104
105
    }
106
107 15 View Code Duplication
    public function delete($key) {
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...
108
109 15
        if ( KeyValidator::validateKey($key) === false ) {
110
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
111
        }
112
113
        try {
114
115 15
            $data = $this->driver->delete($key, $this->getNamespace());
116
117 15
        } catch (Exception $e) {
118
119
            $this->setState(self::CACHE_ERROR, $e->getMessage());
120
            $data = false;
121
122
        }
123
124 15
        return $data;
125
126
    }
127
128 7
    public function clear() {
129
130
        try {
131
132 7
            $data = $this->driver->clear();
133
134 7
        } catch (Exception $e) {
135
136
            $this->setState(self::CACHE_ERROR, $e->getMessage());
137
            $data = false;
138
139
        }
140
141 7
        return $data;
142
143
    }
144
145 8
    public function getMultiple($keys, $default = null) {
146
147 8
        if ( !is_array($keys) && !($keys instanceof Traversable) ) {
148
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
149
        }
150
151 8
        foreach ( $keys as $key ) {
152 8
            if ( KeyValidator::validateKey($key) === false ) {
153
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
154
            }
155 8
        }
156
157
        try {
158
159 8
            $data = $this->driver->getMultiple($keys, $this->getNamespace());
160
161 8
        } catch (Exception $e) {
162
163
            $this->setState(self::CACHE_ERROR, $e->getMessage());
164
            $data = array_combine($keys, array_fill(0, count($keys), null));
165
166
        }
167
168 8
        return array_map(function($value) use($default) {
169 8
            if ( $value === null ) return $default;
170 7
            return unserialize($value);
171 8
        }, $data);
172
173
    }
174
175 8
    public function setMultiple($values, $ttl = null) {
176
177 8
        if ( !is_array($values) && !($values instanceof Traversable) ) {
178
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
179
        }
180
181 8
        $real_values = [];
182
183 8
        foreach ( $values as $key => $value ) {
184 8
            if ( KeyValidator::validateKey($key) === false ) {
185
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
186
            }
187 8
            if ( $value === null ) {
188
                throw new InvalidSimpleCacheArgumentException('Cannot cache a null value');
189
            }
190 8
            $real_values[$key] = serialize($value);
191 8
        }
192
193
        $real_ttl;
0 ignored issues
show
Bug introduced by
The variable $real_ttl seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
194
195 8 View Code Duplication
        if ( $ttl == null || $ttl == 0 ) $real_ttl = 0;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $ttl of type null|integer|Psr\SimpleCache\DateInterval against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
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...
196
        else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s');
197
        else $real_ttl = intval($ttl);
198
199
        try {
200
201 8
            $data = $this->driver->setMultiple($real_values, $this->getNamespace(), $real_ttl);
202
203 8
        } catch (Exception $e) {
204
205
            $this->setState(self::CACHE_ERROR, $e->getMessage());
206
            $data = false;
207
208
        }
209
210 8
        return $data;
211
212
    }
213
214 8
    public function deleteMultiple($keys) {
215
216 8
        if ( !is_array($keys) && !($keys instanceof Traversable) ) {
217
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
218
        }
219
220 8
        foreach ( $keys as $key ) {
221 8
            if ( KeyValidator::validateKey($key) === false ) {
222
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
223
            }
224 8
        }
225
226
        try {
227
228 8
            $data = $this->driver->deleteMultiple($keys, $this->getNamespace());
229
230 8
        } catch (Exception $e) {
231
232
            $this->setState(self::CACHE_ERROR, $e->getMessage());
233
            $data = false;
234
235
        }
236
237 8
        return $data;
238
239
    }
240
241 30 View Code Duplication
    public function has($key) {
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...
242
243 30
        if ( KeyValidator::validateKey($key) === false ) {
244
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
245
        }
246
247
        try {
248
249 30
            $data = $this->driver->has($key, $this->getNamespace());
250
251 30
        } catch (Exception $e) {
252
253
            $this->setState(self::CACHE_ERROR, $e->getMessage());
254
            $data = false;
255
256
        }
257
258 30
        return $data;
259
260
    }
261
262
    abstract public function getStats();
263
264 7 View Code Duplication
    public function clearNamespace() {
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...
265
266
        try {
267
268 7
            $data = $this->driver->clear($this->getNamespace());
269
270 7
        } catch (Exception $e) {
271
272
            $this->setState(self::CACHE_ERROR, $e->getMessage());
273
            $data = false;
274
275
        }
276
277 7
        return $data;
278
279
    }
280
281 141 View Code Duplication
    public function test() {
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...
282
283 141
        if ( $this->driver->test() ) {
284
285 141
            $this->setState(self::CACHE_SUCCESS);
286
287 141
            return true;
288
289
        }
290
291
        $error = $this->driver->getName()." driver unavailable, disabling provider ".$this->getId()." administratively";
292
293
        $this->logger->error($error);
294
295
        $this->setState(self::CACHE_ERROR, $error);
296
297
        return false;
298
299
    }
300
301
}
302