Completed
Push — 2.0 ( a52f91...c9f4d8 )
by Marco
12:16
created

Manager   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 321
Duplicated Lines 38.63 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 47
lcom 1
cbo 7
dl 124
loc 321
rs 8.439
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 23 23 1
A addProvider() 0 5 1
A get() 0 5 1
B set() 0 24 5
A delete() 17 17 4
A getMultiple() 0 5 1
A setMultiple() 17 17 4
A deleteMultiple() 17 17 4
A has() 0 5 1
A selectFrom() 13 19 3
B fromSingleProvider() 0 23 4
B fromAllProviders() 14 54 8
C traverse() 23 75 10

How to fix   Duplicated Code    Complexity   

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Manager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Manager, and based on these observations, apply Extract Interface, too.

1
<?php namespace Comodojo\SimpleCache;
2
3
use \Comodojo\SimpleCache\Providers\AbstractProvider;
4
use \Comodojo\SimpleCache\Providers\Void;
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 \Psr\Cache\CacheItemInterface; ???
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% 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...
12
use \Psr\Log\LoggerInterface;
13
use \ArrayObject;
14
15
/**
16
 *
17
 * @package     Comodojo Spare Parts
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 $void;
47
48
    protected $selected;
49
50 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
        $this->pick_mode = DataFilter::filterInteger($pick_mode, 1, 6, self::DEFAULT_PICK_MODE);
58
59
        $this->align_cache = DataFilter::filterBoolean($align_cache, true);
60
61
        $stack = new ArrayObject([]);
62
63
        $this->stack = new StackManager($stack->getIterator());
64
        $this->stack->setFlapInterval($flap_interval);
65
66
        parent::__construct($logger);
67
68
        $this->void = new Void($this->logger);
69
70
        $this->logger->info("SimpleCache Manager online; pick mode ".$this->pick_mode);
71
72
    }
73
74
    public function addProvider(EnhancedSimpleCacheInterface $provider, $weight = 0) {
75
76
        return $this->genericAddProvider($provider, $weight);
77
78
    }
79
80
    public function get($key, $default = null) {
81
82
        return $this->selectFrom('GET', $key, $default);
83
84
    }
85
86
    public function set($key, $value, $ttl = null) {
87
88
        if ( $this->align_cache === false && $this->pick_mode < 5) {
89
            return $this->selectProvider()->set($key, $value, $ttl);
90
        }
91
92
        $result = [];
93
94
        foreach ($this->stack as $provider) {
95
96
            $pro = $provider[0];
97
98
            $provider_result = $pro->set($key, $value, $ttl);
99
100
            $this->logger->debug("Saving item $key into provider ".
101
                $pro->getId().": ".($provider_result ? "OK" : "NOK - ".$pro->getStateMessage()));
102
103
            $result[] = $provider_result;
104
105
        }
106
107
        return !in_array(false, $result);
108
109
    }
110
111 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...
112
113
        if ( $this->align_cache === false && $this->pick_mode < 5) {
114
            return $this->selectProvider()->delete($key);
115
        }
116
117
        $result = [];
118
119
        foreach ($this->stack as $provider) {
120
121
            $result[] = $provider[0]->delete($key);
122
123
        }
124
125
        return !in_array(false, $result);
126
127
    }
128
129
    public function getMultiple($keys, $default = null) {
130
131
        return $this->selectFrom('GETMULTIPLE', $keys, $default);
132
133
    }
134
135 View Code Duplication
    public function setMultiple($values, $ttl = 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...
136
137
        if ( $this->align_cache === false && $this->pick_mode < 5) {
138
            return $this->selectProvider()->setMultiple($values, $ttl);
139
        }
140
141
        $result = [];
142
143
        foreach ($this->stack as $provider) {
144
145
            $result[] = $provider[0]->setMultiple($values, $ttl);
146
147
        }
148
149
        return !in_array(false, $result);
150
151
    }
152
153 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...
154
155
        if ( $this->align_cache === false && $this->pick_mode < 5) {
156
            return $this->selectProvider()->deleteMultiple($keys);
157
        }
158
159
        $result = [];
160
161
        foreach ($this->stack as $provider) {
162
163
            $result[] = $provider[0]->deleteMultiple($keys);
164
165
        }
166
167
        return !in_array(false, $result);
168
169
    }
170
171
    public function has($key) {
172
173
        return $this->selectFrom('HAS', $key);
174
175
    }
176
177
    protected function selectFrom($mode, $key, $default=null) {
178
179 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...
180
181
            $result = $this->fromSingleProvider($mode, $key, $default);
182
183
        } else if ( $this->pick_mode == 5 ) {
184
185
            $result = $this->fromAllProviders($mode, $key, $default);
186
187
        } else {
188
189
            $result = $this->traverse($mode, $key, $default);
190
191
        }
192
193
        return $result;
194
195
    }
196
197
    protected function fromSingleProvider($mode, $key, $default) {
198
199
        $provider = $this->selectProvider();
200
201
        switch ($mode) {
202
203
            case 'GET':
204
                $data = $provider->get($key, $default);
205
                break;
206
207
            case 'GETMULTIPLE':
208
                $data = $provider->getMultiple($key, $default);
209
                break;
210
211
            case 'HAS':
212
                $data = $provider->has($key);
213
                break;
214
215
        }
216
217
        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...
218
219
    }
220
221
    protected function fromAllProviders($mode, $key, $default) {
222
223
        $result = [];
224
225
        if ( $mode == 'GET' ) {
226
227
            foreach ($this->stack as $provider) {
228
229
                $result[] = $provider[0]->get($key, $default);
230
231
                // selected provider has no sense in this case
232
                $this->selected = $provider[0];
233
234
            }
235
236
            if ( count(array_unique($result)) == 1 ) return $result[0];
237
238
            return $default;
239
240
        } else if ( $mode == 'GETMULTIPLE' ) {
241
242
            foreach ($this->stack as $provider) {
243
244
                $result[] = $provider[0]->getMultiple($key, $default);
245
246
                // selected provider has no sense in this case
247
                $this->selected = $provider[0];
248
249
            }
250
251
            if ( count(array_unique($result)) == 1 ) return $result[0];
252
253
            $this->selected = $this->void;
254
255
            return $this->void->getMultiple($key, $default);
256
257
            // 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...
258
259 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...
260
261
            foreach ($this->stack as $provider) {
262
263
                $result[] = $provider[0]->has($key);
264
265
                // selected provider has no sense in this case
266
                $this->selected = $provider[0];
267
268
            }
269
270
            return !in_array(false, $result);
271
272
        }
273
274
    }
275
276
    protected function traverse($mode, $key, $default) {
277
278
        $this->stack->rewind();
279
280
        if ( $mode == 'GET' ) {
281
282
            foreach ($this->stack as $provider) {
283
284
                $item = $provider[0]->get($key);
285
286
                if ( $item !== null ) {
287
288
                    // selected provider
289
                    $this->selected = $provider[0];
290
291
                    return $item;
292
293
                }
294
295
            }
296
297
            // selected provider has no sense in this case
298
            $this->selected = $this->void;
299
300
            return $default;
301
302
        } else if ( $mode == 'GETMULTIPLE' ) {
303
304
            foreach ($this->stack as $provider) {
305
306
                $items = $provider[0]->getMultiple($key);
307
308
                $item_unique = array_unique($items);
309
310
                if ( count($item_unique) > 1 && $item_unique[0] !== null ) {
311
312
                    // selected provider
313
                    $this->selected = $provider[0];
314
315
                    return $items;
316
317
                }
318
319
            }
320
321
            // selected provider has no sense in this case
322
            $this->selected = $this->void;
323
324
            return $this->void->getMultiple($key, $default);
325
326 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...
327
328
            foreach ($this->stack as $provider) {
329
330
                $item = $provider[0]->has($key);
331
332
                if ( $item === true ) {
333
334
                    // selected provider has no sense in this case
335
                    $this->selected = $provider[0];
336
337
                    return true;
338
339
                }
340
341
            }
342
343
            // selected provider has no sense in this case
344
            $this->selected = $this->void;
345
346
            return false;
347
348
        }
349
350
    }
351
352
}
353