Completed
Push — master ( 79d061...7993bb )
by Marco
06:18
created

AbstractEnhancedProvider::getProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 2
cts 2
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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\Foundation\Utils\ClassProperties;
7
use \Comodojo\Foundation\Utils\UniqueId;
8
use \Psr\Log\LoggerInterface;
9
use \Comodojo\Cache\Components\KeyValidator;
10
use \DateTime;
11
use \DateInterval;
12
use \Traversable;
13
use \Comodojo\Exception\SimpleCacheException;
14
use \Comodojo\Exception\InvalidSimpleCacheArgumentException;
15
use \Exception;
16
17
/**
18
 * Abstract stateful provider implementation
19
 *
20
 * @package     Comodojo Spare Parts
21
 * @author      Marco Giovinazzi <[email protected]>
22
 * @license     MIT
23
 *
24
 * LICENSE:
25
 *
26
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
 * THE SOFTWARE.
33
 */
34
35
abstract class AbstractEnhancedProvider
36
    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...
37
    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...
38
39
    use StatefulTrait;
40
    use NamespaceTrait;
41
42
    protected $driver;
43
44
    protected $default_properties = [];
45
46
    protected $properties;
47
48
    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...
49
50 143 View Code Duplication
    public function __construct(array $properties = [], LoggerInterface $logger = null) {
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...
51
52 143
        parent::__construct($logger);
53
54 143
        $this->properties = ClassProperties::create($this->default_properties)->merge($properties);
55
56 143
        $this->setId(UniqueId::generate(64));
57
58 143
    }
59
60 70
    public function getProperties() {
61
62 70
        return $this->properties;
63
64
    }
65
66 104
    public function get($key, $default = null) {
67
68 90
        if ( KeyValidator::validateKey($key) === false ) {
69
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
70
        }
71
72
        try {
73
74 90
            $data = $this->driver->get($key, $this->getNamespace());
75
76 104
        } catch (Exception $e) {
77
78
            $this->setState(self::CACHE_ERROR, $e->getMessage());
79
            $data = null;
80
81
        }
82
83 90
        if ( $data === null ) return $default;
84
85 61
        return unserialize($data);
86
87
    }
88
89 103
    public function set($key, $value, $ttl = null) {
90
91 103
        if ( KeyValidator::validateKey($key) === false ) {
92
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
93
        }
94
95 103
        if ( $value === null ) {
96 7
            throw new InvalidSimpleCacheArgumentException('Cannot cache a null value');
97
        }
98
99
        $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...
100
101 96 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...
102 22
        else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s');
103 22
        else $real_ttl = intval($ttl);
104
105
        try {
106
107 96
            $data = $this->driver->set($key, $this->getNamespace(), serialize($value), $real_ttl);
108
109 96
        } catch (Exception $e) {
110
111
            $this->setState(self::CACHE_ERROR, $e->getMessage());
112
            $data = false;
113
114
        }
115
116 96
        return $data;
117
118
    }
119
120 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...
121
122 15
        if ( KeyValidator::validateKey($key) === false ) {
123
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
124
        }
125
126
        try {
127
128 15
            $data = $this->driver->delete($key, $this->getNamespace());
129
130 15
        } catch (Exception $e) {
131
132
            $this->setState(self::CACHE_ERROR, $e->getMessage());
133
            $data = false;
134
135
        }
136
137 15
        return $data;
138
139
    }
140
141 7
    public function clear() {
142
143
        try {
144
145 7
            $data = $this->driver->clear();
146
147 7
        } catch (Exception $e) {
148
149
            $this->setState(self::CACHE_ERROR, $e->getMessage());
150
            $data = false;
151
152
        }
153
154 7
        return $data;
155
156
    }
157
158 8
    public function getMultiple($keys, $default = null) {
159
160 8
        if ( !is_array($keys) && !($keys instanceof Traversable) ) {
161
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
162
        }
163
164 8
        foreach ( $keys as $key ) {
165 8
            if ( KeyValidator::validateKey($key) === false ) {
166
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
167
            }
168 8
        }
169
170
        try {
171
172 8
            $data = $this->driver->getMultiple($keys, $this->getNamespace());
173
174 8
        } catch (Exception $e) {
175
176
            $this->setState(self::CACHE_ERROR, $e->getMessage());
177
            $data = array_combine($keys, array_fill(0, count($keys), null));
178
179
        }
180
181 8
        return array_map(function($value) use($default) {
182 8
            if ( $value === null ) return $default;
183 7
            return unserialize($value);
184 8
        }, $data);
185
186
    }
187
188 8
    public function setMultiple($values, $ttl = null) {
189
190 8
        if ( !is_array($values) && !($values instanceof Traversable) ) {
191
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
192
        }
193
194 8
        $real_values = [];
195
196 8
        foreach ( $values as $key => $value ) {
197 8
            if ( KeyValidator::validateKey($key) === false ) {
198
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
199
            }
200 8
            if ( $value === null ) {
201
                throw new InvalidSimpleCacheArgumentException('Cannot cache a null value');
202
            }
203 8
            $real_values[$key] = serialize($value);
204 8
        }
205
206
        $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...
207
208 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...
209
        else if ( $ttl instanceof DateInterval ) $real_ttl = $ttl->format('%s');
210
        else $real_ttl = intval($ttl);
211
212
        try {
213
214 8
            $data = $this->driver->setMultiple($real_values, $this->getNamespace(), $real_ttl);
215
216 8
        } catch (Exception $e) {
217
218
            $this->setState(self::CACHE_ERROR, $e->getMessage());
219
            $data = false;
220
221
        }
222
223 8
        return $data;
224
225
    }
226
227 8
    public function deleteMultiple($keys) {
228
229 8
        if ( !is_array($keys) && !($keys instanceof Traversable) ) {
230
            throw new InvalidSimpleCacheArgumentException('Invalid keys provided');
231
        }
232
233 8
        foreach ( $keys as $key ) {
234 8
            if ( KeyValidator::validateKey($key) === false ) {
235
                throw new InvalidSimpleCacheArgumentException('Invalid key provided');
236
            }
237 8
        }
238
239
        try {
240
241 8
            $data = $this->driver->deleteMultiple($keys, $this->getNamespace());
242
243 8
        } catch (Exception $e) {
244
245
            $this->setState(self::CACHE_ERROR, $e->getMessage());
246
            $data = false;
247
248
        }
249
250 8
        return $data;
251
252
    }
253
254 32 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...
255
256 32
        if ( KeyValidator::validateKey($key) === false ) {
257
            throw new InvalidSimpleCacheArgumentException('Invalid key provided');
258
        }
259
260
        try {
261
262 32
            $data = $this->driver->has($key, $this->getNamespace());
263
264 32
        } catch (Exception $e) {
265
266
            $this->setState(self::CACHE_ERROR, $e->getMessage());
267
            $data = false;
268
269
        }
270
271 32
        return $data;
272
273
    }
274
275
    abstract public function getStats();
276
277 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...
278
279
        try {
280
281 7
            $data = $this->driver->clear($this->getNamespace());
282
283 7
        } catch (Exception $e) {
284
285
            $this->setState(self::CACHE_ERROR, $e->getMessage());
286
            $data = false;
287
288
        }
289
290 7
        return $data;
291
292
    }
293
294 143 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...
295
296 143
        if ( $this->driver->test() ) {
297
298 143
            $this->setState(self::CACHE_SUCCESS);
299
300 143
            return true;
301
302
        }
303
304
        $error = $this->driver->getName()." driver unavailable, disabling provider ".$this->getId()." administratively";
305
306
        $this->logger->error($error);
307
308
        $this->setState(self::CACHE_ERROR, $error);
309
310
        return false;
311
312
    }
313
314
}
315