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 Hooks 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 Hooks, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 40 | class Hooks | ||
| 41 | { | ||
| 42 | /** | ||
| 43 | * Filters - holds list of hooks | ||
| 44 | * | ||
| 45 | * @var array | ||
| 46 | */ | ||
| 47 | protected $filters = array(); | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Merged Filters | ||
| 51 | * | ||
| 52 | * @var array | ||
| 53 | */ | ||
| 54 | protected $merged_filters = array(); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Actions | ||
| 58 | * | ||
| 59 | * @var array | ||
| 60 | */ | ||
| 61 | protected $actions = array(); | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Current Filter - holds the name of the current filter | ||
| 65 | * | ||
| 66 | * @var array | ||
| 67 | */ | ||
| 68 | protected $current_filter = array(); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Container for storing shortcode tags and their hook to call for the shortcode | ||
| 72 | * | ||
| 73 | * @var array | ||
| 74 | */ | ||
| 75 | public static $shortcode_tags = array(); | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Default priority | ||
| 79 | * | ||
| 80 | * @const int | ||
| 81 | */ | ||
| 82 | const PRIORITY_NEUTRAL = 50; | ||
| 83 | |||
| 84 | /** | ||
| 85 | * This class is not allowed to call from outside: private! | ||
| 86 | */ | ||
| 87 | 1 | protected function __construct() | |
| 90 | |||
| 91 | /** | ||
| 92 | * Prevent the object from being cloned. | ||
| 93 | */ | ||
| 94 | protected function __clone() | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Avoid serialization. | ||
| 100 | */ | ||
| 101 | public function __wakeup() | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Returns a Singleton instance of this class. | ||
| 107 | * | ||
| 108 | * @return Hooks | ||
| 109 | */ | ||
| 110 | 10 | public static function getInstance() | |
| 120 | |||
| 121 | /** | ||
| 122 | * FILTERS | ||
| 123 | */ | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Adds Hooks to a function or method to a specific filter action. | ||
| 127 | * | ||
| 128 | * @param string $tag <p> | ||
| 129 | * The name of the filter to hook the | ||
| 130 |    *                                       {@link $function_to_add} to. | ||
| 131 | * </p> | ||
| 132 | * @param string $function_to_add <p> | ||
| 133 | * The name of the function to be called | ||
| 134 | * when the filter is applied. | ||
| 135 | * </p> | ||
| 136 | * @param integer $priority <p> | ||
| 137 | * [optional] Used to specify the order in | ||
| 138 | * which the functions associated with a | ||
| 139 | * particular action are executed (default: 50). | ||
| 140 | * Lower numbers correspond with earlier execution, | ||
| 141 | * and functions with the same priority are executed | ||
| 142 | * in the order in which they were added to the action. | ||
| 143 | * </p> | ||
| 144 | * @param string $include_path <p> | ||
| 145 | * [optional] File to include before executing the callback. | ||
| 146 | * </p> | ||
| 147 | * | ||
| 148 | * @return boolean | ||
| 149 | */ | ||
| 150 | 7 | public function add_filter($tag, $function_to_add, $priority = self::PRIORITY_NEUTRAL, $include_path = null) | |
| 163 | |||
| 164 | /** | ||
| 165 | * Removes a function from a specified filter hook. | ||
| 166 | * | ||
| 167 | * @param string $tag <p>The filter hook to which the function to be removed is hooked.</p> | ||
| 168 | * @param mixed $function_to_remove <p>The name of the function which should be removed.</p> | ||
| 169 | * @param int $priority <p>[optional] The priority of the function (default: 50).</p> | ||
| 170 | * | ||
| 171 | * @return bool | ||
| 172 | */ | ||
| 173 | 1 | public function remove_filter($tag, $function_to_remove, $priority = self::PRIORITY_NEUTRAL) | |
| 190 | |||
| 191 | /** | ||
| 192 | * Remove all of the hooks from a filter. | ||
| 193 | * | ||
| 194 | * @param string $tag <p>The filter to remove hooks from.</p> | ||
| 195 | * @param bool $priority <p>The priority number to remove.</p> | ||
| 196 | * | ||
| 197 | * @return bool | ||
| 198 | */ | ||
| 199 | 4 | public function remove_all_filters($tag, $priority = false) | |
| 217 | |||
| 218 | /** | ||
| 219 | * Check if any filter has been registered for the given hook. | ||
| 220 | * | ||
| 221 | * <p> | ||
| 222 | * <br /> | ||
| 223 | * <strong>INFO:</strong> Use !== false to check if it's true! | ||
| 224 | * </p> | ||
| 225 | * | ||
| 226 | * @param string $tag <p>The name of the filter hook.</p> | ||
| 227 | * @param bool $function_to_check <p>[optional] Callback function name to check for </p> | ||
| 228 | * | ||
| 229 | * @return mixed <p> | ||
| 230 |    *                                       If {@link $function_to_check} is omitted, | ||
| 231 | * returns boolean for whether the hook has | ||
| 232 | * anything registered. | ||
| 233 | * When checking a specific function, the priority | ||
| 234 | * of that hook is returned, or false if the | ||
| 235 | * function is not attached. | ||
| 236 |    *                                       When using the {@link $function_to_check} argument, | ||
| 237 | * this function may return a non-boolean value that | ||
| 238 | * evaluates to false | ||
| 239 | * (e.g.) 0, so use the === operator for testing the return value. | ||
| 240 | * </p> | ||
| 241 | */ | ||
| 242 | 3 | public function has_filter($tag, $function_to_check = false) | |
| 261 | |||
| 262 | /** | ||
| 263 | * Call the functions added to a filter hook. | ||
| 264 | * | ||
| 265 | * <p> | ||
| 266 | * <br /> | ||
| 267 | * <strong>INFO:</strong> Additional variables passed to the functions hooked to <tt>$tag</tt>. | ||
| 268 | * </p> | ||
| 269 | * | ||
| 270 | * @param string|array $tag <p>The name of the filter hook.</p> | ||
| 271 | * @param mixed $value <p>The value on which the filters hooked to <tt>$tag</tt> are applied on.</p> | ||
| 272 | * | ||
| 273 | * @return mixed <p>The filtered value after all hooked functions are applied to it.</p> | ||
| 274 | */ | ||
| 275 | 4 | public function apply_filters($tag, $value) | |
| 331 | |||
| 332 | /** | ||
| 333 | * Execute functions hooked on a specific filter hook, specifying arguments in an array. | ||
| 334 | * | ||
| 335 | * @param string $tag <p>The name of the filter hook.</p> | ||
| 336 | * @param array $args <p>The arguments supplied to the functions hooked to <tt>$tag</tt></p> | ||
| 337 | * | ||
| 338 | * @return mixed <p>The filtered value after all hooked functions are applied to it.</p> | ||
| 339 | */ | ||
| 340 | 1 | public function apply_filters_ref_array($tag, $args) | |
| 387 | |||
| 388 | /** | ||
| 389 | * Hooks a function on to a specific action. | ||
| 390 | * | ||
| 391 | * @param string $tag <p> | ||
| 392 | * The name of the action to which the | ||
| 393 | * <tt>$function_to_add</tt> is hooked. | ||
| 394 | * </p> | ||
| 395 | * @param string $function_to_add <p>The name of the function you wish to be called.</p> | ||
| 396 | * @param integer $priority <p> | ||
| 397 | * [optional] Used to specify the order in which | ||
| 398 | * the functions associated with a particular | ||
| 399 | * action are executed (default: 50). | ||
| 400 | * Lower numbers correspond with earlier execution, | ||
| 401 | * and functions with the same priority are executed | ||
| 402 | * in the order in which they were added to the action. | ||
| 403 | * </p> | ||
| 404 | * @param string $include_path <p>[optional] File to include before executing the callback.</p> | ||
| 405 | * | ||
| 406 | * @return bool | ||
| 407 | */ | ||
| 408 | 5 | public function add_action($tag, $function_to_add, $priority = self::PRIORITY_NEUTRAL, $include_path = null) | |
| 412 | |||
| 413 | /** | ||
| 414 | * Check if any action has been registered for a hook. | ||
| 415 | * | ||
| 416 | * <p> | ||
| 417 | * <br /> | ||
| 418 | * <strong>INFO:</strong> Use !== false to check if it's true! | ||
| 419 | * </p> | ||
| 420 | * | ||
| 421 | * @param string $tag <p>The name of the action hook.</p> | ||
| 422 | * @param bool|string $function_to_check <p>[optional]</p> | ||
| 423 | * | ||
| 424 | * @return mixed <p> | ||
| 425 | * If <tt>$function_to_check</tt> is omitted, | ||
| 426 | * returns boolean for whether the hook has | ||
| 427 | * anything registered. | ||
| 428 | * When checking a specific function, | ||
| 429 | * the priority of that hook is returned, | ||
| 430 | * or false if the function is not attached. | ||
| 431 | * When using the <tt>$function_to_check</tt> | ||
| 432 | * argument, this function may return a non-boolean | ||
| 433 | * value that evaluates to false (e.g.) 0, | ||
| 434 | * so use the === operator for testing the return value. | ||
| 435 | * </p> | ||
| 436 | */ | ||
| 437 | 3 | public function has_action($tag, $function_to_check = false) | |
| 441 | |||
| 442 | /** | ||
| 443 | * Removes a function from a specified action hook. | ||
| 444 | * | ||
| 445 | * @param string $tag <p>The action hook to which the function to be removed is hooked.</p> | ||
| 446 | * @param mixed $function_to_remove <p>The name of the function which should be removed.</p> | ||
| 447 | * @param int $priority <p>[optional] The priority of the function (default: 50).</p> | ||
| 448 | * | ||
| 449 | * @return bool <p>Whether the function is removed.</p> | ||
| 450 | */ | ||
| 451 | 1 | public function remove_action($tag, $function_to_remove, $priority = self::PRIORITY_NEUTRAL) | |
| 455 | |||
| 456 | /** | ||
| 457 | * Remove all of the hooks from an action. | ||
| 458 | * | ||
| 459 | * @param string $tag <p>The action to remove hooks from.</p> | ||
| 460 | * @param bool $priority <p>The priority number to remove them from.</p> | ||
| 461 | * | ||
| 462 | * @return bool | ||
| 463 | */ | ||
| 464 | 4 | public function remove_all_actions($tag, $priority = false) | |
| 468 | |||
| 469 | /** | ||
| 470 | * Execute functions hooked on a specific action hook. | ||
| 471 | * | ||
| 472 | * @param string $tag <p>The name of the action to be executed.</p> | ||
| 473 | * @param mixed $arg <p> | ||
| 474 | * [optional] Additional arguments which are passed on | ||
| 475 | * to the functions hooked to the action. | ||
| 476 | * </p> | ||
| 477 | * | ||
| 478 | * @return bool <p>Will return false if $tag does not exist in $filter array.</p> | ||
| 479 | */ | ||
| 480 | 2 | public function do_action($tag, $arg = '') | |
| 559 | |||
| 560 | /** | ||
| 561 | * Execute functions hooked on a specific action hook, specifying arguments in an array. | ||
| 562 | * | ||
| 563 | * @param string $tag <p>The name of the action to be executed.</p> | ||
| 564 | * @param array $args <p>The arguments supplied to the functions hooked to <tt>$tag</tt></p> | ||
| 565 | * | ||
| 566 | * @return bool <p>Will return false if $tag does not exist in $filter array.</p> | ||
| 567 | */ | ||
| 568 | 1 | public function do_action_ref_array($tag, $args) | |
| 625 | |||
| 626 | /** | ||
| 627 | * Retrieve the number of times an action has fired. | ||
| 628 | * | ||
| 629 | * @param string $tag <p>The name of the action hook.</p> | ||
| 630 | * | ||
| 631 | * @return integer <p>The number of times action hook <tt>$tag</tt> is fired.</p> | ||
| 632 | */ | ||
| 633 | 1 | public function did_action($tag) | |
| 641 | |||
| 642 | /** | ||
| 643 | * Retrieve the name of the current filter or action. | ||
| 644 | * | ||
| 645 | * @return string <p>Hook name of the current filter or action.</p> | ||
| 646 | */ | ||
| 647 | public function current_filter() | ||
| 651 | |||
| 652 | /** | ||
| 653 | * Build Unique ID for storage and retrieval. | ||
| 654 | * | ||
| 655 | * @param string|array $function <p>Used for creating unique id.</p> | ||
| 656 | * | ||
| 657 | * @return string|bool <p> | ||
| 658 | * Unique ID for usage as array key or false if | ||
| 659 | * $priority === false and $function is an | ||
| 660 | * object reference, and it does not already have a unique id. | ||
| 661 | * </p> | ||
| 662 | */ | ||
| 663 | 7 | private function _filter_build_unique_id($function) | |
| 691 | |||
| 692 | /** | ||
| 693 | * Call "All" Hook | ||
| 694 | * | ||
| 695 | * @param array $args | ||
| 696 | */ | ||
| 697 | 1 | public function _call_all_hook($args) | |
| 715 | |||
| 716 | /** @noinspection MagicMethodsValidityInspection */ | ||
| 717 | /** | ||
| 718 | * @param array $args | ||
| 719 | * | ||
| 720 | * @deprecated use "this->_call_all_hook()" | ||
| 721 | */ | ||
| 722 | public function __call_all_hook($args) | ||
| 729 | |||
| 730 | /** | ||
| 731 | * Add hook for shortcode tag. | ||
| 732 | * | ||
| 733 | * <p> | ||
| 734 | * <br /> | ||
| 735 | * There can only be one hook for each shortcode. Which means that if another | ||
| 736 | * plugin has a similar shortcode, it will override yours or yours will override | ||
| 737 | * theirs depending on which order the plugins are included and/or ran. | ||
| 738 | * <br /> | ||
| 739 | * <br /> | ||
| 740 | * </p> | ||
| 741 | * | ||
| 742 | * Simplest example of a shortcode tag using the API: | ||
| 743 | * | ||
| 744 | * <code> | ||
| 745 | * // [footag foo="bar"] | ||
| 746 |    * function footag_func($atts) { | ||
| 747 |    *  return "foo = {$atts[foo]}"; | ||
| 748 | * } | ||
| 749 |    * add_shortcode('footag', 'footag_func'); | ||
| 750 | * </code> | ||
| 751 | * | ||
| 752 | * Example with nice attribute defaults: | ||
| 753 | * | ||
| 754 | * <code> | ||
| 755 | * // [bartag foo="bar"] | ||
| 756 |    * function bartag_func($atts) { | ||
| 757 | * $args = shortcode_atts(array( | ||
| 758 | * 'foo' => 'no foo', | ||
| 759 | * 'baz' => 'default baz', | ||
| 760 | * ), $atts); | ||
| 761 | * | ||
| 762 |    *  return "foo = {$args['foo']}"; | ||
| 763 | * } | ||
| 764 |    * add_shortcode('bartag', 'bartag_func'); | ||
| 765 | * </code> | ||
| 766 | * | ||
| 767 | * Example with enclosed content: | ||
| 768 | * | ||
| 769 | * <code> | ||
| 770 | * // [baztag]content[/baztag] | ||
| 771 |    * function baztag_func($atts, $content='') { | ||
| 772 | * return "content = $content"; | ||
| 773 | * } | ||
| 774 |    * add_shortcode('baztag', 'baztag_func'); | ||
| 775 | * </code> | ||
| 776 | * | ||
| 777 | * @param string $tag <p>Shortcode tag to be searched in post content.</p> | ||
| 778 | * @param callable $func <p>Hook to run when shortcode is found.</p> | ||
| 779 | * | ||
| 780 | * @return bool | ||
| 781 | */ | ||
| 782 | 2 | public function add_shortcode($tag, $func) | |
| 792 | |||
| 793 | /** | ||
| 794 | * Removes hook for shortcode. | ||
| 795 | * | ||
| 796 | * @param string $tag <p>shortcode tag to remove hook for.</p> | ||
| 797 | * | ||
| 798 | * @return bool | ||
| 799 | */ | ||
| 800 | 1 | public function remove_shortcode($tag) | |
| 810 | |||
| 811 | /** | ||
| 812 | * This function is simple, it clears all of the shortcode tags by replacing the | ||
| 813 | * shortcodes by a empty array. This is actually a very efficient method | ||
| 814 | * for removing all shortcodes. | ||
| 815 | * | ||
| 816 | * @return bool | ||
| 817 | */ | ||
| 818 | 1 | public function remove_all_shortcodes() | |
| 824 | |||
| 825 | /** | ||
| 826 | * Whether a registered shortcode exists named $tag | ||
| 827 | * | ||
| 828 | * @param string $tag | ||
| 829 | * | ||
| 830 | * @return boolean | ||
| 831 | */ | ||
| 832 | 1 | public function shortcode_exists($tag) | |
| 836 | |||
| 837 | /** | ||
| 838 | * Whether the passed content contains the specified shortcode. | ||
| 839 | * | ||
| 840 | * @param string $content | ||
| 841 | * @param string $tag | ||
| 842 | * | ||
| 843 | * @return bool | ||
| 844 | */ | ||
| 845 | public function has_shortcode($content, $tag) | ||
| 870 | |||
| 871 | /** | ||
| 872 | * Search content for shortcodes and filter shortcodes through their hooks. | ||
| 873 | * | ||
| 874 | * <p> | ||
| 875 | * <br /> | ||
| 876 | * If there are no shortcode tags defined, then the content will be returned | ||
| 877 | * without any filtering. This might cause issues when plugins are disabled but | ||
| 878 | * the shortcode will still show up in the post or content. | ||
| 879 | * </p> | ||
| 880 | * | ||
| 881 | * @param string $content <p>Content to search for shortcodes.</p> | ||
| 882 | * | ||
| 883 | * @return string <p>Content with shortcodes filtered out.</p> | ||
| 884 | */ | ||
| 885 | 2 | View Code Duplication | public function do_shortcode($content) | 
| 902 | |||
| 903 | /** | ||
| 904 | * Retrieve the shortcode regular expression for searching. | ||
| 905 | * | ||
| 906 | * <p> | ||
| 907 | * <br /> | ||
| 908 | * The regular expression combines the shortcode tags in the regular expression | ||
| 909 | * in a regex class. | ||
| 910 | * <br /><br /> | ||
| 911 | * | ||
| 912 | * The regular expression contains 6 different sub matches to help with parsing. | ||
| 913 | * <br /><br /> | ||
| 914 | * | ||
| 915 | * 1 - An extra [ to allow for escaping shortcodes with double [[]]<br /> | ||
| 916 | * 2 - The shortcode name<br /> | ||
| 917 | * 3 - The shortcode argument list<br /> | ||
| 918 | * 4 - The self closing /<br /> | ||
| 919 | * 5 - The content of a shortcode when it wraps some content.<br /> | ||
| 920 | * 6 - An extra ] to allow for escaping shortcodes with double [[]]<br /> | ||
| 921 | * </p> | ||
| 922 | * | ||
| 923 | * @return string The shortcode search regular expression | ||
| 924 | */ | ||
| 925 | 2 | public function get_shortcode_regex() | |
| 962 | |||
| 963 | /** | ||
| 964 | * Regular Expression callable for do_shortcode() for calling shortcode hook. | ||
| 965 | * | ||
| 966 | * @see self::get_shortcode_regex for details of the match array contents. | ||
| 967 | * | ||
| 968 | * @param array $m <p>regular expression match array</p> | ||
| 969 | * | ||
| 970 | * @return mixed <p><strong>false</strong> on failure</p> | ||
| 971 | */ | ||
| 972 | 2 | private function _do_shortcode_tag($m) | |
| 990 | |||
| 991 | /** | ||
| 992 | * Retrieve all attributes from the shortcodes tag. | ||
| 993 | * | ||
| 994 | * <p> | ||
| 995 | * <br /> | ||
| 996 | * The attributes list has the attribute name as the key and the value of the | ||
| 997 | * attribute as the value in the key/value pair. This allows for easier | ||
| 998 | * retrieval of the attributes, since all attributes have to be known. | ||
| 999 | * </p> | ||
| 1000 | * | ||
| 1001 | * @param string $text | ||
| 1002 | * | ||
| 1003 | * @return array <p>List of attributes and their value.</p> | ||
| 1004 | */ | ||
| 1005 | 2 | public function shortcode_parse_atts($text) | |
| 1030 | |||
| 1031 | /** | ||
| 1032 | * Combine user attributes with known attributes and fill in defaults when needed. | ||
| 1033 | * | ||
| 1034 | * <p> | ||
| 1035 | * <br /> | ||
| 1036 | * The pairs should be considered to be all of the attributes which are | ||
| 1037 | * supported by the caller and given as a list. The returned attributes will | ||
| 1038 | * only contain the attributes in the $pairs list. | ||
| 1039 | * | ||
| 1040 | * <br /><br /> | ||
| 1041 | * If the $atts list has unsupported attributes, then they will be ignored and | ||
| 1042 | * removed from the final returned list. | ||
| 1043 | * </p> | ||
| 1044 | * | ||
| 1045 | * @param array $pairs <p>Entire list of supported attributes and their defaults.</p> | ||
| 1046 | * @param array $atts <p>User defined attributes in shortcode tag.</p> | ||
| 1047 | * @param string $shortcode <p>[optional] The name of the shortcode, provided for context to enable filtering.</p> | ||
| 1048 | * | ||
| 1049 | * @return array <p>Combined and filtered attribute list.</p> | ||
| 1050 | */ | ||
| 1051 | 2 | public function shortcode_atts($pairs, $atts, $shortcode = '') | |
| 1086 | |||
| 1087 | /** | ||
| 1088 | * Remove all shortcode tags from the given content. | ||
| 1089 | * | ||
| 1090 | * @param string $content <p>Content to remove shortcode tags.</p> | ||
| 1091 | * | ||
| 1092 | * @return string <p>Content without shortcode tags.</p> | ||
| 1093 | */ | ||
| 1094 | 1 | View Code Duplication | public function strip_shortcodes($content) | 
| 1112 | |||
| 1113 | /** | ||
| 1114 | * Strip shortcode by tag. | ||
| 1115 | * | ||
| 1116 | * @param array $m | ||
| 1117 | * | ||
| 1118 | * @return string | ||
| 1119 | */ | ||
| 1120 | 1 | private function _strip_shortcode_tag($m) | |
| 1129 | |||
| 1130 | } | ||
| 1131 | 
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: