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 TTextBox 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 TTextBox, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 58 | class TTextBox extends \Prado\Web\UI\WebControls\TWebControl implements \Prado\Web\UI\IPostBackDataHandler, \Prado\Web\UI\IValidatable, \Prado\IDataRenderer |
||
| 59 | { |
||
| 60 | /** |
||
| 61 | * Default number of rows (for MultiLine text box) |
||
| 62 | */ |
||
| 63 | const DEFAULT_ROWS = 4; |
||
| 64 | /** |
||
| 65 | * Default number of columns (for MultiLine text box) |
||
| 66 | */ |
||
| 67 | const DEFAULT_COLUMNS = 20; |
||
| 68 | /** |
||
| 69 | * @var mixed safe text parser |
||
| 70 | */ |
||
| 71 | private static $_safeTextParser = null; |
||
| 72 | /** |
||
| 73 | * @var string safe textbox content with javascript stripped off |
||
| 74 | */ |
||
| 75 | private $_safeText; |
||
| 76 | private $_dataChanged = false; |
||
| 77 | private $_isValid = true; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * @return string tag name of the textbox |
||
| 81 | */ |
||
| 82 | protected function getTagName() |
||
| 86 | |||
| 87 | /** |
||
| 88 | * @return bool whether to render javascript. |
||
| 89 | */ |
||
| 90 | public function getEnableClientScript() |
||
| 94 | |||
| 95 | /** |
||
| 96 | * @param bool $value whether to render javascript. |
||
| 97 | */ |
||
| 98 | public function setEnableClientScript($value) |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Adds attribute name-value pairs to renderer. |
||
| 105 | * This method overrides the parent implementation with additional textbox specific attributes. |
||
| 106 | * @param THtmlWriter $writer the writer used for the rendering purpose |
||
| 107 | */ |
||
| 108 | protected function addAttributesToRender($writer) |
||
| 222 | |||
| 223 | /** |
||
| 224 | * Renders the javascript for textbox. |
||
| 225 | * @param mixed $writer |
||
| 226 | */ |
||
| 227 | protected function renderClientControlScript($writer) |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Gets the name of the javascript class responsible for performing postback for this control. |
||
| 236 | * This method overrides the parent implementation. |
||
| 237 | * @return string the javascript class name |
||
| 238 | */ |
||
| 239 | protected function getClientClassName() |
||
| 243 | |||
| 244 | /** |
||
| 245 | * Gets the post back options for this textbox. |
||
| 246 | * @return array |
||
| 247 | */ |
||
| 248 | View Code Duplication | protected function getPostBackOptions() |
|
| 258 | |||
| 259 | /** |
||
| 260 | * Loads user input data. |
||
| 261 | * This method is primarly used by framework developers. |
||
| 262 | * @param string $key the key that can be used to retrieve data from the input data collection |
||
| 263 | * @param array $values the input data collection |
||
| 264 | * @return bool whether the data of the component has been changed |
||
| 265 | */ |
||
| 266 | public function loadPostData($key, $values) |
||
| 279 | |||
| 280 | /** |
||
| 281 | * Returns a value indicating whether postback has caused the control data change. |
||
| 282 | * This method is required by the \Prado\Web\UI\IPostBackDataHandler interface. |
||
| 283 | * @return bool whether postback has caused the control data change. False if the page is not in postback mode. |
||
| 284 | */ |
||
| 285 | public function getDataChanged() |
||
| 289 | |||
| 290 | /** |
||
| 291 | * Returns the value to be validated. |
||
| 292 | * This methid is required by \Prado\Web\UI\IValidatable interface. |
||
| 293 | * @return mixed the value of the property to be validated. |
||
| 294 | */ |
||
| 295 | public function getValidationPropertyValue() |
||
| 299 | |||
| 300 | /** |
||
| 301 | * Returns true if this control validated successfully. |
||
| 302 | * Defaults to true. |
||
| 303 | * @return bool wether this control validated successfully. |
||
| 304 | */ |
||
| 305 | public function getIsValid() |
||
| 309 | /** |
||
| 310 | * @param bool $value wether this control is valid. |
||
| 311 | */ |
||
| 312 | public function setIsValid($value) |
||
| 316 | |||
| 317 | /** |
||
| 318 | * Raises <b>OnTextChanged</b> event. |
||
| 319 | * This method is invoked when the value of the {@link getText Text} |
||
| 320 | * property changes on postback. |
||
| 321 | * If you override this method, be sure to call the parent implementation to ensure |
||
| 322 | * the invocation of the attached event handlers. |
||
| 323 | * @param TEventParameter $param event parameter to be passed to the event handlers |
||
| 324 | */ |
||
| 325 | public function onTextChanged($param) |
||
| 329 | |||
| 330 | /** |
||
| 331 | * Raises postdata changed event. |
||
| 332 | * This method is required by {@link \Prado\Web\UI\IPostBackDataHandler} interface. |
||
| 333 | * It is invoked by the framework when {@link getText Text} property |
||
| 334 | * is changed on postback. |
||
| 335 | * This method is primarly used by framework developers. |
||
| 336 | */ |
||
| 337 | public function raisePostDataChangedEvent() |
||
| 344 | |||
| 345 | /** |
||
| 346 | * Renders the body content of the textbox when it is in MultiLine text mode. |
||
| 347 | * @param THtmlWriter $writer the writer for rendering |
||
| 348 | */ |
||
| 349 | public function renderContents($writer) |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Renders an additional line-break after the opening tag when it |
||
| 358 | * is in MultiLine text mode. |
||
| 359 | * @param THtmlWriter $writer the writer used for the rendering purpose^M |
||
| 360 | */ |
||
| 361 | public function renderBeginTag($writer) |
||
| 368 | |||
| 369 | /** |
||
| 370 | * @return TTextBoxAutoCompleteType the AutoComplete type of the textbox |
||
| 371 | */ |
||
| 372 | public function getAutoCompleteType() |
||
| 376 | |||
| 377 | /** |
||
| 378 | * @param TTextBoxAutoCompleteType $value the AutoComplete type of the textbox, default value is TTextBoxAutoCompleteType::None. |
||
| 379 | * @throws TInvalidDataValueException if the input parameter is not a valid AutoComplete type |
||
| 380 | */ |
||
| 381 | public function setAutoCompleteType($value) |
||
| 385 | |||
| 386 | /** |
||
| 387 | * @return bool a value indicating whether an automatic postback to the server |
||
| 388 | * will occur whenever the user modifies the text in the TTextBox control and |
||
| 389 | * then tabs out of the component. Defaults to false. |
||
| 390 | */ |
||
| 391 | public function getAutoPostBack() |
||
| 395 | |||
| 396 | /** |
||
| 397 | * Sets the value indicating if postback automatically. |
||
| 398 | * An automatic postback to the server will occur whenever the user |
||
| 399 | * modifies the text in the TTextBox control and then tabs out of the component. |
||
| 400 | * @param bool $value the value indicating if postback automatically |
||
| 401 | */ |
||
| 402 | public function setAutoPostBack($value) |
||
| 406 | |||
| 407 | /** |
||
| 408 | * @return bool a value indicating whether the input text should be trimmed spaces. Defaults to false. |
||
| 409 | */ |
||
| 410 | public function getAutoTrim() |
||
| 414 | |||
| 415 | /** |
||
| 416 | * Sets the value indicating if the input text should be trimmed spaces |
||
| 417 | * @param bool $value the value indicating if the input text should be trimmed spaces |
||
| 418 | */ |
||
| 419 | public function setAutoTrim($value) |
||
| 423 | |||
| 424 | /** |
||
| 425 | * @return bool whether postback event trigger by this text box will cause input validation, default is true. |
||
| 426 | */ |
||
| 427 | public function getCausesValidation() |
||
| 431 | |||
| 432 | /** |
||
| 433 | * @param bool $value whether postback event trigger by this text box will cause input validation. |
||
| 434 | */ |
||
| 435 | public function setCausesValidation($value) |
||
| 439 | |||
| 440 | /** |
||
| 441 | * @return int the display width of the text box in characters, default is 0 meaning not set. |
||
| 442 | */ |
||
| 443 | public function getColumns() |
||
| 447 | |||
| 448 | /** |
||
| 449 | * Sets the display width of the text box in characters. |
||
| 450 | * @param int $value the display width, set it 0 to clear the setting |
||
| 451 | */ |
||
| 452 | public function setColumns($value) |
||
| 456 | |||
| 457 | /** |
||
| 458 | * @return int the maximum number of characters allowed in the text box, default is 0 meaning not set. |
||
| 459 | */ |
||
| 460 | public function getMaxLength() |
||
| 464 | |||
| 465 | /** |
||
| 466 | * Sets the maximum number of characters allowed in the text box. |
||
| 467 | * @param int $value the maximum length, set it 0 to clear the setting |
||
| 468 | */ |
||
| 469 | public function setMaxLength($value) |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @return bool whether the textbox is read only, default is false. |
||
| 476 | */ |
||
| 477 | public function getReadOnly() |
||
| 481 | |||
| 482 | /** |
||
| 483 | * @param bool $value whether the textbox is read only |
||
| 484 | */ |
||
| 485 | public function setReadOnly($value) |
||
| 489 | |||
| 490 | /** |
||
| 491 | * @return int the number of rows displayed in a multiline text box, default is 4 |
||
| 492 | */ |
||
| 493 | public function getRows() |
||
| 497 | |||
| 498 | /** |
||
| 499 | * Sets the number of rows displayed in a multiline text box. |
||
| 500 | * @param int $value the number of rows |
||
| 501 | */ |
||
| 502 | public function setRows($value) |
||
| 506 | |||
| 507 | /** |
||
| 508 | * @return bool whether password should be displayed in the textbox during postback. Defaults to false. This property only applies when TextMode='Password'. |
||
| 509 | */ |
||
| 510 | public function getPersistPassword() |
||
| 514 | |||
| 515 | /** |
||
| 516 | * @param bool $value whether password should be displayed in the textbox during postback. This property only applies when TextMode='Password'. |
||
| 517 | */ |
||
| 518 | public function setPersistPassword($value) |
||
| 522 | |||
| 523 | /** |
||
| 524 | * @return string the text content of the TTextBox control. |
||
| 525 | */ |
||
| 526 | public function getText() |
||
| 530 | |||
| 531 | /** |
||
| 532 | * Sets the text content of the TTextBox control. |
||
| 533 | * @param string $value the text content |
||
| 534 | */ |
||
| 535 | public function setText($value) |
||
| 540 | |||
| 541 | /** |
||
| 542 | * Returns the text content of the TTextBox control. |
||
| 543 | * This method is required by {@link \Prado\IDataRenderer}. |
||
| 544 | * It is the same as {@link getText()}. |
||
| 545 | * @return string the text content of the TTextBox control. |
||
| 546 | * @see getText |
||
| 547 | * @since 3.1.0 |
||
| 548 | */ |
||
| 549 | public function getData() |
||
| 553 | |||
| 554 | /** |
||
| 555 | * Sets the text content of the TTextBox control. |
||
| 556 | * This method is required by {@link \Prado\IDataRenderer}. |
||
| 557 | * It is the same as {@link setText()}. |
||
| 558 | * @param string $value the text content of the TTextBox control. |
||
| 559 | * @see setText |
||
| 560 | * @since 3.1.0 |
||
| 561 | */ |
||
| 562 | public function setData($value) |
||
| 566 | |||
| 567 | /** |
||
| 568 | * @return string safe text content with javascript stripped off |
||
| 569 | */ |
||
| 570 | public function getSafeText() |
||
| 577 | |||
| 578 | /** |
||
| 579 | * @return \HTMLPurifier safe text parser |
||
| 580 | */ |
||
| 581 | protected function getSafeTextParser() |
||
| 588 | |||
| 589 | /** |
||
| 590 | * @return TTextBoxMode the behavior mode of the TTextBox component. Defaults to TTextBoxMode::SingleLine. |
||
| 591 | */ |
||
| 592 | public function getTextMode() |
||
| 596 | |||
| 597 | /** |
||
| 598 | * Sets the behavior mode of the TTextBox component. |
||
| 599 | * @param TTextBoxMode $value the text mode |
||
| 600 | * @throws TInvalidDataValueException if the input value is not a valid text mode. |
||
| 601 | */ |
||
| 602 | public function setTextMode($value) |
||
| 606 | |||
| 607 | /** |
||
| 608 | * @return string the group of validators which the text box causes validation upon postback |
||
| 609 | */ |
||
| 610 | public function getValidationGroup() |
||
| 614 | |||
| 615 | /** |
||
| 616 | * @param string $value the group of validators which the text box causes validation upon postback |
||
| 617 | */ |
||
| 618 | public function setValidationGroup($value) |
||
| 622 | |||
| 623 | /** |
||
| 624 | * @return bool whether the text content wraps within a multiline text box. Defaults to true. |
||
| 625 | */ |
||
| 626 | public function getWrap() |
||
| 630 | |||
| 631 | /** |
||
| 632 | * Sets the value indicating whether the text content wraps within a multiline text box. |
||
| 633 | * @param bool $value whether the text content wraps within a multiline text box. |
||
| 634 | */ |
||
| 635 | public function setWrap($value) |
||
| 639 | |||
| 640 | /** |
||
| 641 | * Sets a custom configuration for HTMLPurifier. |
||
| 642 | * @param \HTMLPurifier_Config $value custom configuration |
||
| 643 | */ |
||
| 644 | public function setConfig(\HTMLPurifier_Config $value) |
||
| 648 | |||
| 649 | /** |
||
| 650 | * @return \HTMLPurifier_Config Configuration for HTMLPurifier. |
||
| 651 | */ |
||
| 652 | public function getConfig() |
||
| 657 | } |
||
| 658 |
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.