Complex classes like Arrgh 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 Arrgh, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class Arrgh implements \ArrayAccess, \Iterator |
||
31 | { |
||
32 | const PHP_SORT_DIRECTION_56 = 1; |
||
33 | const PHP_SORT_DIRECTION_7 = -1; |
||
34 | |||
35 | /** |
||
36 | * Native array |
||
37 | * |
||
38 | * @var array |
||
39 | */ |
||
40 | private $array; |
||
41 | |||
42 | /** |
||
43 | * The original array value |
||
44 | * |
||
45 | * @var array |
||
46 | */ |
||
47 | private $original_array; |
||
48 | |||
49 | /** |
||
50 | * Array positino for ArrayAccess and Iterator |
||
51 | * |
||
52 | * @var integer |
||
53 | */ |
||
54 | private $array_position; |
||
55 | |||
56 | /** |
||
57 | * Termination flag. If set to false terminating methods will return $this |
||
58 | * instead of a value. |
||
59 | * |
||
60 | * @var bool |
||
61 | */ |
||
62 | private $terminate; |
||
63 | |||
64 | /** |
||
65 | * Keep once flag. If set invoke() will switch on the terminate flag after |
||
66 | * not returning value once. |
||
67 | * |
||
68 | * @var bool |
||
69 | */ |
||
70 | private $keep_once; |
||
71 | |||
72 | /** |
||
73 | * The last value computed. |
||
74 | * |
||
75 | * @var mixed |
||
76 | */ |
||
77 | private $last_value; |
||
78 | |||
79 | /** |
||
80 | * PHP version array. [major, minor, patch] |
||
81 | * |
||
82 | * @var array |
||
83 | */ |
||
84 | private static $php_version; |
||
85 | |||
86 | /** |
||
87 | * Sort direction value based on PHP version. Is set first time used. |
||
88 | * |
||
89 | * @var integer |
||
90 | */ |
||
91 | private static $php_sort_direction; |
||
92 | |||
93 | /** |
||
94 | * Creates a new Arrgh object |
||
95 | * |
||
96 | * @method __construct |
||
97 | * @param array|Arrgh $array Optional parameter that can be either an array or another Arrgh object. |
||
98 | */ |
||
99 | public function __construct($array = null) |
||
114 | |||
115 | /** |
||
116 | * Invoke calls for Arrgh instances. |
||
117 | * @internal |
||
118 | */ |
||
119 | public function __call($method, $args) |
||
123 | |||
124 | /** |
||
125 | * Returns a native array. |
||
126 | * |
||
127 | * @method toArray |
||
128 | * @return array Returns an array. |
||
129 | */ |
||
130 | public function toArray() |
||
140 | |||
141 | /** |
||
142 | * Tells Arrgh to either return iteself or a value where it would otherwise |
||
143 | * had terminated the chain and return a value. |
||
144 | * |
||
145 | * The default behaviour is to break the chain on terminating methods like: |
||
146 | * |
||
147 | * - join |
||
148 | * - pop |
||
149 | * |
||
150 | * @method keepChain |
||
151 | * @param bool $value Set true to keep and false to terminate. |
||
152 | * @param bool $keep_once Set true to automatically switch of again |
||
153 | * after one call to a terminating method. |
||
154 | * @see keep |
||
155 | * @see keepOnce |
||
156 | * @see breakChain |
||
157 | * @return Arrgh self |
||
158 | */ |
||
159 | public function keepChain($value = true, $keep_once = false) |
||
165 | |||
166 | /** |
||
167 | * Tells Arrgh to return itself where it would otheriwse had terminated |
||
168 | * the chain and returned a value. |
||
169 | * |
||
170 | * @method keep |
||
171 | * @see keepChain |
||
172 | * @return Arrgh self |
||
173 | */ |
||
174 | public function keep() |
||
178 | |||
179 | /** |
||
180 | * Tells Arrgh to return iteself where it would otherwise had terminated |
||
181 | * the chain and return a value, but do it just once. |
||
182 | * |
||
183 | * @method keepOnce |
||
184 | * @see keepChain |
||
185 | * @return Arrgh self |
||
186 | */ |
||
187 | public function keepOnce() |
||
191 | |||
192 | /** |
||
193 | * Tells Arrgh to return to its normal behaviour and return values rather |
||
194 | * than itself when terminating methods are called. |
||
195 | * |
||
196 | * @method breakChain |
||
197 | * @see keepChain |
||
198 | * @return Arrgh self |
||
199 | */ |
||
200 | public function breakChain() |
||
204 | |||
205 | /** |
||
206 | * ArrayAccess |
||
207 | * @internal |
||
208 | */ |
||
209 | public function offsetExists($offset) |
||
213 | |||
214 | /** |
||
215 | * ArrayAccess |
||
216 | * @internal |
||
217 | */ |
||
218 | public function offsetGet($offset) |
||
222 | |||
223 | /** |
||
224 | * ArrayAccess |
||
225 | * @internal |
||
226 | */ |
||
227 | public function offsetSet($offset, $value) |
||
235 | |||
236 | /** |
||
237 | * ArrayAccess |
||
238 | * @internal |
||
239 | */ |
||
240 | public function offsetUnset($offset) |
||
244 | |||
245 | /** |
||
246 | * Iterator |
||
247 | * @internal |
||
248 | */ |
||
249 | public function current() |
||
257 | |||
258 | /** |
||
259 | * Iterator |
||
260 | * @internal |
||
261 | */ |
||
262 | public function key() |
||
266 | |||
267 | /** |
||
268 | * Iterator |
||
269 | * @internal |
||
270 | */ |
||
271 | public function next() |
||
275 | |||
276 | /** |
||
277 | * Iterator |
||
278 | * @internal |
||
279 | */ |
||
280 | public function rewind() |
||
284 | |||
285 | /** |
||
286 | * Iterator |
||
287 | * @internal |
||
288 | */ |
||
289 | public function valid() |
||
293 | |||
294 | /** |
||
295 | * Creates a new Arrgh object (chain) |
||
296 | * |
||
297 | * @param mixed $array Optional parameter that can be either an array or another Arrgh object. |
||
298 | * @see chain |
||
299 | * @return Arrgh A new Arrgh object. |
||
300 | */ |
||
301 | public static function arr($array = []) |
||
305 | |||
306 | /** |
||
307 | * Creates a new Arrgh object (chain) |
||
308 | * |
||
309 | * @param mixed $array Optional parameter that can be either an array or another Arrgh object. |
||
310 | * @see arr |
||
311 | * @return Arrgh A new Arrgh object. |
||
312 | */ |
||
313 | public static function chain($array = []) |
||
317 | |||
318 | /** |
||
319 | * Invoke calls for static Arrgh calls. |
||
320 | * @internal |
||
321 | */ |
||
322 | public static function __callStatic($method, $args) |
||
335 | |||
336 | /** |
||
337 | * Returns list of supported functions partitioned into types of functions. |
||
338 | * |
||
339 | * @method allFunctions |
||
340 | * @return array Associative array with function type as key point |
||
341 | * to a list of functions of that type |
||
342 | */ |
||
343 | public static function allFunctions() |
||
355 | |||
356 | /** |
||
357 | * Given the PHP version this functions returns the sort integer to use |
||
358 | * for equal values in functions like `usort`. Optionally you can pass in |
||
359 | * the existing value like so: |
||
360 | * |
||
361 | * usort($input, function ($a, $b) { |
||
362 | * return Arrgh::getSortDirection($a - $b); |
||
363 | * }); |
||
364 | * |
||
365 | * This will ensure that the custom sort function will work in both PHP |
||
366 | * version 5.6.x and 7.x |
||
367 | * |
||
368 | * @method getSortDirection |
||
369 | * @param integer $direction An integer like value |
||
370 | * @return integer Returns a sort integer for a sort or compare function |
||
371 | */ |
||
372 | public static function getSortDirection($direction = null) |
||
383 | |||
384 | /** |
||
385 | * Wraps a callable with the purpose of fixing bad PHP sort implementations. |
||
386 | * |
||
387 | * @internal |
||
388 | * |
||
389 | * @method wrapCallable |
||
390 | * @param Closure $callable A sort function |
||
391 | * @return Closure A new closeure |
||
392 | */ |
||
393 | private static function wrapCallable(Closure $callable) |
||
404 | |||
405 | |||
406 | /** |
||
407 | * Transforms the incoming calls to native calls. |
||
408 | * |
||
409 | * @internal |
||
410 | * |
||
411 | * @method invoke |
||
412 | * @param string $method Name of method to invoke. |
||
413 | * @param array $args Arguments for method. |
||
414 | * @param Arrgh|null $object Optionally invoke on $object. |
||
415 | * |
||
416 | * @return mixed Can return anything. |
||
417 | */ |
||
418 | private static function invoke($method, $args, Arrgh $object = null) |
||
490 | |||
491 | /** |
||
492 | * Based on input method finds handler, function and post handler. |
||
493 | * |
||
494 | * @internal |
||
495 | * |
||
496 | * @return array Returns a tuble of [handler, function, postHandler] |
||
497 | */ |
||
498 | private static function findFunction($method) |
||
525 | |||
526 | /** |
||
527 | * Handles special case: asort - In PHP5 reverses equals ("arsort" doen't mess up for some reason) |
||
528 | * |
||
529 | * @internal |
||
530 | */ |
||
531 | private static function handleCaseAsort(&$matching_function, &$args) |
||
536 | |||
537 | /** |
||
538 | * Handles special case: array_column - Native array_column filters away null values. |
||
539 | * |
||
540 | * That means you cannot use array_column for multisort since array size no longer matches. |
||
541 | * This version of array_column returns null if the column is missing. |
||
542 | * |
||
543 | * @internal |
||
544 | */ |
||
545 | private static function handleCaseArrayColumn(&$matching_handler, &$matching_function, &$post_handler, &$args) |
||
565 | |||
566 | /** |
||
567 | * Handler: _call |
||
568 | * |
||
569 | * Calls the native function directly. |
||
570 | * |
||
571 | * @internal |
||
572 | */ |
||
573 | private static function _call($function, $args) |
||
577 | |||
578 | /** |
||
579 | * Handler: _rotateRight |
||
580 | * |
||
581 | * Shifts of the first argument (callable) and pushes it to the end. |
||
582 | * |
||
583 | * @internal |
||
584 | */ |
||
585 | private static function _rotateRight($function, $args) |
||
591 | |||
592 | /** |
||
593 | * Handler: _swapTwoFirst |
||
594 | * |
||
595 | * Swaps the first two args. |
||
596 | * |
||
597 | * @internal |
||
598 | */ |
||
599 | private static function _swapTwoFirst($function, $args) |
||
607 | |||
608 | /** |
||
609 | * Handler: _copy |
||
610 | * |
||
611 | * Makes a copy of the array and returns it after invoking function. |
||
612 | * |
||
613 | * @internal |
||
614 | */ |
||
615 | private static function _copy($function, $args) |
||
621 | |||
622 | /** |
||
623 | * Handler: _copyMultiple |
||
624 | * |
||
625 | * If multiple arrays are passed as arguments mulitple will be returned. |
||
626 | * Otherwise _copy is used. |
||
627 | * |
||
628 | * @internal |
||
629 | */ |
||
630 | private static function _copyMultiple($function, $args) |
||
644 | |||
645 | /** |
||
646 | * Handler: _copyValue |
||
647 | * |
||
648 | * Makes a copy of the array and returns it after invoking function. |
||
649 | * |
||
650 | * @internal |
||
651 | */ |
||
652 | private static function _copyValue($function, $args, $object = null) |
||
661 | |||
662 | /** |
||
663 | * Handler: _arrgh |
||
664 | * |
||
665 | * The handler for non-native functions |
||
666 | * |
||
667 | * @internal |
||
668 | */ |
||
669 | private static function _arrgh($function, $args) |
||
674 | |||
675 | /** |
||
676 | * A mapping function for associative arrays (keeps keys). |
||
677 | * |
||
678 | * @method map_assoc |
||
679 | * |
||
680 | * @param array $array Array or array-like value. |
||
681 | * @param Closure $callable Mapping function |
||
682 | * |
||
683 | * @return array Returns mapped associative array. |
||
684 | */ |
||
685 | private static function arr_map_assoc($array, Closure $callable) |
||
690 | |||
691 | /** |
||
692 | * Sort an array of associative arrays by key. It checks the first two values for type |
||
693 | * either sorts by number or using strcmp. If a key is missing entries are moved to the top |
||
694 | * (or bottom depending on $direction) |
||
695 | */ |
||
696 | private static function arr_sort_by($array, $key, $direction = "ASC") |
||
714 | |||
715 | private static function arr_collapse($array) |
||
725 | |||
726 | private static function arr_contains($array, $search, $key = null) |
||
737 | |||
738 | private static function arr_except($array, $except) |
||
759 | |||
760 | private static function arr_only($array, $only) |
||
783 | |||
784 | /** |
||
785 | * Get for multi-dimensional arrays |
||
786 | * |
||
787 | * @param array An array to query on |
||
788 | * @param path|array A string representing the path to traverse. |
||
789 | * Optionally pass as [ $path, ...$functions ] if `!$` is used |
||
790 | * @param bool Collapse resulting data-set |
||
791 | * @throws InvalidArgumentException Thrown when a path cannot be reached in case $array does |
||
792 | * not correspond to path type. E.g. collection expected |
||
793 | * but a simple value was encountered. |
||
794 | */ |
||
795 | private static function arr_get($array, $path, $collapse = false) |
||
804 | |||
805 | /* arr_get: Traverses path to get value */ |
||
806 | private static function _arr_get_traverse($data, $path, $collapse = false, $functions = []) |
||
867 | |||
868 | private static function _arr_get_traverse_collection($path, $next_node, $collapse, $functions) |
||
903 | |||
904 | /* arr_get: Find next node by index */ |
||
905 | private static function _arr_get_traverse_next_node_index($data, $plug_index) |
||
919 | |||
920 | /* arr_get: Find next node by key */ |
||
921 | private static function _arr_get_traverse_next_node_key($data, $is_collection, $next_key) |
||
941 | |||
942 | /* arr_get: Invoke custom filter function on path */ |
||
943 | private static function _arr_get_traverse_apply_custom_function($data, $functions, $path) |
||
950 | |||
951 | private static function arr_is_collection($mixed) |
||
955 | |||
956 | /** |
||
957 | * Return the depth of a collection hiearchy. Zero based. |
||
958 | * |
||
959 | * @param array A collection |
||
960 | * @return int `null` if $array is not a collection. |
||
961 | */ |
||
962 | private static function arr_depth($array) |
||
982 | |||
983 | /** |
||
984 | * Partion the input based on the result of the callback function. |
||
985 | * |
||
986 | * @param array $array A collection |
||
987 | * @param \Closeure $callable A callable returning true or false depending on which way to partion the element—left or right. |
||
988 | * @return array An array with two arrays—left and right: [left, right] |
||
989 | */ |
||
990 | private static function arr_partition($array, Closure $callable) |
||
1003 | |||
1004 | private static function arr_even($array) |
||
1008 | |||
1009 | private static function arr_odd($array) |
||
1013 | |||
1014 | /* Synonym of shift */ |
||
1015 | private static function arr_head($array) |
||
1019 | |||
1020 | private static function arr_first($array) |
||
1027 | |||
1028 | private static function arr_last($array) |
||
1035 | |||
1036 | private static function arr_tail($array, $object = null) |
||
1044 | |||
1045 | // _arrgh |
||
1046 | static private $arr_functions = [ |
||
1047 | "collapse", |
||
1048 | "contains", |
||
1049 | "except", |
||
1050 | "map_assoc", |
||
1051 | "only", |
||
1052 | "sort_by", |
||
1053 | 'depth', |
||
1054 | 'even', |
||
1055 | 'first', |
||
1056 | 'get', |
||
1057 | 'head', |
||
1058 | 'is_collection', |
||
1059 | 'last', |
||
1060 | 'odd', |
||
1061 | 'partition', |
||
1062 | 'tail', |
||
1063 | ]; |
||
1064 | |||
1065 | // _call |
||
1066 | static private $simple_functions = [ |
||
1067 | "array_change_key_case", |
||
1068 | "array_chunk", |
||
1069 | "array_column", |
||
1070 | "array_combine", |
||
1071 | "array_count_values", |
||
1072 | "array_diff", |
||
1073 | "array_diff_assoc", |
||
1074 | "array_diff_key", |
||
1075 | "array_diff_uassoc", |
||
1076 | "array_diff_ukey", |
||
1077 | "array_fill", |
||
1078 | "array_fill_keys", |
||
1079 | "array_filter", |
||
1080 | "array_flip", |
||
1081 | "array_intersect", |
||
1082 | "array_intersect_assoc", |
||
1083 | "array_intersect_key", |
||
1084 | "array_intersect_uassoc", |
||
1085 | "array_intersect_ukey", |
||
1086 | "array_keys", |
||
1087 | "array_merge", |
||
1088 | "array_merge_recursive", |
||
1089 | "array_pad", |
||
1090 | "array_product", |
||
1091 | "array_rand", |
||
1092 | "array_reduce", |
||
1093 | "array_replace", |
||
1094 | "array_replace_recursive", |
||
1095 | "array_reverse", |
||
1096 | "array_slice", |
||
1097 | "array_sum", |
||
1098 | "array_udiff", |
||
1099 | "array_udiff_assoc", |
||
1100 | "array_udiff_uassoc", |
||
1101 | "array_uintersect", |
||
1102 | "array_uintersect_assoc", |
||
1103 | "array_uintersect_uassoc", |
||
1104 | "array_unique", |
||
1105 | "array_values", |
||
1106 | "count", |
||
1107 | "max", |
||
1108 | "min", |
||
1109 | "range", |
||
1110 | "sizeof", |
||
1111 | ]; |
||
1112 | |||
1113 | // _copy |
||
1114 | static private $mutable_functions = [ |
||
1115 | "array_push", |
||
1116 | "array_splice", |
||
1117 | "array_unshift", |
||
1118 | "array_walk", |
||
1119 | "array_walk_recursive", |
||
1120 | "arsort", |
||
1121 | "asort", |
||
1122 | "krsort", |
||
1123 | "ksort", |
||
1124 | "natcasesort", |
||
1125 | "natsort", |
||
1126 | "rsort", |
||
1127 | "shuffle", |
||
1128 | "sort", |
||
1129 | "uasort", |
||
1130 | "uksort", |
||
1131 | "usort", |
||
1132 | ]; |
||
1133 | |||
1134 | // _copyMultiple |
||
1135 | static private $mutable_functions_multiple = [ |
||
1136 | "array_multisort", |
||
1137 | ]; |
||
1138 | |||
1139 | // _copyValue |
||
1140 | static private $mutable_value_functions = [ |
||
1141 | "array_pop", |
||
1142 | "array_shift", |
||
1143 | "end", |
||
1144 | ]; |
||
1145 | |||
1146 | // _rotateRight |
||
1147 | static private $reverse_functions = [ |
||
1148 | "array_map", |
||
1149 | ]; |
||
1150 | |||
1151 | // _swapTwoFirst |
||
1152 | static private $swapped_functions = [ |
||
1153 | "array_key_exists", |
||
1154 | "array_search", |
||
1155 | "implode", |
||
1156 | "in_array", |
||
1157 | "join", |
||
1158 | ]; |
||
1159 | |||
1160 | static private $starters = [ |
||
1161 | "array_fill", |
||
1162 | "array_fill_keys", |
||
1163 | "range", |
||
1164 | ]; |
||
1165 | |||
1166 | static private $terminators = [ |
||
1167 | "array_pop", |
||
1168 | "array_shift", |
||
1169 | "array_sum", |
||
1170 | "count", |
||
1171 | "first", |
||
1172 | "head", |
||
1173 | "join", |
||
1174 | "last", |
||
1175 | "max", |
||
1176 | "min", |
||
1177 | "sizeof", |
||
1178 | ]; |
||
1179 | |||
1180 | static private $reverse_result_functions = [ |
||
1181 | "uasort", |
||
1182 | "uksort", |
||
1183 | "usort", |
||
1184 | "asort", |
||
1185 | ]; |
||
1186 | } |
||
1187 |