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 classes like Field 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 Field, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class Field implements Renderable |
||
17 | { |
||
18 | use Macroable; |
||
19 | |||
20 | const FILE_DELETE_FLAG = '_file_del_'; |
||
21 | |||
22 | /** |
||
23 | * Element id. |
||
24 | * |
||
25 | * @var array|string |
||
26 | */ |
||
27 | protected $id; |
||
28 | |||
29 | /** |
||
30 | * Element value. |
||
31 | * |
||
32 | * @var mixed |
||
33 | */ |
||
34 | protected $value; |
||
35 | |||
36 | /** |
||
37 | * Data of all original columns of value. |
||
38 | * |
||
39 | * @var mixed |
||
40 | */ |
||
41 | protected $data; |
||
42 | |||
43 | /** |
||
44 | * Field original value. |
||
45 | * |
||
46 | * @var mixed |
||
47 | */ |
||
48 | protected $original; |
||
49 | |||
50 | /** |
||
51 | * Field default value. |
||
52 | * |
||
53 | * @var mixed |
||
54 | */ |
||
55 | protected $default; |
||
56 | |||
57 | /** |
||
58 | * Element label. |
||
59 | * |
||
60 | * @var string |
||
61 | */ |
||
62 | protected $label = ''; |
||
63 | |||
64 | /** |
||
65 | * Column name. |
||
66 | * |
||
67 | * @var string|array |
||
68 | */ |
||
69 | protected $column = ''; |
||
70 | |||
71 | /** |
||
72 | * Form element name. |
||
73 | * |
||
74 | * @var string |
||
75 | */ |
||
76 | protected $elementName = []; |
||
77 | |||
78 | /** |
||
79 | * Form element classes. |
||
80 | * |
||
81 | * @var array |
||
82 | */ |
||
83 | protected $elementClass = []; |
||
84 | |||
85 | /** |
||
86 | * Variables of elements. |
||
87 | * |
||
88 | * @var array |
||
89 | */ |
||
90 | protected $variables = []; |
||
91 | |||
92 | /** |
||
93 | * Options for specify elements. |
||
94 | * |
||
95 | * @var array |
||
96 | */ |
||
97 | protected $options = []; |
||
98 | |||
99 | /** |
||
100 | * Checked for specify elements. |
||
101 | * |
||
102 | * @var array |
||
103 | */ |
||
104 | protected $checked = []; |
||
105 | |||
106 | /** |
||
107 | * Validation rules. |
||
108 | * |
||
109 | * @var string|\Closure |
||
110 | */ |
||
111 | protected $rules = ''; |
||
112 | |||
113 | /** |
||
114 | * @var callable |
||
115 | */ |
||
116 | protected $validator; |
||
117 | |||
118 | /** |
||
119 | * Validation messages. |
||
120 | * |
||
121 | * @var array |
||
122 | */ |
||
123 | protected $validationMessages = []; |
||
124 | |||
125 | /** |
||
126 | * Css required by this field. |
||
127 | * |
||
128 | * @var array |
||
129 | */ |
||
130 | protected static $css = []; |
||
131 | |||
132 | /** |
||
133 | * Js required by this field. |
||
134 | * |
||
135 | * @var array |
||
136 | */ |
||
137 | protected static $js = []; |
||
138 | |||
139 | /** |
||
140 | * Script for field. |
||
141 | * |
||
142 | * @var string |
||
143 | */ |
||
144 | protected $script = ''; |
||
145 | |||
146 | /** |
||
147 | * Element attributes. |
||
148 | * |
||
149 | * @var array |
||
150 | */ |
||
151 | protected $attributes = []; |
||
152 | |||
153 | /** |
||
154 | * Parent form. |
||
155 | * |
||
156 | * @var Form |
||
157 | */ |
||
158 | protected $form = null; |
||
159 | |||
160 | /** |
||
161 | * View for field to render. |
||
162 | * |
||
163 | * @var string |
||
164 | */ |
||
165 | protected $view = ''; |
||
166 | |||
167 | /** |
||
168 | * Help block. |
||
169 | * |
||
170 | * @var array |
||
171 | */ |
||
172 | protected $help = []; |
||
173 | |||
174 | /** |
||
175 | * Key for errors. |
||
176 | * |
||
177 | * @var mixed |
||
178 | */ |
||
179 | protected $errorKey; |
||
180 | |||
181 | /** |
||
182 | * Placeholder for this field. |
||
183 | * |
||
184 | * @var string|array |
||
185 | */ |
||
186 | protected $placeholder; |
||
187 | |||
188 | /** |
||
189 | * Width for label and field. |
||
190 | * |
||
191 | * @var array |
||
192 | */ |
||
193 | protected $width = [ |
||
194 | 'label' => 2, |
||
195 | 'field' => 8, |
||
196 | ]; |
||
197 | |||
198 | /** |
||
199 | * If the form horizontal layout. |
||
200 | * |
||
201 | * @var bool |
||
202 | */ |
||
203 | protected $horizontal = true; |
||
204 | |||
205 | /** |
||
206 | * column data format. |
||
207 | * |
||
208 | * @var \Closure |
||
209 | */ |
||
210 | protected $customFormat = null; |
||
211 | |||
212 | /** |
||
213 | * @var bool |
||
214 | */ |
||
215 | protected $display = true; |
||
216 | |||
217 | /** |
||
218 | * @var array |
||
219 | */ |
||
220 | protected $labelClass = []; |
||
221 | |||
222 | /** |
||
223 | * @var array |
||
224 | */ |
||
225 | protected $groupClass = []; |
||
226 | |||
227 | /** |
||
228 | * Field constructor. |
||
229 | * |
||
230 | * @param $column |
||
231 | * @param array $arguments |
||
232 | */ |
||
233 | public function __construct($column, $arguments = []) |
||
239 | |||
240 | /** |
||
241 | * Get assets required by this field. |
||
242 | * |
||
243 | * @return array |
||
244 | */ |
||
245 | public static function getAssets() |
||
252 | |||
253 | /** |
||
254 | * Format the field element id. |
||
255 | * |
||
256 | * @param string|array $column |
||
257 | * |
||
258 | * @return string|array |
||
259 | */ |
||
260 | protected function formatId($column) |
||
264 | |||
265 | /** |
||
266 | * Format the label value. |
||
267 | * |
||
268 | * @param array $arguments |
||
269 | * |
||
270 | * @return string |
||
271 | */ |
||
272 | protected function formatLabel($arguments = []) |
||
280 | |||
281 | /** |
||
282 | * Format the name of the field. |
||
283 | * |
||
284 | * @param string $column |
||
285 | * |
||
286 | * @return array|mixed|string |
||
287 | */ |
||
288 | protected function formatName($column) |
||
316 | |||
317 | /** |
||
318 | * Set form element name. |
||
319 | * |
||
320 | * @param string $name |
||
321 | * |
||
322 | * @return $this |
||
323 | * |
||
324 | * @author Edwin Hui |
||
325 | */ |
||
326 | public function setElementName($name) |
||
332 | |||
333 | /** |
||
334 | * Fill data to the field. |
||
335 | * |
||
336 | * @param array $data |
||
337 | * |
||
338 | * @return void |
||
339 | */ |
||
340 | public function fill($data) |
||
362 | |||
363 | /** |
||
364 | * custom format form column data when edit. |
||
365 | * |
||
366 | * @param \Closure $call |
||
367 | * |
||
368 | * @return $this |
||
369 | */ |
||
370 | public function customFormat(\Closure $call) |
||
376 | |||
377 | /** |
||
378 | * Set original value to the field. |
||
379 | * |
||
380 | * @param array $data |
||
381 | * |
||
382 | * @return void |
||
383 | */ |
||
384 | public function setOriginal($data) |
||
396 | |||
397 | /** |
||
398 | * @param Form $form |
||
399 | * |
||
400 | * @return $this |
||
401 | */ |
||
402 | public function setForm(Form $form = null) |
||
408 | |||
409 | /** |
||
410 | * Set width for field and label. |
||
411 | * |
||
412 | * @param int $field |
||
413 | * @param int $label |
||
414 | * |
||
415 | * @return $this |
||
416 | */ |
||
417 | public function setWidth($field = 8, $label = 2) |
||
426 | |||
427 | /** |
||
428 | * Set the field options. |
||
429 | * |
||
430 | * @param array $options |
||
431 | * |
||
432 | * @return $this |
||
433 | */ |
||
434 | View Code Duplication | public function options($options = []) |
|
444 | |||
445 | /** |
||
446 | * Set the field option checked. |
||
447 | * |
||
448 | * @param array $checked |
||
449 | * |
||
450 | * @return $this |
||
451 | */ |
||
452 | View Code Duplication | public function checked($checked = []) |
|
462 | |||
463 | /** |
||
464 | * Get or set rules. |
||
465 | * |
||
466 | * @param null $rules |
||
467 | * @param array $messages |
||
468 | * |
||
469 | * @return $this |
||
470 | */ |
||
471 | public function rules($rules = null, $messages = []) |
||
493 | |||
494 | /** |
||
495 | * Get field validation rules. |
||
496 | * |
||
497 | * @return string |
||
498 | */ |
||
499 | protected function getRules() |
||
507 | |||
508 | /** |
||
509 | * Remove a specific rule by keyword. |
||
510 | * |
||
511 | * @param string $rule |
||
512 | * |
||
513 | * @return void |
||
514 | */ |
||
515 | protected function removeRule($rule) |
||
524 | |||
525 | /** |
||
526 | * Set field validator. |
||
527 | * |
||
528 | * @param callable $validator |
||
529 | * |
||
530 | * @return $this |
||
531 | */ |
||
532 | public function validator(callable $validator) |
||
538 | |||
539 | /** |
||
540 | * Get key for error message. |
||
541 | * |
||
542 | * @return string |
||
543 | */ |
||
544 | public function getErrorKey() |
||
548 | |||
549 | /** |
||
550 | * Set key for error message. |
||
551 | * |
||
552 | * @param string $key |
||
553 | * |
||
554 | * @return $this |
||
555 | */ |
||
556 | public function setErrorKey($key) |
||
562 | |||
563 | /** |
||
564 | * Set or get value of the field. |
||
565 | * |
||
566 | * @param null $value |
||
567 | * |
||
568 | * @return mixed |
||
569 | */ |
||
570 | View Code Duplication | public function value($value = null) |
|
580 | |||
581 | /** |
||
582 | * Set or get data. |
||
583 | * |
||
584 | * @param array $data |
||
585 | * |
||
586 | * @return $this |
||
587 | */ |
||
588 | public function data(array $data = null) |
||
598 | |||
599 | /** |
||
600 | * Set default value for field. |
||
601 | * |
||
602 | * @param $default |
||
603 | * |
||
604 | * @return $this |
||
605 | */ |
||
606 | public function default($default) |
||
612 | |||
613 | /** |
||
614 | * Get default value. |
||
615 | * |
||
616 | * @return mixed |
||
617 | */ |
||
618 | public function getDefault() |
||
626 | |||
627 | /** |
||
628 | * Set help block for current field. |
||
629 | * |
||
630 | * @param string $text |
||
631 | * @param string $icon |
||
632 | * |
||
633 | * @return $this |
||
634 | */ |
||
635 | public function help($text = '', $icon = 'fa-info-circle') |
||
641 | |||
642 | /** |
||
643 | * Get column of the field. |
||
644 | * |
||
645 | * @return string|array |
||
646 | */ |
||
647 | public function column() |
||
651 | |||
652 | /** |
||
653 | * Get label of the field. |
||
654 | * |
||
655 | * @return string |
||
656 | */ |
||
657 | public function label() |
||
661 | |||
662 | /** |
||
663 | * Get original value of the field. |
||
664 | * |
||
665 | * @return mixed |
||
666 | */ |
||
667 | public function original() |
||
671 | |||
672 | /** |
||
673 | * Get validator for this field. |
||
674 | * |
||
675 | * @param array $input |
||
676 | * |
||
677 | * @return bool|Validator |
||
678 | */ |
||
679 | public function getValidator(array $input) |
||
715 | |||
716 | /** |
||
717 | * Sanitize input data. |
||
718 | * |
||
719 | * @param array $input |
||
720 | * @param string $column |
||
721 | * |
||
722 | * @return array |
||
723 | */ |
||
724 | protected function sanitizeInput($input, $column) |
||
733 | |||
734 | /** |
||
735 | * Add html attributes to elements. |
||
736 | * |
||
737 | * @param array|string $attribute |
||
738 | * @param mixed $value |
||
739 | * |
||
740 | * @return $this |
||
741 | */ |
||
742 | public function attribute($attribute, $value = null) |
||
752 | |||
753 | /** |
||
754 | * Specifies a regular expression against which to validate the value of the input. |
||
755 | * |
||
756 | * @param string $regexp |
||
757 | * |
||
758 | * @return Field |
||
759 | */ |
||
760 | public function pattern($regexp) |
||
764 | |||
765 | /** |
||
766 | * set the input filed required. |
||
767 | * |
||
768 | * @param bool $isLabelAsterisked |
||
769 | * |
||
770 | * @return Field |
||
771 | */ |
||
772 | public function required($isLabelAsterisked = true) |
||
780 | |||
781 | /** |
||
782 | * Set the field automatically get focus. |
||
783 | * |
||
784 | * @return Field |
||
785 | */ |
||
786 | public function autofocus() |
||
790 | |||
791 | /** |
||
792 | * Set the field as readonly mode. |
||
793 | * |
||
794 | * @return Field |
||
795 | */ |
||
796 | public function readOnly() |
||
800 | |||
801 | /** |
||
802 | * Set field as disabled. |
||
803 | * |
||
804 | * @return Field |
||
805 | */ |
||
806 | public function disable() |
||
810 | |||
811 | /** |
||
812 | * Set field placeholder. |
||
813 | * |
||
814 | * @param string $placeholder |
||
815 | * |
||
816 | * @return Field |
||
817 | */ |
||
818 | public function placeholder($placeholder = '') |
||
824 | |||
825 | /** |
||
826 | * Get placeholder. |
||
827 | * |
||
828 | * @return string |
||
829 | */ |
||
830 | public function getPlaceholder() |
||
834 | |||
835 | /** |
||
836 | * Prepare for a field value before update or insert. |
||
837 | * |
||
838 | * @param $value |
||
839 | * |
||
840 | * @return mixed |
||
841 | */ |
||
842 | public function prepare($value) |
||
846 | |||
847 | /** |
||
848 | * Format the field attributes. |
||
849 | * |
||
850 | * @return string |
||
851 | */ |
||
852 | protected function formatAttributes() |
||
862 | |||
863 | /** |
||
864 | * @return $this |
||
865 | */ |
||
866 | public function disableHorizontal() |
||
872 | |||
873 | /** |
||
874 | * @return array |
||
875 | */ |
||
876 | public function getViewElementClasses() |
||
888 | |||
889 | /** |
||
890 | * Set form element class. |
||
891 | * |
||
892 | * @param string|array $class |
||
893 | * |
||
894 | * @return $this |
||
895 | */ |
||
896 | public function setElementClass($class) |
||
902 | |||
903 | /** |
||
904 | * Get element class. |
||
905 | * |
||
906 | * @return array |
||
907 | */ |
||
908 | protected function getElementClass() |
||
918 | |||
919 | /** |
||
920 | * Get element class string. |
||
921 | * |
||
922 | * @return mixed |
||
923 | */ |
||
924 | View Code Duplication | protected function getElementClassString() |
|
940 | |||
941 | /** |
||
942 | * Get element class selector. |
||
943 | * |
||
944 | * @return string|array |
||
945 | */ |
||
946 | View Code Duplication | protected function getElementClassSelector() |
|
962 | |||
963 | /** |
||
964 | * Add the element class. |
||
965 | * |
||
966 | * @param $class |
||
967 | * |
||
968 | * @return $this |
||
969 | */ |
||
970 | public function addElementClass($class) |
||
980 | |||
981 | /** |
||
982 | * Remove element class. |
||
983 | * |
||
984 | * @param $class |
||
985 | * |
||
986 | * @return $this |
||
987 | */ |
||
988 | public function removeElementClass($class) |
||
1004 | |||
1005 | /** |
||
1006 | * Set form group class. |
||
1007 | * |
||
1008 | * @param string|array $class |
||
1009 | * |
||
1010 | * @return $this |
||
1011 | */ |
||
1012 | public function setGroupClass($class) |
||
1018 | |||
1019 | /** |
||
1020 | * Get element class. |
||
1021 | * |
||
1022 | * @return array |
||
1023 | */ |
||
1024 | protected function getGroupClass($default = false) |
||
1029 | |||
1030 | /** |
||
1031 | * Add variables to field view. |
||
1032 | * |
||
1033 | * @param array $variables |
||
1034 | * |
||
1035 | * @return $this |
||
1036 | */ |
||
1037 | protected function addVariables(array $variables = []) |
||
1043 | |||
1044 | /** |
||
1045 | * @return string |
||
1046 | */ |
||
1047 | public function getLabelClass() |
||
1052 | |||
1053 | /** |
||
1054 | * @param array $labelClass |
||
1055 | * |
||
1056 | * @return self |
||
1057 | */ |
||
1058 | public function setLabelClass(array $labelClass) |
||
1065 | |||
1066 | /** |
||
1067 | * Get the view variables of this field. |
||
1068 | * |
||
1069 | * @return array |
||
1070 | */ |
||
1071 | public function variables() |
||
1087 | |||
1088 | /** |
||
1089 | * Get view of this field. |
||
1090 | * |
||
1091 | * @return string |
||
1092 | */ |
||
1093 | public function getView() |
||
1103 | |||
1104 | /** |
||
1105 | * Get script of current field. |
||
1106 | * |
||
1107 | * @return string |
||
1108 | */ |
||
1109 | public function getScript() |
||
1113 | |||
1114 | /** |
||
1115 | * Set script of current field. |
||
1116 | * |
||
1117 | * @return self |
||
1118 | */ |
||
1119 | public function setScript($script) |
||
1125 | |||
1126 | /** |
||
1127 | * To set this field should render or not. |
||
1128 | * |
||
1129 | * @return self |
||
1130 | */ |
||
1131 | public function setDisplay(bool $display) |
||
1137 | |||
1138 | /** |
||
1139 | * If this field should render. |
||
1140 | * |
||
1141 | * @return bool |
||
1142 | */ |
||
1143 | protected function shouldRender() |
||
1151 | |||
1152 | /** |
||
1153 | * Render this filed. |
||
1154 | * |
||
1155 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string |
||
1156 | */ |
||
1157 | public function render() |
||
1167 | |||
1168 | /** |
||
1169 | * @return string |
||
1170 | */ |
||
1171 | public function __toString() |
||
1175 | } |
||
1176 |
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.