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 Widget 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 Widget, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | abstract class Widget extends HtmlDoubleElement { |
||
23 | use FieldAsTrait,FormTrait; |
||
24 | |||
25 | /** |
||
26 | * @var string classname |
||
27 | */ |
||
28 | protected $_model; |
||
29 | protected $_modelInstance; |
||
30 | /** |
||
31 | * @var InstanceViewer |
||
32 | */ |
||
33 | protected $_instanceViewer; |
||
34 | /** |
||
35 | * @var HtmlMenu |
||
36 | */ |
||
37 | protected $_toolbar; |
||
38 | /** |
||
39 | * @var PositionInTable |
||
40 | */ |
||
41 | protected $_toolbarPosition; |
||
42 | |||
43 | /** |
||
44 | * @var boolean |
||
45 | */ |
||
46 | protected $_edition; |
||
47 | |||
48 | /** |
||
49 | * @var HtmlForm |
||
50 | */ |
||
51 | protected $_form; |
||
52 | |||
53 | protected $_generated; |
||
54 | |||
55 | |||
56 | public function __construct($identifier,$model,$modelInstance=NULL) { |
||
65 | |||
66 | protected function _init($instanceViewer,$contentKey,$content,$edition){ |
||
73 | |||
74 | /** |
||
75 | * @param int|string $fieldName |
||
76 | * @return int|string |
||
77 | */ |
||
78 | protected function _getIndex($fieldName){ |
||
86 | |||
87 | protected function _getFieldIdentifier($prefix,$name=""){ |
||
90 | |||
91 | protected function _getFieldName($index){ |
||
94 | |||
95 | protected function _getFieldCaption($index){ |
||
98 | |||
99 | abstract protected function _setToolbarPosition($table,$captions=NULL); |
||
100 | |||
101 | public function show($modelInstance){ |
||
107 | |||
108 | public function getModel() { |
||
111 | |||
112 | public function setModel($_model) { |
||
116 | |||
117 | public function getInstanceViewer() { |
||
120 | |||
121 | public function setInstanceViewer($_instanceViewer) { |
||
125 | |||
126 | abstract public function getHtmlComponent(); |
||
127 | |||
128 | public function setAttached($value=true){ |
||
131 | |||
132 | /** |
||
133 | * Associates a $callback function after the compilation of the field at $index position |
||
134 | * The $callback function can take the following arguments : $field=>the compiled field, $instance : the active instance of the object, $index: the field position |
||
135 | * @param int $index postion of the compiled field |
||
136 | * @param callable $callback function called after the field compilation |
||
137 | * @return Widget |
||
138 | */ |
||
139 | public function afterCompile($index,$callback){ |
||
144 | |||
145 | public function setColor($color){ |
||
148 | |||
149 | |||
150 | public function setCaptions($captions){ |
||
154 | |||
155 | public function setCaption($index,$caption){ |
||
159 | |||
160 | public function setFields($fields){ |
||
164 | |||
165 | public function addField($field){ |
||
169 | |||
170 | public function addFields($fields){ |
||
174 | |||
175 | public function addMessage($attributes=NULL,$fieldName="message"){ |
||
180 | |||
181 | public function addErrorMessage(){ |
||
184 | |||
185 | public function insertField($index,$field){ |
||
190 | |||
191 | public function insertInField($index,$field){ |
||
196 | |||
197 | public function setValueFunction($index,$callback){ |
||
202 | |||
203 | public function setIdentifierFunction($callback){ |
||
207 | |||
208 | /** |
||
209 | * @return \Ajax\semantic\html\collections\menus\HtmlMenu |
||
210 | */ |
||
211 | public function getToolbar(){ |
||
217 | |||
218 | /** |
||
219 | * Adds a new element in toolbar |
||
220 | * @param mixed $element |
||
221 | * @param callable $callback function to call on $element |
||
222 | * @return \Ajax\common\html\HtmlDoubleElement |
||
223 | */ |
||
224 | public function addInToolbar($element,$callback=NULL){ |
||
238 | |||
239 | /** |
||
240 | * @param string $caption |
||
241 | * @param string $icon |
||
242 | * @param callable $callback function($element) |
||
243 | * @return \Ajax\common\html\HtmlDoubleElement |
||
244 | */ |
||
245 | public function addItemInToolbar($caption,$icon=NULL,$callback=NULL){ |
||
251 | |||
252 | /** |
||
253 | * @param array $items |
||
254 | * @param callable $callback function($element) |
||
255 | * @return \Ajax\common\Widget |
||
256 | */ |
||
257 | public function addItemsInToolbar(array $items,$callback=NULL){ |
||
269 | |||
270 | /** |
||
271 | * @param string $value |
||
272 | * @param array $items |
||
273 | * @param callable $callback function($element) |
||
274 | * @return \Ajax\common\html\HtmlDoubleElement |
||
275 | */ |
||
276 | View Code Duplication | public function addDropdownInToolbar($value,$items,$callback=NULL){ |
|
283 | |||
284 | /** |
||
285 | * @param string $caption |
||
286 | * @param string $cssStyle |
||
287 | * @param callable $callback function($element) |
||
288 | * @return \Ajax\common\html\HtmlDoubleElement |
||
289 | */ |
||
290 | public function addButtonInToolbar($caption,$cssStyle=null,$callback=NULL){ |
||
294 | |||
295 | /** |
||
296 | * @param array $captions |
||
297 | * @param boolean $asIcon |
||
298 | * @param callable $callback function($element) |
||
299 | * @return \Ajax\common\html\HtmlDoubleElement |
||
300 | */ |
||
301 | public function addButtonsInToolbar(array $captions,$asIcon=false,$callback=NULL){ |
||
305 | |||
306 | /** |
||
307 | * @param string $caption |
||
308 | * @param string $icon |
||
309 | * @param boolean $before |
||
310 | * @param boolean $labeled |
||
311 | * @return \Ajax\common\html\HtmlDoubleElement |
||
312 | */ |
||
313 | public function addLabelledIconButtonInToolbar($caption,$icon,$before=true,$labeled=false){ |
||
318 | |||
319 | public function addSubmitInToolbar($identifier,$value,$cssStyle=NULL,$url=NULL,$responseElement=NULL,$parameters=NULL){ |
||
324 | |||
325 | /** |
||
326 | * Defines a callback function to call for modifying captions |
||
327 | * function parameters are $captions: the captions to modify and $instance: the active model instance |
||
328 | * @param callable $captionCallback |
||
329 | * @return Widget |
||
330 | */ |
||
331 | public function setCaptionCallback($captionCallback) { |
||
335 | |||
336 | /** |
||
337 | * Makes the input fields editable |
||
338 | * @param boolean $_edition |
||
339 | * @return \Ajax\common\Widget |
||
340 | */ |
||
341 | public function setEdition($_edition=true) { |
||
345 | |||
346 | /** |
||
347 | * Defines the default function which displays fields value |
||
348 | * @param callable $defaultValueFunction function parameters are : $name : the field name, $value : the field value ,$index : the field index, $instance : the active instance of model |
||
349 | * @return \Ajax\common\Widget |
||
350 | */ |
||
351 | public function setDefaultValueFunction($defaultValueFunction){ |
||
355 | |||
356 | /** |
||
357 | * @param string|boolean $disable |
||
358 | * @return string |
||
359 | */ |
||
360 | public function jsDisabled($disable=true){ |
||
363 | |||
364 | /** |
||
365 | * @param string $caption |
||
366 | * @param callable $callback function($element) |
||
367 | * @return \Ajax\common\html\HtmlDoubleElement |
||
368 | */ |
||
369 | public function addEditButtonInToolbar($caption,$callback=NULL){ |
||
376 | |||
377 | public function setToolbar(HtmlMenu $_toolbar) { |
||
381 | |||
382 | public function setToolbarPosition($_toolbarPosition) { |
||
386 | |||
387 | public function getForm() { |
||
394 | |||
395 | public function run(JsUtils $js){ |
||
402 | |||
403 | protected function runForm(JsUtils $js){ |
||
410 | |||
411 | protected function _compileForm(){ |
||
419 | |||
420 | public function setValidationParams(array $_validationParams) { |
||
424 | |||
425 | public function moveFieldTo($from,$to){ |
||
428 | |||
429 | public function swapFields($index1,$index2){ |
||
434 | |||
435 | public function removeField($index){ |
||
440 | |||
441 | public function asModal($header=null){ |
||
449 | |||
450 | public function addToProperty($name, $value, $separator=" ") { |
||
453 | } |
||
454 |
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.