Completed
Push — master ( 747a6a...c6c655 )
by Ítalo
02:55
created

CommonContainerMethodsTrait   F

Complexity

Total Complexity 59

Size/Duplication

Total Lines 394
Duplicated Lines 12.69 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 59
c 1
b 0
f 0
lcom 1
cbo 21
dl 50
loc 394
rs 1.9075

35 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultComparer() 0 8 2
A setDefaultComparer() 0 6 1
A __toString() 0 4 1
A equals() 0 4 1
A serialize() 0 4 1
A unserialize() 0 6 1
A jsonSerialize() 0 4 1
A toValuesArray() 13 13 3
A toKeysArray() 0 9 2
A toArray() 13 13 3
A fromArray() 0 13 3
A toVector() 0 4 1
A toImmVector() 0 4 1
A toSet() 0 4 1
A toImmSet() 0 4 1
A toMap() 0 4 1
A toImmMap() 0 4 1
A map() 0 4 1
A mapWithKey() 0 4 1
A filter() 0 4 1
A filterWithKey() 0 4 1
A zip() 12 12 3
A take() 0 8 2
A takeWhile() 0 4 1
A skip() 0 8 2
A skipWhile() 0 4 1
A slice() 0 11 3
A first() 0 8 2
A last() 0 10 2
A each() 0 8 2
A exists() 0 10 3
A concatAll() 12 12 1
A groupBy() 0 16 4
A indexBy() 0 10 2
A reduce() 0 8 2

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 CommonContainerMethodsTrait 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 CommonContainerMethodsTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Collections\Traits;
4
5
use Collections\ArrayList;
6
use Collections\Comparer\NumericKeyComparer;
7
use Collections\Dictionary;
8
use Collections\Generic\ComparerInterface;
9
use Collections\Immutable\ImmArrayList;
10
use Collections\Immutable\ImmDictionary;
11
use Collections\Immutable\ImmSet;
12
use Collections\Iterable;
13
use Collections\Iterator\LazyFilterIterable;
14
use Collections\Iterator\LazyFilterKeyedIterable;
15
use Collections\Iterator\LazyMapIterable;
16
use Collections\Iterator\LazyMapWithKeyIterable;
17
use Collections\Iterator\LazySkipIterable;
18
use Collections\Iterator\LazySkipWhileIterable;
19
use Collections\Iterator\LazySliceIterable;
20
use Collections\Iterator\LazyTakeIterable;
21
use Collections\Iterator\LazyTakeWhileIterable;
22
use Collections\Iterator\LazyZipIterable;
23
use Collections\Pair;
24
use Collections\Set;
25
use Collections\VectorInterface;
26
27
trait CommonContainerMethodsTrait
28
{
29
    use GuardTrait;
30
    /**
31
     * @var ComparerInterface
32
     */
33
    private $defaultComparer;
34
35
    /**
36
     * Gets the default comparer for this collection
37
     * @return ComparerInterface
38
     */
39
    public function getDefaultComparer()
40
    {
41
        if ($this->defaultComparer === null) {
42
            $this->defaultComparer = new NumericKeyComparer();
43
        }
44
45
        return $this->defaultComparer;
46
    }
47
48
    /**
49
     * Sets the default comparer for this collection
50
     * @param ComparerInterface $defaultComparer
51
     * @return $this
52
     */
53
    public function setDefaultComparer(ComparerInterface $defaultComparer)
54
    {
55
        $this->defaultComparer = $defaultComparer;
56
57
        return $this;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function __toString()
64
    {
65
        return get_class($this);
66
    }
67
68
    public function equals($obj)
69
    {
70
        return ($obj === $this);
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76
    public function serialize()
77
    {
78
        return serialize($this->container);
0 ignored issues
show
Bug introduced by
The property container does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function unserialize($serialized)
85
    {
86
        $this->container = unserialize($serialized);
87
88
        return $this->container;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function jsonSerialize()
95
    {
96
        return $this->container;
97
    }
98
99
    /**
100
     * @return array
101
     */
102 View Code Duplication
    public function toValuesArray()
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...
103
    {
104
        $arr = [];
105
        foreach ($this as $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
106
            if ($value instanceof Iterable) {
107
                $arr[] = $value->toArray();
108
            } else {
109
                $arr[] = $value;
110
            }
111
        }
112
113
        return $arr;
114
    }
115
116
    public function toKeysArray()
117
    {
118
        $res = [];
119
        foreach ($this as $k => $_) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
120
            $res[] = $k;
121
        }
122
123
        return $res;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 View Code Duplication
    public function toArray()
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...
130
    {
131
        $arr = [];
132
        foreach ($this as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
133
            if ($value instanceof Iterable) {
134
                $arr[$key] = $value->toArray();
135
            } else {
136
                $arr[$key] = $value;
137
            }
138
        }
139
140
        return $arr;
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public static function fromArray(array $arr)
147
    {
148
        $map = new static();
149
        foreach ($arr as $k => $v) {
150
            if (is_array($v)) {
151
                $map[$k] = new static($v);
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with $v.

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...
152
            } else {
153
                $map[$k] = $v;
154
            }
155
        }
156
157
        return $map;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function toVector()
164
    {
165
        return new ArrayList($this);
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function toImmVector()
172
    {
173
        return new ImmArrayList($this);
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function toSet()
180
    {
181
        return new Set($this);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    public function toImmSet()
188
    {
189
        return new ImmSet($this);
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195
    public function toMap()
196
    {
197
        return new Dictionary($this);
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203
    public function toImmMap()
204
    {
205
        return new ImmDictionary($this);
206
    }
207
208
    /**
209
     * {@inheritDoc}
210
     * @return $this
211
     */
212
    public function map(callable $callable)
213
    {
214
        return new static(new LazyMapIterable($this, $callable));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callable).

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...
215
    }
216
217
    /**
218
     * {@inheritDoc}
219
     * @return $this
220
     */
221
    public function mapWithKey($callback)
222
    {
223
        return new static(new LazyMapWithKeyIterable($this, $callback));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callback).

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...
224
    }
225
226
    /**
227
     * {@inheritDoc}
228
     * @return $this
229
     */
230
    public function filter(callable $callable)
231
    {
232
        return new static(new LazyFilterIterable($this, $callable));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callable).

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...
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     * @return $this
238
     */
239
    public function filterWithKey($callback)
240
    {
241
        return new static(new LazyFilterKeyedIterable($this, $callback));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callback).

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...
242
    }
243
244
    /**
245
     * {@inheritDoc}
246
     * @return $this
247
     */
248 View Code Duplication
    public function zip(Iterable $iterable)
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...
249
    {
250
        if (is_array($iterable)) {
251
            $iterable = new ImmArrayList($iterable);
252
        }
253
254
        if ($iterable instanceof \Traversable) {
255
            return new static(new LazyZipIterable($this, $iterable));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $iterable).

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...
256
        } else {
257
            throw new \InvalidArgumentException('Parameter must be an array or an instance of Traversable');
258
        }
259
    }
260
261
    /**
262
     * {@inheritDoc}
263
     * @return $this
264
     */
265
    public function take($size = 1)
266
    {
267
        if (!is_int($size)) {
268
            throw new \InvalidArgumentException('Parameter n must be an integer');
269
        }
270
271
        return new static(new LazyTakeIterable($this, $size));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...eIterable($this, $size).

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...
272
    }
273
274
    public function takeWhile(callable $callable)
275
    {
276
        return new static(new LazyTakeWhileIterable($this, $callable));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callable).

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...
277
    }
278
279
    public function skip($n)
280
    {
281
        if (!is_int($n)) {
282
            throw new \InvalidArgumentException('Parameter n must be an integer');
283
        }
284
285
        return new static(new LazySkipIterable($this, $n));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...SkipIterable($this, $n).

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...
286
    }
287
288
    public function skipWhile(callable $callable)
289
    {
290
        return new static(new LazySkipWhileIterable($this, $callable));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...rable($this, $callable).

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...
291
    }
292
293
    public function slice($start, $length)
294
    {
295
        if ($start < 0) {
296
            throw new \InvalidArgumentException('Parameter start must be a non-negative integer');
297
        }
298
        if ($length < 0) {
299
            throw new \InvalidArgumentException('Parameter len must be a non-negative integer');
300
        }
301
302
        return new static(new LazySliceIterable($this, $start, $length));
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with new \Collections\Iterato...$this, $start, $length).

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...
303
    }
304
305
    /**
306
     * {@inheritDoc}
307
     * @return $this
308
     */
309
    public function first()
310
    {
311
        if ($this->isEmpty()) {
312
            return null;
313
        }
314
315
        return current($this->container);
316
    }
317
318
    /**
319
     * {@inheritDoc}
320
     * @return $this
321
     */
322
    public function last()
323
    {
324
        if ($this->isEmpty()) {
325
            return null;
326
        }
327
328
        $lastItem = array_slice($this->container, -1, 1);
329
330
        return current($lastItem);
331
    }
332
333
    /**
334
     * {@inheritDoc}
335
     * @return $this
336
     */
337
    public function each(callable $callable)
338
    {
339
        foreach ($this as $v) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
340
            $callable($v);
341
        }
342
343
        return $this;
344
    }
345
346
    /**
347
     * {@inheritdoc}
348
     */
349
    public function exists(callable $fn)
350
    {
351
        foreach ($this as $element) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
352
            if ($fn($element)) {
353
                return true;
354
            }
355
        }
356
357
        return false;
358
    }
359
360 View Code Duplication
    public function concatAll()
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...
361
    {
362
        /** @var VectorInterface $results */
363
        $results = new static();
364
        $this->each(function (Iterable $subArray) use ($results) {
365
            $subArray->each(function ($item) use ($results) {
366
                $results->add($item);
367
            });
368
        });
369
370
        return $results;
371
    }
372
373
    /**
374
     * {@inheritDoc}
375
     * @return $this
376
     */
377
    public function groupBy($callback)
378
    {
379
        $group = new Dictionary();
380
        foreach ($this as $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
381
            $key = $callback($value);
382
            if (!$group->containsKey($key)) {
383
                $element = $this instanceof VectorInterface ? new static([$value]) : new ArrayList([$value]);
0 ignored issues
show
Unused Code introduced by
The call to CommonContainerMethodsTrait::__construct() has too many arguments starting with array($value).

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...
384
                $group->add(new Pair($key, $element));
385
            } else {
386
                $value = $group->get($key)->add($value);
387
                $group->set($key, $value);
388
            }
389
        }
390
391
        return $group;
392
    }
393
394
    /**
395
     * {@inheritDoc}
396
     * @return $this
397
     */
398
    public function indexBy($callback)
399
    {
400
        $group = new Dictionary();
401
        foreach ($this as $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
402
            $key = $callback($value);
403
            $group->set($key, $value);
404
        }
405
406
        return $group;
407
    }
408
409
    /**
410
     * {@inheritdoc}
411
     */
412
    public function reduce(callable $callback, $initial = null)
413
    {
414
        foreach ($this as $element) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Collections\Traits\...nContainerMethodsTrait> is not traversable.
Loading history...
415
            $initial = $callback($initial, $element);
416
        }
417
418
        return $initial;
419
    }
420
}
421