ArrayCollection   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 328
Duplicated Lines 6.1 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 20
loc 328
rs 8.8798
c 0
b 0
f 0
wmc 44
lcom 1
cbo 0

32 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A toArray() 0 4 1
A first() 0 4 1
A last() 0 4 1
A key() 0 4 1
A next() 0 4 1
A current() 0 4 1
A remove() 0 11 3
A removeElement() 0 12 2
A offsetExists() 0 4 1
A offsetGet() 0 4 1
A offsetSet() 0 10 2
A offsetUnset() 0 4 1
A containsKey() 0 4 2
A contains() 0 4 1
A exists() 10 10 3
A indexOf() 0 4 1
A get() 0 4 2
A getKeys() 0 4 1
A getValues() 0 4 1
A count() 0 4 1
A set() 0 4 1
A add() 0 6 1
A isEmpty() 0 4 1
A getIterator() 0 4 1
A map() 0 4 1
A filter() 0 4 1
A forAll() 10 10 3
A partition() 0 17 3
A __toString() 0 4 1
A clear() 0 4 1
A slice() 0 4 1

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

1
<?php
2
3
namespace Mailxpert\Model;
4
5
use ArrayIterator;
6
use Closure;
7
8
/**
9
 * Date: 19/08/15
10
 * Inspired from Doctrine ArrayCollection
11
 */
12
class ArrayCollection implements Collection
13
{
14
15
    /**
16
     * An array containing the entries of this collection.
17
     *
18
     * @var array
19
     */
20
    private $elements;
21
22
    /**
23
     * Initializes a new ArrayCollection.
24
     *
25
     * @param array $elements
26
     */
27
    public function __construct(array $elements = array())
28
    {
29
        $this->elements = $elements;
30
    }
31
32
    /**
33
     * {@inheritDoc}
34
     */
35
    public function toArray()
36
    {
37
        return $this->elements;
38
    }
39
40
    /**
41
     * {@inheritDoc}
42
     */
43
    public function first()
44
    {
45
        return reset($this->elements);
46
    }
47
48
    /**
49
     * {@inheritDoc}
50
     */
51
    public function last()
52
    {
53
        return end($this->elements);
54
    }
55
56
    /**
57
     * {@inheritDoc}
58
     */
59
    public function key()
60
    {
61
        return key($this->elements);
62
    }
63
64
    /**
65
     * {@inheritDoc}
66
     */
67
    public function next()
68
    {
69
        return next($this->elements);
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75
    public function current()
76
    {
77
        return current($this->elements);
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function remove($key)
84
    {
85
        if (!isset($this->elements[$key]) && !array_key_exists($key, $this->elements)) {
86
            return null;
87
        }
88
89
        $removed = $this->elements[$key];
90
        unset($this->elements[$key]);
91
92
        return $removed;
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     */
98
    public function removeElement($element)
99
    {
100
        $key = array_search($element, $this->elements, true);
101
102
        if ($key === false) {
103
            return false;
104
        }
105
106
        unset($this->elements[$key]);
107
108
        return true;
109
    }
110
111
    /**
112
     * Required by interface ArrayAccess.
113
     *
114
     * {@inheritDoc}
115
     */
116
    public function offsetExists($offset)
117
    {
118
        return $this->containsKey($offset);
119
    }
120
121
    /**
122
     * Required by interface ArrayAccess.
123
     *
124
     * {@inheritDoc}
125
     */
126
    public function offsetGet($offset)
127
    {
128
        return $this->get($offset);
129
    }
130
131
    /**
132
     * Required by interface ArrayAccess.
133
     *
134
     * {@inheritDoc}
135
     */
136
    public function offsetSet($offset, $value)
137
    {
138
        if (!isset($offset)) {
139
            return $this->add($value);
140
        }
141
142
        $this->set($offset, $value);
143
144
        return true;
145
    }
146
147
    /**
148
     * Required by interface ArrayAccess.
149
     *
150
     * {@inheritDoc}
151
     */
152
    public function offsetUnset($offset)
153
    {
154
        return $this->remove($offset);
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    public function containsKey($key)
161
    {
162
        return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
163
    }
164
165
    /**
166
     * {@inheritDoc}
167
     */
168
    public function contains($element)
169
    {
170
        return in_array($element, $this->elements, true);
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     */
176 View Code Duplication
    public function exists(Closure $p)
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...
177
    {
178
        foreach ($this->elements as $key => $element) {
179
            if ($p($key, $element)) {
180
                return true;
181
            }
182
        }
183
184
        return false;
185
    }
186
187
    /**
188
     * {@inheritDoc}
189
     */
190
    public function indexOf($element)
191
    {
192
        return array_search($element, $this->elements, true);
193
    }
194
195
    /**
196
     * {@inheritDoc}
197
     */
198
    public function get($key)
199
    {
200
        return isset($this->elements[$key]) ? $this->elements[$key] : null;
201
    }
202
203
    /**
204
     * {@inheritDoc}
205
     */
206
    public function getKeys()
207
    {
208
        return array_keys($this->elements);
209
    }
210
211
    /**
212
     * {@inheritDoc}
213
     */
214
    public function getValues()
215
    {
216
        return array_values($this->elements);
217
    }
218
219
    /**
220
     * {@inheritDoc}
221
     */
222
    public function count()
223
    {
224
        return count($this->elements);
225
    }
226
227
    /**
228
     * {@inheritDoc}
229
     */
230
    public function set($key, $value)
231
    {
232
        $this->elements[$key] = $value;
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     */
238
    public function add($value)
239
    {
240
        $this->elements[] = $value;
241
242
        return true;
243
    }
244
245
    /**
246
     * {@inheritDoc}
247
     */
248
    public function isEmpty()
249
    {
250
        return empty($this->elements);
251
    }
252
253
    /**
254
     * Required by interface IteratorAggregate.
255
     *
256
     * {@inheritDoc}
257
     */
258
    public function getIterator()
259
    {
260
        return new ArrayIterator($this->elements);
261
    }
262
263
    /**
264
     * {@inheritDoc}
265
     */
266
    public function map(Closure $func)
267
    {
268
        return new static(array_map($func, $this->elements));
269
    }
270
271
    /**
272
     * {@inheritDoc}
273
     */
274
    public function filter(Closure $p)
275
    {
276
        return new static(array_filter($this->elements, $p));
277
    }
278
279
    /**
280
     * {@inheritDoc}
281
     */
282 View Code Duplication
    public function forAll(Closure $p)
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...
283
    {
284
        foreach ($this->elements as $key => $element) {
285
            if (!$p($key, $element)) {
286
                return false;
287
            }
288
        }
289
290
        return true;
291
    }
292
293
    /**
294
     * {@inheritDoc}
295
     */
296
    public function partition(Closure $p)
297
    {
298
        $matches = $noMatches = array();
299
300
        foreach ($this->elements as $key => $element) {
301
            if ($p($key, $element)) {
302
                $matches[$key] = $element;
303
            } else {
304
                $noMatches[$key] = $element;
305
            }
306
        }
307
308
        return [
309
            new static($matches),
310
            new static($noMatches),
311
        ];
312
    }
313
314
    /**
315
     * Returns a string representation of this object.
316
     *
317
     * @return string
318
     */
319
    public function __toString()
320
    {
321
        return __CLASS__.'@'.spl_object_hash($this);
322
    }
323
324
    /**
325
     * {@inheritDoc}
326
     */
327
    public function clear()
328
    {
329
        $this->elements = array();
330
    }
331
332
    /**
333
     * {@inheritDoc}
334
     */
335
    public function slice($offset, $length = null)
336
    {
337
        return array_slice($this->elements, $offset, $length, true);
338
    }
339
}
340