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 TWizard 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 TWizard, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 82 | class TWizard extends \Prado\Web\UI\WebControls\TWebControl implements \Prado\Web\UI\INamingContainer |
||
| 83 | { |
||
| 84 | /** |
||
| 85 | * Navigation commands. |
||
| 86 | */ |
||
| 87 | const CMD_PREVIOUS = 'PreviousStep'; |
||
| 88 | const CMD_NEXT = 'NextStep'; |
||
| 89 | const CMD_CANCEL = 'Cancel'; |
||
| 90 | const CMD_COMPLETE = 'Complete'; |
||
| 91 | const CMD_MOVETO = 'MoveTo'; |
||
| 92 | /** |
||
| 93 | * Side bar button ID |
||
| 94 | */ |
||
| 95 | const ID_SIDEBAR_BUTTON = 'SideBarButton'; |
||
| 96 | /** |
||
| 97 | * Side bar data list |
||
| 98 | */ |
||
| 99 | const ID_SIDEBAR_LIST = 'SideBarList'; |
||
| 100 | |||
| 101 | /** |
||
| 102 | * @var TMultiView multiview that contains the wizard steps |
||
| 103 | */ |
||
| 104 | private $_multiView; |
||
| 105 | /** |
||
| 106 | * @var mixed navigation template for the start step. |
||
| 107 | */ |
||
| 108 | private $_startNavigationTemplate; |
||
| 109 | /** |
||
| 110 | * @var mixed navigation template for internal steps. |
||
| 111 | */ |
||
| 112 | private $_stepNavigationTemplate; |
||
| 113 | /** |
||
| 114 | * @var mixed navigation template for the finish step. |
||
| 115 | */ |
||
| 116 | private $_finishNavigationTemplate; |
||
| 117 | /** |
||
| 118 | * @var mixed template for wizard header. |
||
| 119 | */ |
||
| 120 | private $_headerTemplate; |
||
| 121 | /** |
||
| 122 | * @var mixed template for the side bar. |
||
| 123 | */ |
||
| 124 | private $_sideBarTemplate; |
||
| 125 | /** |
||
| 126 | * @var TWizardStepCollection |
||
| 127 | */ |
||
| 128 | private $_wizardSteps; |
||
| 129 | /** |
||
| 130 | * @var TPanel container of the wizard header |
||
| 131 | */ |
||
| 132 | private $_header; |
||
| 133 | /** |
||
| 134 | * @var TPanel container of the wizard step content |
||
| 135 | */ |
||
| 136 | private $_stepContent; |
||
| 137 | /** |
||
| 138 | * @var TPanel container of the wizard side bar |
||
| 139 | */ |
||
| 140 | private $_sideBar; |
||
| 141 | /** |
||
| 142 | * @var TPanel navigation panel |
||
| 143 | */ |
||
| 144 | private $_navigation; |
||
| 145 | /** |
||
| 146 | * @var TWizardNavigationContainer container of the start navigation |
||
| 147 | */ |
||
| 148 | private $_startNavigation; |
||
| 149 | /** |
||
| 150 | * @var TWizardNavigationContainer container of the step navigation |
||
| 151 | */ |
||
| 152 | private $_stepNavigation; |
||
| 153 | /** |
||
| 154 | * @var TWizardNavigationContainer container of the finish navigation |
||
| 155 | */ |
||
| 156 | private $_finishNavigation; |
||
| 157 | /** |
||
| 158 | * @var bool whether ActiveStepIndex was already set |
||
| 159 | */ |
||
| 160 | private $_activeStepIndexSet = false; |
||
| 161 | /** |
||
| 162 | * @var TDataList side bar data list. |
||
| 163 | */ |
||
| 164 | private $_sideBarDataList; |
||
| 165 | /** |
||
| 166 | * @var bool whether navigation should be cancelled (a status set in OnSideBarButtonClick) |
||
| 167 | */ |
||
| 168 | private $_cancelNavigation = false; |
||
| 169 | |||
| 170 | /** |
||
| 171 | * @return string tag name for the wizard |
||
| 172 | */ |
||
| 173 | protected function getTagName() |
||
| 177 | |||
| 178 | /** |
||
| 179 | * Adds {@link TWizardStep} objects into step collection. |
||
| 180 | * This method overrides the parent implementation and is |
||
| 181 | * invoked when template is being instantiated. |
||
| 182 | * @param mixed $object object instantiated in template |
||
| 183 | */ |
||
| 184 | public function addParsedObject($object) |
||
| 190 | |||
| 191 | /** |
||
| 192 | * @return TWizardStep the currently active wizard step |
||
| 193 | */ |
||
| 194 | public function getActiveStep() |
||
| 198 | |||
| 199 | /** |
||
| 200 | * @param TWizardStep $step step to be activated |
||
| 201 | * @throws TInvalidOperationException if the step is not in the wizard step collection |
||
| 202 | */ |
||
| 203 | public function setActiveStep($step) |
||
| 210 | |||
| 211 | /** |
||
| 212 | * @return int the zero-based index of the active wizard step |
||
| 213 | */ |
||
| 214 | public function getActiveStepIndex() |
||
| 218 | |||
| 219 | /** |
||
| 220 | * @param int $value the zero-based index of the wizard step to be activated |
||
| 221 | */ |
||
| 222 | public function setActiveStepIndex($value) |
||
| 235 | |||
| 236 | /** |
||
| 237 | * @return TWizardStepCollection collection of wizard steps |
||
| 238 | */ |
||
| 239 | public function getWizardSteps() |
||
| 246 | |||
| 247 | /** |
||
| 248 | * @return bool whether to display a cancel button in each wizard step. Defaults to false. |
||
| 249 | */ |
||
| 250 | public function getShowCancelButton() |
||
| 254 | |||
| 255 | /** |
||
| 256 | * @param bool $value whether to display a cancel button in each wizard step. |
||
| 257 | */ |
||
| 258 | public function setShowCancelButton($value) |
||
| 262 | |||
| 263 | /** |
||
| 264 | * @return bool whether to display a side bar that contains links to wizard steps. Defaults to true. |
||
| 265 | */ |
||
| 266 | public function getShowSideBar() |
||
| 270 | |||
| 271 | /** |
||
| 272 | * @param bool $value whether to display a side bar that contains links to wizard steps. |
||
| 273 | */ |
||
| 274 | public function setShowSideBar($value) |
||
| 278 | |||
| 279 | /** |
||
| 280 | * @return ITemplate navigation template for the start step. Defaults to null. |
||
| 281 | */ |
||
| 282 | public function getStartNavigationTemplate() |
||
| 286 | |||
| 287 | /** |
||
| 288 | * @param ITemplate $value navigation template for the start step. |
||
| 289 | */ |
||
| 290 | public function setStartNavigationTemplate($value) |
||
| 295 | |||
| 296 | /** |
||
| 297 | * @return ITemplate navigation template for internal steps. Defaults to null. |
||
| 298 | */ |
||
| 299 | public function getStepNavigationTemplate() |
||
| 303 | |||
| 304 | /** |
||
| 305 | * @param ITemplate $value navigation template for internal steps. |
||
| 306 | */ |
||
| 307 | public function setStepNavigationTemplate($value) |
||
| 312 | |||
| 313 | /** |
||
| 314 | * @return ITemplate navigation template for the finish step. Defaults to null. |
||
| 315 | */ |
||
| 316 | public function getFinishNavigationTemplate() |
||
| 320 | |||
| 321 | /** |
||
| 322 | * @param ITemplate $value navigation template for the finish step. |
||
| 323 | */ |
||
| 324 | public function setFinishNavigationTemplate($value) |
||
| 329 | |||
| 330 | /** |
||
| 331 | * @return ITemplate template for wizard header. Defaults to null. |
||
| 332 | */ |
||
| 333 | public function getHeaderTemplate() |
||
| 337 | |||
| 338 | /** |
||
| 339 | * @param ITemplate $value template for wizard header. |
||
| 340 | */ |
||
| 341 | public function setHeaderTemplate($value) |
||
| 346 | |||
| 347 | /** |
||
| 348 | * @return ITemplate template for the side bar. Defaults to null. |
||
| 349 | */ |
||
| 350 | public function getSideBarTemplate() |
||
| 354 | |||
| 355 | /** |
||
| 356 | * @param ITemplate $value template for the side bar. |
||
| 357 | */ |
||
| 358 | public function setSideBarTemplate($value) |
||
| 363 | |||
| 364 | /** |
||
| 365 | * @return string header text. Defaults to ''. |
||
| 366 | */ |
||
| 367 | public function getHeaderText() |
||
| 371 | |||
| 372 | /** |
||
| 373 | * @param string $value header text. |
||
| 374 | */ |
||
| 375 | public function setHeaderText($value) |
||
| 379 | |||
| 380 | /** |
||
| 381 | * @return string the URL that the browser will be redirected to if the cancel button in the |
||
| 382 | * wizard is clicked. Defaults to ''. |
||
| 383 | */ |
||
| 384 | public function getCancelDestinationUrl() |
||
| 388 | |||
| 389 | /** |
||
| 390 | * @param string $value the URL that the browser will be redirected to if the cancel button in the |
||
| 391 | * wizard is clicked. |
||
| 392 | */ |
||
| 393 | public function setCancelDestinationUrl($value) |
||
| 397 | |||
| 398 | /** |
||
| 399 | * @return string the URL that the browser will be redirected to if the wizard finishes. |
||
| 400 | * Defaults to ''. |
||
| 401 | */ |
||
| 402 | public function getFinishDestinationUrl() |
||
| 406 | |||
| 407 | /** |
||
| 408 | * @param string $value the URL that the browser will be redirected to if the wizard finishes. |
||
| 409 | */ |
||
| 410 | public function setFinishDestinationUrl($value) |
||
| 414 | |||
| 415 | /** |
||
| 416 | * @return TStyle the style for the buttons displayed in the side bar. |
||
| 417 | */ |
||
| 418 | View Code Duplication | public function getSideBarButtonStyle() |
|
| 426 | |||
| 427 | /** |
||
| 428 | * @return TStyle the style common for all navigation buttons. |
||
| 429 | */ |
||
| 430 | View Code Duplication | public function getNavigationButtonStyle() |
|
| 438 | |||
| 439 | /** |
||
| 440 | * @return TWizardNavigationButtonStyle the style for the next button in the start wizard step. |
||
| 441 | */ |
||
| 442 | View Code Duplication | public function getStartNextButtonStyle() |
|
| 451 | |||
| 452 | /** |
||
| 453 | * @return TWizardNavigationButtonStyle the style for the next button in each internal wizard step. |
||
| 454 | */ |
||
| 455 | View Code Duplication | public function getStepNextButtonStyle() |
|
| 464 | |||
| 465 | /** |
||
| 466 | * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step. |
||
| 467 | */ |
||
| 468 | View Code Duplication | public function getStepPreviousButtonStyle() |
|
| 477 | |||
| 478 | /** |
||
| 479 | * @return TWizardNavigationButtonStyle the style for the complete button in the finish wizard step. |
||
| 480 | */ |
||
| 481 | View Code Duplication | public function getFinishCompleteButtonStyle() |
|
| 490 | |||
| 491 | /** |
||
| 492 | * @return TWizardNavigationButtonStyle the style for the previous button in the start wizard step. |
||
| 493 | */ |
||
| 494 | View Code Duplication | public function getFinishPreviousButtonStyle() |
|
| 503 | |||
| 504 | /** |
||
| 505 | * @return TWizardNavigationButtonStyle the style for the cancel button |
||
| 506 | */ |
||
| 507 | View Code Duplication | public function getCancelButtonStyle() |
|
| 516 | |||
| 517 | /** |
||
| 518 | * @return TPanelStyle the style for the side bar. |
||
| 519 | */ |
||
| 520 | View Code Duplication | public function getSideBarStyle() |
|
| 528 | |||
| 529 | /** |
||
| 530 | * @return TPanelStyle the style for the header. |
||
| 531 | */ |
||
| 532 | View Code Duplication | public function getHeaderStyle() |
|
| 540 | |||
| 541 | /** |
||
| 542 | * @return TPanelStyle the style for each internal wizard step. |
||
| 543 | */ |
||
| 544 | View Code Duplication | public function getStepStyle() |
|
| 552 | |||
| 553 | /** |
||
| 554 | * @return TPanelStyle the style for the navigation panel. |
||
| 555 | */ |
||
| 556 | View Code Duplication | public function getNavigationStyle() |
|
| 564 | |||
| 565 | /** |
||
| 566 | * @return bool whether to use default layout to arrange side bar and the rest wizard components. Defaults to true. |
||
| 567 | */ |
||
| 568 | public function getUseDefaultLayout() |
||
| 572 | |||
| 573 | /** |
||
| 574 | * @param bool $value whether to use default layout to arrange side bar and the rest wizard components. |
||
| 575 | * If true, an HTML table will be used which places the side bar in the left cell |
||
| 576 | * while the rest components in the right cell. |
||
| 577 | */ |
||
| 578 | public function setUseDefaultLayout($value) |
||
| 582 | |||
| 583 | /** |
||
| 584 | * @return TPanel container of the wizard header |
||
| 585 | */ |
||
| 586 | public function getHeader() |
||
| 590 | |||
| 591 | /** |
||
| 592 | * @return TPanel container of the wizard step content |
||
| 593 | */ |
||
| 594 | public function getStepContent() |
||
| 598 | |||
| 599 | /** |
||
| 600 | * @return TPanel container of the wizard side bar |
||
| 601 | */ |
||
| 602 | public function getSideBar() |
||
| 606 | |||
| 607 | /** |
||
| 608 | * @return TWizardNavigationContainer container of the start navigation |
||
| 609 | */ |
||
| 610 | public function getStartNavigation() |
||
| 614 | |||
| 615 | /** |
||
| 616 | * @return TWizardNavigationContainer container of the step navigation |
||
| 617 | */ |
||
| 618 | public function getStepNavigation() |
||
| 622 | |||
| 623 | /** |
||
| 624 | * @return TWizardNavigationContainer container of the finish navigation |
||
| 625 | */ |
||
| 626 | public function getFinishNavigation() |
||
| 630 | |||
| 631 | /** |
||
| 632 | * Raises <b>OnActiveStepChanged</b> event. |
||
| 633 | * This event is raised when the current visible step is changed in the |
||
| 634 | * wizard. |
||
| 635 | * @param TEventParameter $param event parameter |
||
| 636 | */ |
||
| 637 | public function onActiveStepChanged($param) |
||
| 641 | |||
| 642 | /** |
||
| 643 | * Raises <b>OnCancelButtonClick</b> event. |
||
| 644 | * This event is raised when a cancel navigation button is clicked in the |
||
| 645 | * current active step. |
||
| 646 | * @param TEventParameter $param event parameter |
||
| 647 | */ |
||
| 648 | public function onCancelButtonClick($param) |
||
| 655 | |||
| 656 | /** |
||
| 657 | * Raises <b>OnCompleteButtonClick</b> event. |
||
| 658 | * This event is raised when a finish navigation button is clicked in the |
||
| 659 | * current active step. |
||
| 660 | * @param TWizardNavigationEventParameter $param event parameter |
||
| 661 | */ |
||
| 662 | public function onCompleteButtonClick($param) |
||
| 669 | |||
| 670 | /** |
||
| 671 | * Raises <b>OnNextButtonClick</b> event. |
||
| 672 | * This event is raised when a next navigation button is clicked in the |
||
| 673 | * current active step. |
||
| 674 | * @param TWizardNavigationEventParameter $param event parameter |
||
| 675 | */ |
||
| 676 | public function onNextButtonClick($param) |
||
| 680 | |||
| 681 | /** |
||
| 682 | * Raises <b>OnPreviousButtonClick</b> event. |
||
| 683 | * This event is raised when a previous navigation button is clicked in the |
||
| 684 | * current active step. |
||
| 685 | * @param TWizardNavigationEventParameter $param event parameter |
||
| 686 | */ |
||
| 687 | public function onPreviousButtonClick($param) |
||
| 691 | |||
| 692 | /** |
||
| 693 | * Raises <b>OnSideBarButtonClick</b> event. |
||
| 694 | * This event is raised when a link button in the side bar is clicked. |
||
| 695 | * @param TWizardNavigationEventParameter $param event parameter |
||
| 696 | */ |
||
| 697 | public function onSideBarButtonClick($param) |
||
| 701 | |||
| 702 | /** |
||
| 703 | * Returns the multiview that holds the wizard steps. |
||
| 704 | * This method should only be used by control developers. |
||
| 705 | * @return TMultiView the multiview holding wizard steps |
||
| 706 | */ |
||
| 707 | public function getMultiView() |
||
| 717 | |||
| 718 | /** |
||
| 719 | * Adds a wizard step to the multiview. |
||
| 720 | * This method should only be used by control developers. |
||
| 721 | * It is invoked when a step is added into the step collection of the wizard. |
||
| 722 | * @param TWizardStep $step wizard step to be added into multiview. |
||
| 723 | */ |
||
| 724 | public function addedWizardStep($step) |
||
| 732 | |||
| 733 | /** |
||
| 734 | * Removes a wizard step from the multiview. |
||
| 735 | * This method should only be used by control developers. |
||
| 736 | * It is invoked when a step is removed from the step collection of the wizard. |
||
| 737 | * @param TWizardStep $step wizard step to be removed from multiview. |
||
| 738 | */ |
||
| 739 | public function removedWizardStep($step) |
||
| 744 | |||
| 745 | /** |
||
| 746 | * Creates the child controls of the wizard. |
||
| 747 | * This method overrides the parent implementation. |
||
| 748 | * @param TEventParameter $param event parameter |
||
| 749 | */ |
||
| 750 | public function onInit($param) |
||
| 759 | |||
| 760 | /** |
||
| 761 | * Saves the current active step index into history. |
||
| 762 | * This method is invoked by the framework when the control state is being saved. |
||
| 763 | */ |
||
| 764 | public function saveState() |
||
| 772 | |||
| 773 | /** |
||
| 774 | * Indicates the wizard needs to recreate all child controls. |
||
| 775 | */ |
||
| 776 | protected function requiresControlsRecreation() |
||
| 782 | |||
| 783 | /** |
||
| 784 | * Renders the wizard. |
||
| 785 | * @param THtmlWriter $writer |
||
| 786 | */ |
||
| 787 | public function render($writer) |
||
| 813 | |||
| 814 | /** |
||
| 815 | * Applies various properties to the components of wizard |
||
| 816 | */ |
||
| 817 | protected function applyControlProperties() |
||
| 824 | |||
| 825 | /** |
||
| 826 | * Applies properties to the wizard header |
||
| 827 | */ |
||
| 828 | protected function applyHeaderProperties() |
||
| 838 | |||
| 839 | /** |
||
| 840 | * Applies properties to the wizard sidebar |
||
| 841 | */ |
||
| 842 | protected function applySideBarProperties() |
||
| 861 | |||
| 862 | /** |
||
| 863 | * Applies properties to the wizard step content |
||
| 864 | */ |
||
| 865 | protected function applyStepContentProperties() |
||
| 871 | |||
| 872 | /** |
||
| 873 | * Apply properties to various navigation panels. |
||
| 874 | */ |
||
| 875 | protected function applyNavigationProperties() |
||
| 987 | |||
| 988 | /** |
||
| 989 | * @return TStack history containing step indexes that were navigated before |
||
| 990 | */ |
||
| 991 | protected function getHistory() |
||
| 999 | |||
| 1000 | /** |
||
| 1001 | * Determines the type of the specified wizard step. |
||
| 1002 | * @param TWizardStep $wizardStep * @return TWizardStepType type of the step |
||
| 1003 | */ |
||
| 1004 | protected function getStepType($wizardStep) |
||
| 1026 | |||
| 1027 | /** |
||
| 1028 | * Clears up everything within the wizard. |
||
| 1029 | */ |
||
| 1030 | protected function reset() |
||
| 1042 | |||
| 1043 | /** |
||
| 1044 | * Creates child controls within the wizard |
||
| 1045 | */ |
||
| 1046 | public function createChildControls() |
||
| 1055 | |||
| 1056 | /** |
||
| 1057 | * Creates the wizard header. |
||
| 1058 | */ |
||
| 1059 | protected function createHeader() |
||
| 1069 | |||
| 1070 | /** |
||
| 1071 | * Creates the wizard side bar |
||
| 1072 | */ |
||
| 1073 | protected function createSideBar() |
||
| 1095 | |||
| 1096 | /** |
||
| 1097 | * Event handler for sidebar datalist's OnItemCommand event. |
||
| 1098 | * This method is used internally by wizard. It mainly |
||
| 1099 | * sets the active step index according to the button clicked in the sidebar. |
||
| 1100 | * @param mixed $sender sender of the event |
||
| 1101 | * @param TDataListCommandEventParameter $param |
||
| 1102 | */ |
||
| 1103 | public function dataListItemCommand($sender, $param) |
||
| 1131 | |||
| 1132 | /** |
||
| 1133 | * Event handler for sidebar datalist's OnItemDataBound event. |
||
| 1134 | * This method is used internally by wizard. It mainly configures |
||
| 1135 | * the buttons in the sidebar datalist. |
||
| 1136 | * @param mixed $sender sender of the event |
||
| 1137 | * @param TDataListItemEventParameter $param |
||
| 1138 | */ |
||
| 1139 | public function dataListItemDataBound($sender, $param) |
||
| 1160 | |||
| 1161 | /** |
||
| 1162 | * Creates wizard step content. |
||
| 1163 | */ |
||
| 1164 | protected function createStepContent() |
||
| 1179 | |||
| 1180 | /** |
||
| 1181 | * Creates navigation panel. |
||
| 1182 | */ |
||
| 1183 | protected function createNavigation() |
||
| 1203 | |||
| 1204 | /** |
||
| 1205 | * Creates start navigation panel. |
||
| 1206 | */ |
||
| 1207 | View Code Duplication | protected function createStartNavigation() |
|
| 1216 | |||
| 1217 | /** |
||
| 1218 | * Creates step navigation panel. |
||
| 1219 | */ |
||
| 1220 | View Code Duplication | protected function createStepNavigation() |
|
| 1229 | |||
| 1230 | /** |
||
| 1231 | * Creates finish navigation panel. |
||
| 1232 | */ |
||
| 1233 | View Code Duplication | protected function createFinishNavigation() |
|
| 1242 | |||
| 1243 | /** |
||
| 1244 | * Updates the sidebar datalist if any. |
||
| 1245 | * This method is invoked when any wizard step is changed. |
||
| 1246 | */ |
||
| 1247 | public function wizardStepsChanged() |
||
| 1255 | |||
| 1256 | /** |
||
| 1257 | * Determines the index of the previous step based on history. |
||
| 1258 | * @param bool $popStack whether the first item in the history stack should be popped |
||
| 1259 | * up after calling this method. |
||
| 1260 | */ |
||
| 1261 | protected function getPreviousStepIndex($popStack) |
||
| 1285 | |||
| 1286 | /** |
||
| 1287 | * @return bool whether navigation to the previous step is allowed |
||
| 1288 | */ |
||
| 1289 | protected function allowNavigationToPreviousStep() |
||
| 1297 | |||
| 1298 | /** |
||
| 1299 | * @param int $index index of the step |
||
| 1300 | * @return bool whether navigation to the specified step is allowed |
||
| 1301 | */ |
||
| 1302 | protected function allowNavigationToStep($index) |
||
| 1310 | |||
| 1311 | /** |
||
| 1312 | * Handles bubbled events. |
||
| 1313 | * This method mainly translate certain command events into |
||
| 1314 | * wizard-specific events. |
||
| 1315 | * @param mixed $sender sender of the original command event |
||
| 1316 | * @param TEventParameter $param event parameter |
||
| 1317 | * @throws TInvalidDataValueException if a navigation command is associated with an invalid parameter |
||
| 1318 | */ |
||
| 1319 | public function bubbleEvent($sender, $param) |
||
| 1407 | } |
||
| 1408 |
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.