Completed
Push — 2.0 ( 8b0753...eaa66b )
by Marco
04:57
created

Manager::deleteMultiple()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 8

Duplication

Lines 19
Ratio 100 %

Code Coverage

Tests 7
CRAP Score 5.0488

Importance

Changes 0
Metric Value
dl 19
loc 19
ccs 7
cts 8
cp 0.875
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 8
nc 4
nop 1
crap 5.0488
1
<?php namespace Comodojo\SimpleCache;
2
3
use \Comodojo\SimpleCache\Providers\AbstractProvider;
4
use \Comodojo\SimpleCache\Providers\Vacuum;
5
use \Comodojo\SimpleCache\Interfaces\SimpleCacheManagerInterface;
6
use \Comodojo\SimpleCache\Interfaces\EnhancedSimpleCacheInterface;
7
use \Comodojo\Cache\Traits\NamespaceTrait;
8
use \Comodojo\Cache\Traits\GenericManagerTrait;
9
use \Comodojo\SimpleCache\Components\StackManager;
10
use \Comodojo\Foundation\Validation\DataFilter;
11
use \Comodojo\SimpleCache\Components\ConfigurationParser;
12
use \Comodojo\Foundation\Base\Configuration;
13
use \Psr\Log\LoggerInterface;
14
use \ArrayObject;
15
16
/**
17
 * @package     Comodojo Cache
18
 * @author      Marco Giovinazzi <[email protected]>
19
 * @license     MIT
20
 *
21
 * LICENSE:
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
 * THE SOFTWARE.
30
 */
31
32
class Manager extends AbstractProvider implements SimpleCacheManagerInterface {
33
34
    use NamespaceTrait, GenericManagerTrait {
35
        GenericManagerTrait::setNamespace insteadof NamespaceTrait;
36
    }
37
38
    const DEFAULT_PICK_MODE = 1;
39
40
    protected $pick_mode;
41
42
    protected $stack;
43
44
    protected $align_cache;
45
46
    protected $vacuum;
47
48
    protected $selected;
49
50 35 View Code Duplication
    public function __construct(
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
        $pick_mode = null,
52
        LoggerInterface $logger = null,
53
        $align_cache = true,
54
        $flap_interval = null
55
    ) {
56
57 35
        $this->pick_mode = DataFilter::filterInteger($pick_mode, 1, 6, self::DEFAULT_PICK_MODE);
0 ignored issues
show
Documentation introduced by
1 is of type integer, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
58
59 35
        $this->align_cache = DataFilter::filterBoolean($align_cache, false);
0 ignored issues
show
Documentation introduced by
$align_cache is of type boolean, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
60
61 35
        $stack = new ArrayObject([]);
62
63 35
        $this->stack = new StackManager($stack->getIterator());
64 35
        $this->stack->setFlapInterval($flap_interval);
65
66 35
        parent::__construct($logger);
67
68 35
        $this->vacuum = new Vacuum([], $this->logger);
69
70 35
        $this->logger->debug("SimpleCache Manager online; pick mode ".$this->pick_mode);
71
72 35
    }
73
74 34
    public function addProvider(EnhancedSimpleCacheInterface $provider, $weight = 0) {
75
76 34
        return $this->genericAddProvider($provider, $weight);
77
78
    }
79
80 24
    public function get($key, $default = null) {
81
82 24
        return $this->selectFrom('GET', $key, $default);
83
84
    }
85
86 30
    public function set($key, $value, $ttl = null) {
87
88 30
        if ( iterator_count($this->stack) == 0 ) return $this->vacuum->set($key, $value, $ttl);
89
90 29
        if ( $this->align_cache === false && $this->pick_mode < 5 ) {
91 1
            return $this->selectProvider()->set($key, $value, $ttl);
92
        }
93
94 28
        $result = [];
95
96 28
        foreach ( $this->stack as $provider ) {
97
98 28
            $pro = $provider[0];
99
100 28
            $provider_result = $pro->set($key, $value, $ttl);
101
102 27
            $this->logger->debug("Saving item $key into provider ".
103 27
                $pro->getId().": ".($provider_result ? "OK" : "NOK - ".$pro->getStateMessage()));
104
105 27
            $result[] = $provider_result;
106
107
        }
108
109 27
        return !in_array(false, $result);
110
111
    }
112
113 3 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...
114
115 3
        if ( iterator_count($this->stack) == 0 ) return $this->vacuum->delete($key);
116
117 2
        if ( $this->align_cache === false && $this->pick_mode < 5 ) {
118
            return $this->selectProvider()->delete($key);
119
        }
120
121 2
        $result = [];
122
123 2
        foreach ( $this->stack as $provider ) {
124
125 2
            $result[] = $provider[0]->delete($key);
126
127
        }
128
129 2
        return !in_array(false, $result);
130
131
    }
132
133 2
    public function getMultiple($keys, $default = null) {
134
135 2
        return $this->selectFrom('GETMULTIPLE', $keys, $default);
136
137
    }
138
139 2
    public function setMultiple($values, $ttl = null) {
140
141 2
        if ( iterator_count($this->stack) == 0 ) return $this->vacuum->setMultiple($values, $ttl);
142
143 1
        if ( $this->align_cache === false && $this->pick_mode < 5 ) {
144
            return $this->selectProvider()->setMultiple($values, $ttl);
145
        }
146
147 1
        $result = [];
148
149 1
        foreach ( $this->stack as $provider ) {
150
151 1
            $result[] = $provider[0]->setMultiple($values, $ttl);
152
153
        }
154
155 1
        return !in_array(false, $result);
156
157
    }
158
159 2 View Code Duplication
    public function deleteMultiple($keys) {
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...
160
161 2
        if ( iterator_count($this->stack) == 0 ) return $this->vacuum->deleteMultiple($keys);
162
163 1
        if ( $this->align_cache === false && $this->pick_mode < 5 ) {
164
            return $this->selectProvider()->deleteMultiple($keys);
165
        }
166
167 1
        $result = [];
168
169 1
        foreach ( $this->stack as $provider ) {
170
171 1
            $result[] = $provider[0]->deleteMultiple($keys);
172
173
        }
174
175 1
        return !in_array(false, $result);
176
177
    }
178
179 18
    public function has($key) {
180
181 18
        return $this->selectFrom('HAS', $key);
182
183
    }
184
185 1 View Code Duplication
    public static function createFromConfiguration(Configuration $configuration, LoggerInterface $logger, $stanza = 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...
186
187 1
        list($enable, $manager_configuration, $providers) = ConfigurationParser::parse($configuration, $logger, $stanza);
188
189 1
        $manager = new Manager(...$manager_configuration);
190
191 1
        if ( $enable ) {
192 1
            foreach ( $providers as $name => $provider ) {
193 1
                $instance = $provider->instance;
194 1
                $weight = $provider->weight;
195 1
                $id = $instance->getId();
196 1
                $logger->debug("Adding provider $name ($id) to cache manager (w $weight)");
197 1
                $manager->addProvider($instance, $weight);
198
            }
199
        }
200
201 1
        return $manager;
202
203
    }
204
205 30
    protected function selectFrom($mode, $key, $default = null) {
206
207 30 View Code Duplication
        if ( $this->pick_mode < 5 ) {
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...
208
209 28
            $result = $this->fromSingleProvider($mode, $key, $default);
210
211 2
        } else if ( $this->pick_mode == 5 ) {
212
213 1
            $result = $this->fromAllProviders($mode, $key, $default);
214
215
        } else {
216
217 1
            $result = $this->traverse($mode, $key, $default);
218
219
        }
220
221 30
        return $result;
222
223
    }
224
225 28
    protected function fromSingleProvider($mode, $key, $default) {
226
227 28
        $provider = $this->selectProvider();
228
229
        switch ( $mode ) {
230
231 28
            case 'GET':
232 23
                $data = $provider->get($key, $default);
233 23
                break;
234
235 17
            case 'GETMULTIPLE':
236 2
                $data = $provider->getMultiple($key, $default);
237 2
                break;
238
239 16
            case 'HAS':
240 16
                $data = $provider->has($key);
241 16
                break;
242
243
        }
244
245 28
        return $data;
0 ignored issues
show
Bug introduced by
The variable $data does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
246
247
    }
248
249 1
    protected function fromAllProviders($mode, $key, $default) {
250
251 1
        $result = [];
252
253 1
        if ( $mode == 'GET' ) {
254
255 1
            foreach ( $this->stack as $provider ) {
256
257 1
                $result[] = $provider[0]->get($key, $default);
258
259
                // selected provider has no sense in this case
260 1
                $this->selected = $provider[0];
261
262
            }
263
264 1
            if ( count(array_unique($result)) == 1 ) return $result[0];
265
266 1
            return $default;
267
268 1
        } else if ( $mode == 'GETMULTIPLE' ) {
269
270
            foreach ( $this->stack as $provider ) {
271
272
                $result[] = $provider[0]->getMultiple($key, $default);
273
274
                // selected provider has no sense in this case
275
                $this->selected = $provider[0];
276
277
            }
278
279
            if ( count(array_unique($result)) == 1 ) return $result[0];
280
281
            $this->selected = $this->vacuum;
282
283
            return $this->vacuum->getMultiple($key, $default);
284
285
            // return array_combine($key, array_fill(0, count($key), $default));
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% 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...
286
287 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...
288
289 1
            foreach ( $this->stack as $provider ) {
290
291 1
                $result[] = $provider[0]->has($key);
292
293
                // selected provider has no sense in this case
294 1
                $this->selected = $provider[0];
295
296
            }
297
298 1
            return !in_array(false, $result);
299
300
        }
301
302
    }
303
304 1
    protected function traverse($mode, $key, $default) {
305
306 1
        $this->stack->rewind();
307
308 1
        if ( $mode == 'GET' ) {
309
310
            foreach ( $this->stack as $provider ) {
311
312
                $item = $provider[0]->get($key);
313
314
                if ( $item !== null ) {
315
316
                    // selected provider
317
                    $this->selected = $provider[0];
318
319
                    return $item;
320
321
                }
322
323
            }
324
325
            // selected provider has no sense in this case
326
            $this->selected = $this->vacuum;
327
328
            return $default;
329
330 1
        } else if ( $mode == 'GETMULTIPLE' ) {
331
332
            foreach ( $this->stack as $provider ) {
333
334
                $items = $provider[0]->getMultiple($key);
335
336
                $item_unique = array_unique($items);
337
338
                if ( count($item_unique) > 1 && $item_unique[0] !== null ) {
339
340
                    // selected provider
341
                    $this->selected = $provider[0];
342
343
                    return $items;
344
345
                }
346
347
            }
348
349
            // selected provider has no sense in this case
350
            $this->selected = $this->vacuum;
351
352
            return $this->vacuum->getMultiple($key, $default);
353
354 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...
355
356 1
            foreach ( $this->stack as $provider ) {
357
358 1
                $item = $provider[0]->has($key);
359
360 1
                if ( $item === true ) {
361
362
                    // selected provider has no sense in this case
363 1
                    $this->selected = $provider[0];
364
365 1
                    return true;
366
367
                }
368
369
            }
370
371
            // selected provider has no sense in this case
372
            $this->selected = $this->vacuum;
373
374
            return false;
375
376
        }
377
378
    }
379
380
}
381