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 Validation_Core 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 Validation_Core, and based on these observations, apply Extract Interface, too.
| 1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
| 12 | class Validation_Core extends ArrayObject |
||
| 13 | { |
||
| 14 | |||
| 15 | // Filters |
||
| 16 | protected $pre_filters = array(); |
||
| 17 | protected $post_filters = array(); |
||
| 18 | |||
| 19 | // Rules and callbacks |
||
| 20 | protected $rules = array(); |
||
| 21 | protected $callbacks = array(); |
||
| 22 | |||
| 23 | // Rules that are allowed to run on empty fields |
||
| 24 | protected $empty_rules = array('required', 'matches'); |
||
| 25 | |||
| 26 | // Errors |
||
| 27 | protected $errors = array(); |
||
| 28 | protected $messages = array(); |
||
| 29 | |||
| 30 | // Fields that are expected to be arrays |
||
| 31 | protected $array_fields = array(); |
||
| 32 | |||
| 33 | // Checks if there is data to validate. |
||
| 34 | protected $submitted; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * Creates a new Validation instance. |
||
| 38 | * |
||
| 39 | * @param array array to use for validation |
||
| 40 | * @return object |
||
|
|
|||
| 41 | */ |
||
| 42 | public static function factory(array $array) |
||
| 46 | |||
| 47 | /** |
||
| 48 | * Sets the unique "any field" key and creates an ArrayObject from the |
||
| 49 | * passed array. |
||
| 50 | * |
||
| 51 | * @param array array to validate |
||
| 52 | * @return void |
||
| 53 | */ |
||
| 54 | public function __construct(array $array) |
||
| 61 | |||
| 62 | /** |
||
| 63 | * Magic clone method, clears errors and messages. |
||
| 64 | * |
||
| 65 | * @return void |
||
| 66 | */ |
||
| 67 | public function __clone() |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Create a copy of the current validation rules and change the array. |
||
| 75 | * |
||
| 76 | * @chainable |
||
| 77 | * @param array new array to validate |
||
| 78 | * @return Validation_Core |
||
| 79 | */ |
||
| 80 | public function copy(array $array) |
||
| 88 | |||
| 89 | /** |
||
| 90 | * Test if the data has been submitted. |
||
| 91 | * |
||
| 92 | * @return boolean |
||
| 93 | */ |
||
| 94 | public function submitted($value = null) |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Returns an array of all the field names that have filters, rules, or callbacks. |
||
| 105 | * |
||
| 106 | * @return array |
||
| 107 | */ |
||
| 108 | public function field_names() |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Returns the array values of the current object. |
||
| 126 | * |
||
| 127 | * @return array |
||
| 128 | */ |
||
| 129 | public function as_array() |
||
| 133 | |||
| 134 | /** |
||
| 135 | * Returns the ArrayObject values, removing all inputs without rules. |
||
| 136 | * To choose specific inputs, list the field name as arguments. |
||
| 137 | * |
||
| 138 | * @param boolean return only fields with filters, rules, and callbacks |
||
| 139 | * @return array |
||
| 140 | */ |
||
| 141 | public function safe_array() |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Add additional rules that will forced, even for empty fields. All arguments |
||
| 175 | * passed will be appended to the list. |
||
| 176 | * |
||
| 177 | * @chainable |
||
| 178 | * @param string rule name |
||
| 179 | * @return Validation_Core |
||
| 180 | */ |
||
| 181 | public function allow_empty_rules($rules) |
||
| 191 | |||
| 192 | /** |
||
| 193 | * Converts a filter, rule, or callback into a fully-qualified callback array. |
||
| 194 | * |
||
| 195 | * @return callable |
||
| 196 | */ |
||
| 197 | protected function callback($callback) |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Add a pre-filter to one or more inputs. Pre-filters are applied before |
||
| 236 | * rules or callbacks are executed. |
||
| 237 | * |
||
| 238 | * @chainable |
||
| 239 | * @param callback filter |
||
| 240 | * @param string fields to apply filter to, use TRUE for all fields |
||
| 241 | * @return Validation_Core |
||
| 242 | */ |
||
| 243 | View Code Duplication | public function pre_filter($filter, $field = true) |
|
| 264 | |||
| 265 | /** |
||
| 266 | * Add a post-filter to one or more inputs. Post-filters are applied after |
||
| 267 | * rules and callbacks have been executed. |
||
| 268 | * |
||
| 269 | * @chainable |
||
| 270 | * @param callback filter |
||
| 271 | * @param string fields to apply filter to, use TRUE for all fields |
||
| 272 | * @return Validation_Core |
||
| 273 | */ |
||
| 274 | View Code Duplication | public function post_filter($filter, $field = true) |
|
| 295 | |||
| 296 | /** |
||
| 297 | * Add rules to a field. Validation rules may only return TRUE or FALSE and |
||
| 298 | * can not manipulate the value of a field. |
||
| 299 | * |
||
| 300 | * @chainable |
||
| 301 | * @param string field name |
||
| 302 | * @param callback rules (one or more arguments) |
||
| 303 | * @return Validation_Core |
||
| 304 | */ |
||
| 305 | public function add_rules($field, $rules) |
||
| 345 | |||
| 346 | /** |
||
| 347 | * Add callbacks to a field. Callbacks must accept the Validation object |
||
| 348 | * and the input name. Callback returns are not processed. |
||
| 349 | * |
||
| 350 | * @chainable |
||
| 351 | * @param string field name |
||
| 352 | * @param callbacks callbacks (unlimited number) |
||
| 353 | * @return Validation_Core |
||
| 354 | */ |
||
| 355 | View Code Duplication | public function add_callbacks($field, $callbacks) |
|
| 376 | |||
| 377 | /** |
||
| 378 | * Validate by processing pre-filters, rules, callbacks, and post-filters. |
||
| 379 | * All fields that have filters, rules, or callbacks will be initialized if |
||
| 380 | * they are undefined. Validation will only be run if there is data already |
||
| 381 | * in the array. |
||
| 382 | * |
||
| 383 | * @param object Validation object, used only for recursion |
||
| 384 | * @param object name of field for errors |
||
| 385 | * @return bool |
||
| 386 | */ |
||
| 387 | public function validate($object = null, $field_name = null) |
||
| 549 | |||
| 550 | /** |
||
| 551 | * Add an error to an input. |
||
| 552 | * |
||
| 553 | * @chainable |
||
| 554 | * @param string input name |
||
| 555 | * @param string unique error name |
||
| 556 | * @return Validation_Core |
||
| 557 | */ |
||
| 558 | public function add_error($field, $name) |
||
| 564 | |||
| 565 | /** |
||
| 566 | * Sets or returns the message for an input. |
||
| 567 | * |
||
| 568 | * @chainable |
||
| 569 | * @param string input key |
||
| 570 | * @param string message to set |
||
| 571 | * @return string|object |
||
| 572 | */ |
||
| 573 | public function message($input = null, $message = null) |
||
| 600 | |||
| 601 | /** |
||
| 602 | * Return the errors array. |
||
| 603 | * |
||
| 604 | * @param boolean load errors from a lang file |
||
| 605 | * @return array |
||
| 606 | */ |
||
| 607 | public function errors($file = null) |
||
| 626 | |||
| 627 | /** |
||
| 628 | * Rule: required. Generates an error if the field has an empty value. |
||
| 629 | * |
||
| 630 | * @param mixed input value |
||
| 631 | * @return bool |
||
| 632 | */ |
||
| 633 | public function required($str) |
||
| 646 | |||
| 647 | /** |
||
| 648 | * Rule: matches. Generates an error if the field does not match one or more |
||
| 649 | * other fields. |
||
| 650 | * |
||
| 651 | * @param mixed input value |
||
| 652 | * @param array input names to match against |
||
| 653 | * @return bool |
||
| 654 | */ |
||
| 655 | public function matches($str, array $inputs) |
||
| 665 | |||
| 666 | /** |
||
| 667 | * Rule: length. Generates an error if the field is too long or too short. |
||
| 668 | * |
||
| 669 | * @param mixed input value |
||
| 670 | * @param array minimum, maximum, or exact length to match |
||
| 671 | * @return bool |
||
| 672 | */ |
||
| 673 | public function length($str, array $length) |
||
| 694 | |||
| 695 | /** |
||
| 696 | * Rule: depends_on. Generates an error if the field does not depend on one |
||
| 697 | * or more other fields. |
||
| 698 | * |
||
| 699 | * @param mixed field name |
||
| 700 | * @param array field names to check dependency |
||
| 701 | * @return bool |
||
| 702 | */ |
||
| 703 | public function depends_on($field, array $fields) |
||
| 713 | |||
| 714 | /** |
||
| 715 | * Rule: chars. Generates an error if the field contains characters outside of the list. |
||
| 716 | * |
||
| 717 | * @param string field value |
||
| 718 | * @param array allowed characters |
||
| 719 | * @return bool |
||
| 720 | */ |
||
| 721 | public function chars($value, array $chars) |
||
| 725 | } // End Validation |
||
| 726 |
This check looks for the generic type
arrayas a return type and suggests a more specific type. This type is inferred from the actual code.