Complex classes like CollectionTrait 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 CollectionTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | trait CollectionTrait |
||
9 | { |
||
10 | /** |
||
11 | * @return array |
||
12 | */ |
||
13 | 57 | public function toArray() |
|
17 | |||
18 | /** |
||
19 | * Returns a lazy collection of items for which $function returned true. |
||
20 | * |
||
21 | * @param callable $function ($value, $key) |
||
22 | * @return Collection |
||
23 | */ |
||
24 | 1 | public function filter(callable $function) |
|
28 | |||
29 | /** |
||
30 | * Returns a lazy collection of distinct items. The comparison is the same as in in_array. |
||
31 | * |
||
32 | * @return Collection |
||
33 | */ |
||
34 | 1 | public function distinct() |
|
38 | |||
39 | /** |
||
40 | * Returns a lazy collection with items from all $collections passed as argument appended together |
||
41 | * |
||
42 | * @param Traversable|array ...$collections |
||
43 | * @return Collection |
||
44 | */ |
||
45 | 1 | public function concat(...$collections) |
|
49 | |||
50 | /** |
||
51 | * Returns collection where each item is changed to the output of executing $function on each key/item. |
||
52 | * |
||
53 | * @param callable $function |
||
54 | * @return Collection |
||
55 | */ |
||
56 | 7 | public function map(callable $function) |
|
60 | |||
61 | /** |
||
62 | * Reduces the collection to single value by iterating over the collection and calling $function while |
||
63 | * passing $startValue and current key/item as parameters. The output of $function is used as $startValue in |
||
64 | * next iteration. The output of $function on last element is the return value of this function. |
||
65 | * |
||
66 | * @param mixed $startValue |
||
67 | * @param callable $function ($tmpValue, $value, $key) |
||
68 | * @return mixed |
||
69 | */ |
||
70 | 2 | public function reduce(callable $function, $startValue) |
|
76 | |||
77 | /** |
||
78 | * Returns a lazy collection with one or multiple levels of nesting flattened. Removes all nesting when no value |
||
79 | * is passed. |
||
80 | * |
||
81 | * @param int $depth How many levels should be flatten, default (-1) is infinite. |
||
82 | * @return Collection |
||
83 | */ |
||
84 | 1 | public function flatten($depth = -1) |
|
88 | |||
89 | /** |
||
90 | * Returns a non-lazy collection sorted using $function($item1, $item2, $key1, $key2 ). $function should |
||
91 | * return true if first item is larger than the second and false otherwise. |
||
92 | * |
||
93 | * @param callable $function ($value1, $value2, $key1, $key2) |
||
94 | * @return Collection |
||
95 | */ |
||
96 | 1 | public function sort(callable $function) |
|
100 | |||
101 | /** |
||
102 | * Returns lazy collection items of which are part of the original collection from item number $from to item |
||
103 | * number $to. The items before $from are also iterated over, just not returned. |
||
104 | * |
||
105 | * @param int $from |
||
106 | * @param int $to If omitted, will slice until end |
||
107 | * @return Collection |
||
108 | */ |
||
109 | 1 | public function slice($from, $to = -1) |
|
113 | |||
114 | /** |
||
115 | * Returns collection which items are separated into groups indexed by the return value of $function. |
||
116 | * |
||
117 | * @param callable $function ($value, $key) |
||
118 | * @return Collection |
||
119 | */ |
||
120 | 1 | public function groupBy(callable $function) |
|
124 | |||
125 | /** |
||
126 | * Returns a lazy collection in which $function is executed for each item. |
||
127 | * |
||
128 | * @param callable $function ($value, $key) |
||
129 | * @return Collection |
||
130 | */ |
||
131 | 1 | public function each(callable $function) |
|
135 | |||
136 | /** |
||
137 | * Returns the number of items in this collection. |
||
138 | * |
||
139 | * @return int |
||
140 | */ |
||
141 | 6 | public function size() |
|
145 | |||
146 | /** |
||
147 | * Returns value at the key $key. If multiple values have this key, return first. If no value has this key, throw |
||
148 | * ItemNotFound. If $convertToCollection is true and the return value is a collection (array|Traversable) an |
||
149 | * instance of Collection will be returned. |
||
150 | * |
||
151 | * @param mixed $key |
||
152 | * @param bool $convertToCollection |
||
153 | * @return Collection|mixed |
||
154 | * @throws ItemNotFound |
||
155 | */ |
||
156 | 2 | public function get($key, $convertToCollection = false) |
|
162 | |||
163 | /** |
||
164 | * Returns item at the key $key. If multiple items have this key, return first. If no item has this key, return |
||
165 | * $ifNotFound. If no value has this key, throw ItemNotFound. If $convertToCollection is true and the return value |
||
166 | * is a collection (array|Traversable) an instance of Collection will be returned. |
||
167 | * |
||
168 | * @param mixed $key |
||
169 | * @param mixed $default |
||
170 | * @param bool $convertToCollection |
||
171 | * @return mixed |
||
172 | * @throws ItemNotFound |
||
173 | */ |
||
174 | 1 | public function getOrDefault($key, $default = null, $convertToCollection = false) |
|
180 | |||
181 | /** |
||
182 | * Returns nth item in the collection starting from 0. If the size of this collection is smaller than $position, |
||
183 | * throw ItemNotFound. If $convertToCollection is true and the return value is a collection (array|Traversable) an |
||
184 | * instance of Collection will be returned. |
||
185 | * |
||
186 | * @param int $position |
||
187 | * @param bool $convertToCollection |
||
188 | * @return Collection|mixed |
||
189 | * @throws ItemNotFound |
||
190 | */ |
||
191 | 6 | public function getNth($position, $convertToCollection = false) |
|
197 | |||
198 | /** |
||
199 | * Returns first value matched by $function. If no value matches, return $default. If $convertToCollection is true |
||
200 | * and the return value is a collection (array|Traversable) an instance of Collection will be returned. |
||
201 | * |
||
202 | * @param callable $function |
||
203 | * @param mixed|null $default |
||
204 | * @param bool $convertToCollection |
||
205 | * @return Collection|mixed |
||
206 | */ |
||
207 | 1 | public function find(callable $function, $default = null, $convertToCollection = false) |
|
213 | |||
214 | /** |
||
215 | * Returns a non-lazy collection of items whose keys are the return values of $function and values are the number of |
||
216 | * items in this collection for which the $function returned this value. |
||
217 | * |
||
218 | * @param callable $function |
||
219 | * @return Collection |
||
220 | */ |
||
221 | 1 | public function countBy(callable $function) |
|
225 | |||
226 | /** |
||
227 | * Returns a lazy collection by changing keys of this collection for each item to the result of $function for |
||
228 | * that item. |
||
229 | * |
||
230 | * @param callable $function |
||
231 | * @return Collection |
||
232 | */ |
||
233 | 1 | public function indexBy(callable $function) |
|
237 | |||
238 | /** |
||
239 | * Returns true if $function returns true for every item in this collection, false otherwise. |
||
240 | * |
||
241 | * @param callable $function |
||
242 | * @return bool |
||
243 | */ |
||
244 | 1 | public function every(callable $function) |
|
248 | |||
249 | /** |
||
250 | * Returns true if $function returns true for at least one item in this collection, false otherwise. |
||
251 | * |
||
252 | * @param callable $function |
||
253 | * @return bool |
||
254 | */ |
||
255 | 1 | public function some(callable $function) |
|
259 | |||
260 | /** |
||
261 | * Returns true if $value is present in the collection. |
||
262 | * |
||
263 | * @param mixed $value |
||
264 | * @return bool |
||
265 | */ |
||
266 | 1 | public function contains($value) |
|
270 | |||
271 | /** |
||
272 | * Returns collection of items in this collection in reverse order. |
||
273 | * |
||
274 | * @return Collection |
||
275 | */ |
||
276 | 1 | public function reverse() |
|
280 | |||
281 | /** |
||
282 | * Reduce the collection to single value. Walks from right to left. |
||
283 | * |
||
284 | * @param callable $function Must take 2 arguments, intermediate value and item from the iterator. |
||
285 | * @param mixed $startValue |
||
286 | * @return mixed |
||
287 | */ |
||
288 | 1 | public function reduceRight(callable $function, $startValue) |
|
292 | |||
293 | /** |
||
294 | * A form of slice that returns first $numberOfItems items. |
||
295 | * |
||
296 | * @param int $numberOfItems |
||
297 | * @return Collection |
||
298 | */ |
||
299 | 8 | public function take($numberOfItems) |
|
303 | |||
304 | /** |
||
305 | * A form of slice that returns all but first $numberOfItems items. |
||
306 | * |
||
307 | * @param int $numberOfItems |
||
308 | * @return Collection |
||
309 | */ |
||
310 | 2 | public function drop($numberOfItems) |
|
314 | |||
315 | /** |
||
316 | * Returns collection of values from this collection but with keys being numerical from 0 upwards. |
||
317 | * |
||
318 | * @return Collection |
||
319 | */ |
||
320 | 10 | public function values() |
|
324 | |||
325 | /** |
||
326 | * Returns a lazy collection without elements matched by $function. |
||
327 | * |
||
328 | * @param callable $function |
||
329 | * @return Collection |
||
330 | */ |
||
331 | 1 | public function reject(callable $function) |
|
335 | |||
336 | /** |
||
337 | * Returns a lazy collection of the keys of this collection. |
||
338 | * |
||
339 | * @return Collection |
||
340 | */ |
||
341 | 1 | public function keys() |
|
345 | |||
346 | /** |
||
347 | * Returns a lazy collection of items of this collection separated by $separator |
||
348 | * |
||
349 | * @param mixed $separator |
||
350 | * @return Collection |
||
351 | */ |
||
352 | 1 | public function interpose($separator) |
|
356 | |||
357 | /** |
||
358 | * Returns a lazy collection with last $numberOfItems items skipped. These are still iterated over, just skipped. |
||
359 | * |
||
360 | * @param int $numberOfItems |
||
361 | * @return Collection |
||
362 | */ |
||
363 | 1 | public function dropLast($numberOfItems = 1) |
|
367 | |||
368 | /** |
||
369 | * Returns a lazy collection of first item from first collection, first item from second, second from first and |
||
370 | * so on. Accepts any number of collections. |
||
371 | * |
||
372 | * @param array|Traversable ...$collections |
||
373 | * @return Collection |
||
374 | */ |
||
375 | 1 | public function interleave(...$collections) |
|
379 | |||
380 | /** |
||
381 | * Returns an infinite lazy collection of items in this collection repeated infinitely. |
||
382 | * |
||
383 | * @return Collection |
||
384 | */ |
||
385 | 1 | public function cycle() |
|
389 | |||
390 | /** |
||
391 | * Returns a lazy collection of items of this collection with $value added as first element. If $key is not provided |
||
392 | * it will be next integer index. |
||
393 | * |
||
394 | * @param mixed $value |
||
395 | * @param mixed|null $key |
||
396 | * @return Collection |
||
397 | */ |
||
398 | 2 | public function prepend($value, $key = null) |
|
402 | |||
403 | /** |
||
404 | * Returns a lazy collection of items of this collection with $value added as last element. If $key is not provided |
||
405 | * it will be next integer index. |
||
406 | * |
||
407 | * @param mixed $value |
||
408 | * @param mixed $key |
||
409 | * @return Collection |
||
410 | */ |
||
411 | 7 | public function append($value, $key = null) |
|
415 | |||
416 | /** |
||
417 | * Returns a lazy collection by removing items from this collection until first item for which $function returns |
||
418 | * false. |
||
419 | * |
||
420 | * @param callable $function |
||
421 | * @return Collection |
||
422 | */ |
||
423 | 1 | public function dropWhile(callable $function) |
|
427 | |||
428 | /** |
||
429 | * Returns a lazy collection which is a result of calling map($function) and then flatten(1) |
||
430 | * |
||
431 | * @param callable $function |
||
432 | * @return Collection |
||
433 | */ |
||
434 | 1 | public function mapcat(callable $function) |
|
438 | |||
439 | /** |
||
440 | * Returns a lazy collection of items from the start of the ollection until the first item for which $function |
||
441 | * returns false. |
||
442 | * |
||
443 | * @param callable $function |
||
444 | * @return Collection |
||
445 | */ |
||
446 | 1 | public function takeWhile(callable $function) |
|
450 | |||
451 | /** |
||
452 | * Returns a collection of [take($position), drop($position)] |
||
453 | * |
||
454 | * @param int $position |
||
455 | * @return Collection |
||
456 | */ |
||
457 | 1 | public function splitAt($position) |
|
461 | |||
462 | /** |
||
463 | * Returns a collection of [takeWhile($predicament), dropWhile($predicament] |
||
464 | * |
||
465 | * @param callable $function |
||
466 | * @return Collection |
||
467 | */ |
||
468 | 1 | public function splitWith(callable $function) |
|
472 | |||
473 | /** |
||
474 | * Returns a lazy collection with items from this collection but values that are found in keys of $replacementMap |
||
475 | * are replaced by their values. |
||
476 | * |
||
477 | * @param Traversable|array $replacementMap |
||
478 | * @return Collection |
||
479 | */ |
||
480 | 1 | public function replace($replacementMap) |
|
484 | |||
485 | /** |
||
486 | * Returns a lazy collection of reduction steps. |
||
487 | * |
||
488 | * @param callable $function |
||
489 | * @param mixed $startValue |
||
490 | * @return Collection |
||
491 | */ |
||
492 | 1 | public function reductions(callable $function, $startValue) |
|
496 | |||
497 | /** |
||
498 | * Returns a lazy collection of every nth item in this collection |
||
499 | * |
||
500 | * @param int $step |
||
501 | * @return Collection |
||
502 | */ |
||
503 | 1 | public function takeNth($step) |
|
507 | |||
508 | /** |
||
509 | * Returns a non-collection of shuffled items from this collection |
||
510 | * |
||
511 | * @return Collection |
||
512 | */ |
||
513 | 1 | public function shuffle() |
|
517 | |||
518 | /** |
||
519 | * Returns a lazy collection of collections of $numberOfItems items each, at $step step |
||
520 | * apart. If $step is not supplied, defaults to $numberOfItems, i.e. the partitions |
||
521 | * do not overlap. If a $padding collection is supplied, use its elements as |
||
522 | * necessary to complete last partition up to $numberOfItems items. In case there are |
||
523 | * not enough padding elements, return a partition with less than $numberOfItems items. |
||
524 | * |
||
525 | * @param int $numberOfItems |
||
526 | * @param int $step |
||
527 | * @param array|Traversable $padding |
||
528 | * @return Collection |
||
529 | */ |
||
530 | 2 | public function partition($numberOfItems, $step = 0, $padding = []) |
|
534 | |||
535 | /** |
||
536 | * Creates a lazy collection of collections created by partitioning this collection every time $function will |
||
537 | * return different result. |
||
538 | * |
||
539 | * @param callable $function |
||
540 | * @return Collection |
||
541 | */ |
||
542 | 1 | public function partitionBy(callable $function) |
|
546 | |||
547 | /** |
||
548 | * Returns true if this collection is empty. False otherwise. |
||
549 | * |
||
550 | * @return bool |
||
551 | */ |
||
552 | 2 | public function isEmpty() |
|
556 | |||
557 | /** |
||
558 | * Opposite of isEmpty. |
||
559 | * |
||
560 | * @return bool |
||
561 | */ |
||
562 | 2 | public function isNotEmpty() |
|
566 | |||
567 | /** |
||
568 | * Returns a collection where keys are distinct items from this collection and their values are number of |
||
569 | * occurrences of each value. |
||
570 | * |
||
571 | * @return Collection |
||
572 | */ |
||
573 | 1 | public function frequencies() |
|
577 | |||
578 | /** |
||
579 | * Returns first item of this collection. If the collection is empty, throws ItemNotFound. If $convertToCollection |
||
580 | * is true and the return value is a collection (array|Traversable) an instance of Collection is returned. |
||
581 | * |
||
582 | * @param bool $convertToCollection |
||
583 | * @return mixed|Collection |
||
584 | * @throws ItemNotFound |
||
585 | */ |
||
586 | 10 | public function first($convertToCollection = false) |
|
591 | |||
592 | /** |
||
593 | * Returns last item of this collection. If the collection is empty, throws ItemNotFound. If $convertToCollection |
||
594 | * is true and the return value is a collection (array|Traversable) an |
||
595 | * |
||
596 | * @param bool $convertToCollection |
||
597 | * @return mixed|Collection |
||
598 | * @throws ItemNotFound |
||
599 | */ |
||
600 | 2 | public function last($convertToCollection = false) |
|
605 | |||
606 | /** |
||
607 | * Returns a lazy collection by picking a $key key from each sub-collection of $this. |
||
608 | * |
||
609 | * @param mixed $key |
||
610 | * @return Collection |
||
611 | */ |
||
612 | 2 | public function pluck($key) |
|
616 | |||
617 | /** |
||
618 | * Realizes collection - turns lazy collection into non-lazy one by iterating over it and storing the key/values. |
||
619 | * |
||
620 | * @return Collection |
||
621 | */ |
||
622 | 1 | public function realize() |
|
626 | |||
627 | /** |
||
628 | * Returns the second item in this collection or throws ItemNotFound if the collection is empty or has 1 item. |
||
629 | * |
||
630 | * @return mixed |
||
631 | */ |
||
632 | 2 | public function second() |
|
636 | |||
637 | /** |
||
638 | * Combines the values of this collection as keys, with values of $collection as values. The resulting collection |
||
639 | * has length equal to the size of smaller collection. If $strict is true, the size of both collections must be |
||
640 | * equal, otherwise ItemNotFound is thrown. When strict, the collection is realized immediately. |
||
641 | * |
||
642 | * @param array|Traversable $collection |
||
643 | * @param bool $strict |
||
644 | * @return Collection |
||
645 | */ |
||
646 | 1 | public function combine($collection, $strict = false) |
|
650 | |||
651 | /** |
||
652 | * Returns a lazy collection without the items associated to any of the keys from $keys. |
||
653 | * |
||
654 | * @param array|Traversable $keys |
||
655 | * @return Collection |
||
656 | */ |
||
657 | 1 | public function except($keys) |
|
661 | |||
662 | /** |
||
663 | * Returns a lazy collection of items associated to any of the keys from $keys. |
||
664 | * |
||
665 | * @param array|Traversable $keys |
||
666 | * @return Collection |
||
667 | */ |
||
668 | 1 | public function only($keys) |
|
672 | |||
673 | /** |
||
674 | * Returns a lazy collection of items that are in $this but are not in any of the other arguments. Note that the |
||
675 | * ...$collections are iterated non-lazily. |
||
676 | * |
||
677 | * @param array|Traversable ...$collections |
||
678 | * @return Collection |
||
679 | */ |
||
680 | 1 | public function difference(...$collections) |
|
684 | |||
685 | |||
686 | /** |
||
687 | * Returns a lazy collection where keys and values are flipped. |
||
688 | * |
||
689 | * @return Collection |
||
690 | */ |
||
691 | 1 | public function flip() |
|
695 | |||
696 | /** |
||
697 | * Checks for the existence of $key in this collection. |
||
698 | * |
||
699 | * @param mixed $key |
||
700 | * @return bool |
||
701 | */ |
||
702 | 1 | public function has($key) |
|
706 | |||
707 | /** |
||
708 | * @return array|Traversable |
||
709 | */ |
||
710 | 76 | protected function getItems() |
|
714 | } |
||
715 |
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.