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 |
||
| 35 | class Hooks |
||
| 36 | { |
||
| 37 | /** |
||
| 38 | * Filters - holds list of hooks |
||
| 39 | * |
||
| 40 | * @var array |
||
| 41 | * @access protected |
||
| 42 | * @since 1.0.0 |
||
| 43 | */ |
||
| 44 | protected $filters = array(); |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Merged Filters |
||
| 48 | * |
||
| 49 | * @var array |
||
| 50 | * @access protected |
||
| 51 | * @since 1.0.0 |
||
| 52 | */ |
||
| 53 | protected $merged_filters = array(); |
||
| 54 | |||
| 55 | /** |
||
| 56 | * Actions |
||
| 57 | * |
||
| 58 | * @var array |
||
| 59 | * @access protected |
||
| 60 | * @since 1.0.0 |
||
| 61 | */ |
||
| 62 | protected $actions = array(); |
||
| 63 | |||
| 64 | /** |
||
| 65 | * Current Filter - holds the name of the current filter |
||
| 66 | * |
||
| 67 | * @var array |
||
| 68 | * @access protected |
||
| 69 | * @since 1.0.0 |
||
| 70 | */ |
||
| 71 | protected $current_filter = array(); |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Container for storing shortcode tags and their hook to call for the shortcode |
||
| 75 | * |
||
| 76 | * @since 1.0.0 |
||
| 77 | * @name $shortcode_tags |
||
| 78 | * @var array |
||
| 79 | */ |
||
| 80 | public static $shortcode_tags = array(); |
||
| 81 | |||
| 82 | /** |
||
| 83 | * Default priority |
||
| 84 | * |
||
| 85 | * @since 0.2 |
||
| 86 | * @const int |
||
| 87 | */ |
||
| 88 | const PRIORITY_NEUTRAL = 50; |
||
| 89 | |||
| 90 | /** |
||
| 91 | * is not allowed to call from outside: private! |
||
| 92 | * |
||
| 93 | * @access private |
||
| 94 | */ |
||
| 95 | 1 | protected function __construct() |
|
| 98 | |||
| 99 | /** |
||
| 100 | * prevent the instance from being cloned |
||
| 101 | * |
||
| 102 | * @access private |
||
| 103 | * |
||
| 104 | * @return void |
||
| 105 | */ |
||
| 106 | protected function __clone() |
||
| 109 | |||
| 110 | /** |
||
| 111 | * Singleton Instance |
||
| 112 | * |
||
| 113 | * Returns a Singleton instance of this class. |
||
| 114 | * |
||
| 115 | * @param void |
||
| 116 | * |
||
| 117 | * @return Hooks |
||
| 118 | * @access public |
||
| 119 | * @static |
||
| 120 | * @since 1.0.0 |
||
| 121 | */ |
||
| 122 | 10 | public static function getInstance() |
|
| 132 | |||
| 133 | /** |
||
| 134 | * FILTERS |
||
| 135 | */ |
||
| 136 | |||
| 137 | /** |
||
| 138 | * Adds Hooks to a function or method to a specific filter action. |
||
| 139 | * |
||
| 140 | * @access public |
||
| 141 | * @since 1.0.0 |
||
| 142 | * |
||
| 143 | * @param string $tag The name of the filter to hook the |
||
| 144 | * {@link $function_to_add} to. |
||
| 145 | * @param string $function_to_add The name of the function to be called |
||
| 146 | * when the filter is applied. |
||
| 147 | * @param integer $priority (optional) Used to specify the order in |
||
| 148 | * which the functions associated with a |
||
| 149 | * particular action are executed (default: 50). |
||
| 150 | * Lower numbers correspond with earlier execution, |
||
| 151 | * and functions with the same priority are executed |
||
| 152 | * in the order in which they were added to the action. |
||
| 153 | * @param string $include_path optional. File to include before executing the callback. |
||
| 154 | * |
||
| 155 | * @return boolean true |
||
| 156 | */ |
||
| 157 | 7 | public function add_filter($tag, $function_to_add, $priority = self::PRIORITY_NEUTRAL, $include_path = null) |
|
| 170 | |||
| 171 | /** |
||
| 172 | * Removes a function from a specified filter hook. |
||
| 173 | * |
||
| 174 | * @param string $tag the filter hook to which the function to be removed is hooked. |
||
| 175 | * @param mixed $function_to_remove the name of the function which should be removed. |
||
| 176 | * @param int $priority (optional) The priority of the function (default: 50). |
||
| 177 | * |
||
| 178 | * @return bool |
||
| 179 | */ |
||
| 180 | 1 | public function remove_filter($tag, $function_to_remove, $priority = self::PRIORITY_NEUTRAL) |
|
| 197 | |||
| 198 | /** |
||
| 199 | * Remove all of the hooks from a filter. |
||
| 200 | * |
||
| 201 | * @param string $tag the filter to remove hooks from. |
||
| 202 | * @param bool $priority the priority number to remove. |
||
| 203 | * |
||
| 204 | * @return bool True when finished. |
||
| 205 | */ |
||
| 206 | 4 | public function remove_all_filters($tag, $priority = false) |
|
| 224 | |||
| 225 | /** |
||
| 226 | * Check if any filter has been registered for the given hook. |
||
| 227 | * |
||
| 228 | * Info: Use !== false to check if it's true! |
||
| 229 | * |
||
| 230 | * @param string $tag the name of the filter hook. |
||
| 231 | * @param bool $function_to_check callback function name to check for. [optional] |
||
| 232 | * |
||
| 233 | * @return mixed If {@link $function_to_check} is omitted, |
||
| 234 | * returns boolean for whether the hook has |
||
| 235 | * anything registered. |
||
| 236 | * When checking a specific function, the priority |
||
| 237 | * of that hook is returned, or false if the |
||
| 238 | * function is not attached. |
||
| 239 | * When using the {@link $function_to_check} argument, |
||
| 240 | * this function may return a non-boolean value that |
||
| 241 | * evaluates to false |
||
| 242 | * (e.g.) 0, so use the === operator for testing the return value. |
||
| 243 | * @access public |
||
| 244 | * @since 1.0.0 |
||
| 245 | */ |
||
| 246 | 3 | public function has_filter($tag, $function_to_check = false) |
|
| 265 | |||
| 266 | /** |
||
| 267 | * Call the functions added to a filter hook. |
||
| 268 | * |
||
| 269 | * Info: Additional variables passed to the functions hooked to <tt>$tag</tt>. |
||
| 270 | * |
||
| 271 | * @param string|array $tag The name of the filter hook. |
||
| 272 | * @param mixed $value The value on which the filters hooked to <tt>$tag</tt> are applied on. |
||
| 273 | * |
||
| 274 | * @return mixed The filtered value after all hooked functions are applied to it. |
||
| 275 | * @access public |
||
| 276 | * @since 1.0.0 |
||
| 277 | */ |
||
| 278 | 4 | public function apply_filters($tag, $value) |
|
| 334 | |||
| 335 | /** |
||
| 336 | * Execute functions hooked on a specific filter hook, specifying arguments in an array. |
||
| 337 | * |
||
| 338 | * @param string $tag The name of the filter hook. |
||
| 339 | * @param array $args The arguments supplied to the functions hooked to <tt>$tag</tt> |
||
| 340 | * |
||
| 341 | * @return mixed The filtered value after all hooked functions are applied to it. |
||
| 342 | * |
||
| 343 | * @access public |
||
| 344 | * @since 1.0.0 |
||
| 345 | */ |
||
| 346 | 1 | public function apply_filters_ref_array($tag, $args) |
|
| 393 | |||
| 394 | /** |
||
| 395 | * ACTIONS |
||
| 396 | */ |
||
| 397 | |||
| 398 | /** |
||
| 399 | * Hooks a function on to a specific action. |
||
| 400 | * |
||
| 401 | * @param string $tag The name of the action to which the |
||
| 402 | * <tt>$function_to_add</tt> is hooked. |
||
| 403 | * @param string $function_to_add The name of the function you wish to be called. |
||
| 404 | * @param integer $priority (optional) Used to specify the order in which |
||
| 405 | * the functions associated with a particular |
||
| 406 | * action are executed (default: 50). |
||
| 407 | * Lower numbers correspond with earlier execution, |
||
| 408 | * and functions with the same priority are executed |
||
| 409 | * in the order in which they were added to the action. |
||
| 410 | * @param string $include_path optional. File to include before executing the callback. |
||
| 411 | * |
||
| 412 | * @access public |
||
| 413 | * @since 1.0.0 |
||
| 414 | * @return bool |
||
| 415 | */ |
||
| 416 | 5 | public function add_action($tag, $function_to_add, $priority = self::PRIORITY_NEUTRAL, $include_path = null) |
|
| 420 | |||
| 421 | /** |
||
| 422 | * Check if any action has been registered for a hook. |
||
| 423 | * |
||
| 424 | * Info: Use !== false to check if it's true! |
||
| 425 | * |
||
| 426 | * @param string $tag The name of the action hook. |
||
| 427 | * @param bool|string $function_to_check (optional) |
||
| 428 | * |
||
| 429 | * @return mixed If <tt>$function_to_check</tt> is omitted, |
||
| 430 | * returns boolean for whether the hook has |
||
| 431 | * anything registered. |
||
| 432 | * When checking a specific function, |
||
| 433 | * the priority of that hook is returned, |
||
| 434 | * or false if the function is not attached. |
||
| 435 | * When using the <tt>$function_to_check</tt> |
||
| 436 | * argument, this function may return a non-boolean |
||
| 437 | * value that evaluates to false (e.g.) 0, |
||
| 438 | * so use the === operator for testing the return value. |
||
| 439 | * @access public |
||
| 440 | * @since 1.0.0 |
||
| 441 | */ |
||
| 442 | 3 | public function has_action($tag, $function_to_check = false) |
|
| 446 | |||
| 447 | /** |
||
| 448 | * Removes a function from a specified action hook. |
||
| 449 | * |
||
| 450 | * @param string $tag the action hook to which the function to be removed is hooked. |
||
| 451 | * @param mixed $function_to_remove the name of the function which should be removed. |
||
| 452 | * @param int $priority [optional] The priority of the function (default: 50). |
||
| 453 | * |
||
| 454 | * @return bool Whether the function is removed. |
||
| 455 | */ |
||
| 456 | 1 | public function remove_action($tag, $function_to_remove, $priority = self::PRIORITY_NEUTRAL) |
|
| 460 | |||
| 461 | /** |
||
| 462 | * Remove all of the hooks from an action. |
||
| 463 | * |
||
| 464 | * @param string $tag the action to remove hooks from. |
||
| 465 | * @param bool $priority the priority number to remove them from. |
||
| 466 | * |
||
| 467 | * @return bool True when finished. |
||
| 468 | */ |
||
| 469 | 4 | public function remove_all_actions($tag, $priority = false) |
|
| 473 | |||
| 474 | /** |
||
| 475 | * Execute functions hooked on a specific action hook. |
||
| 476 | * |
||
| 477 | * @param string $tag The name of the action to be executed. |
||
| 478 | * @param mixed $arg ,.. Optional additional arguments which are passed on |
||
| 479 | * to the functions hooked to the action. |
||
| 480 | * |
||
| 481 | * @return bool Will return false if $tag does not exist in $filter array |
||
| 482 | * @access public |
||
| 483 | * @since 1.0.0 |
||
| 484 | */ |
||
| 485 | 2 | public function do_action($tag, $arg = '') |
|
| 564 | |||
| 565 | /** |
||
| 566 | * Execute functions hooked on a specific action hook, specifying arguments in an array. |
||
| 567 | * |
||
| 568 | * @param string $tag The name of the action to be executed. |
||
| 569 | * @param array $args The arguments supplied to the functions hooked to <tt>$tag</tt> |
||
| 570 | * |
||
| 571 | * @return bool Will return false if $tag does not exist in $filter array |
||
| 572 | * @access public |
||
| 573 | * @since 1.0.0 |
||
| 574 | */ |
||
| 575 | 1 | public function do_action_ref_array($tag, $args) |
|
| 632 | |||
| 633 | /** |
||
| 634 | * Retrieve the number of times an action has fired. |
||
| 635 | * |
||
| 636 | * @param string $tag The name of the action hook. |
||
| 637 | * |
||
| 638 | * @return integer The number of times action hook <tt>$tag</tt> is fired |
||
| 639 | * @access public |
||
| 640 | * @since 1.0.0 |
||
| 641 | */ |
||
| 642 | 1 | public function did_action($tag) |
|
| 650 | |||
| 651 | /** |
||
| 652 | * HELPERS |
||
| 653 | */ |
||
| 654 | |||
| 655 | /** |
||
| 656 | * Retrieve the name of the current filter or action. |
||
| 657 | * |
||
| 658 | * @param void |
||
| 659 | * |
||
| 660 | * @return string Hook name of the current filter or action. |
||
| 661 | * @access public |
||
| 662 | * @since 1.0.0 |
||
| 663 | */ |
||
| 664 | public function current_filter() |
||
| 668 | |||
| 669 | /** |
||
| 670 | * Build Unique ID for storage and retrieval. |
||
| 671 | * |
||
| 672 | * @param string|array $function Used for creating unique id |
||
| 673 | * |
||
| 674 | * @return string|bool Unique ID for usage as array key or false if |
||
| 675 | * $priority === false and $function is an |
||
| 676 | * object reference, and it does not already have a unique id. |
||
| 677 | * @access private |
||
| 678 | * @since 1.0.0 |
||
| 679 | */ |
||
| 680 | 7 | private function _filter_build_unique_id($function) |
|
| 708 | |||
| 709 | /** |
||
| 710 | * Call "All" Hook |
||
| 711 | * |
||
| 712 | * @param array $args |
||
| 713 | * |
||
| 714 | * @access public |
||
| 715 | * @since 1.0.0 |
||
| 716 | */ |
||
| 717 | 1 | public function _call_all_hook($args) |
|
| 738 | |||
| 739 | /** @noinspection MagicMethodsValidityInspection */ |
||
| 740 | /** |
||
| 741 | * @param array $args |
||
| 742 | * |
||
| 743 | * @deprecated use "this->_call_all_hook()" |
||
| 744 | * @access public |
||
| 745 | * @since 1.0.0 |
||
| 746 | */ |
||
| 747 | public function __call_all_hook($args) |
||
| 751 | |||
| 752 | /** |
||
| 753 | * Add hook for shortcode tag. |
||
| 754 | * |
||
| 755 | * There can only be one hook for each shortcode. Which means that if another |
||
| 756 | * plugin has a similar shortcode, it will override yours or yours will override |
||
| 757 | * theirs depending on which order the plugins are included and/or ran. |
||
| 758 | * |
||
| 759 | * Simplest example of a shortcode tag using the API: |
||
| 760 | * |
||
| 761 | * <code> |
||
| 762 | * // [footag foo="bar"] |
||
| 763 | * function footag_func($atts) { |
||
| 764 | * return "foo = {$atts[foo]}"; |
||
| 765 | * } |
||
| 766 | * add_shortcode('footag', 'footag_func'); |
||
| 767 | * </code> |
||
| 768 | * |
||
| 769 | * Example with nice attribute defaults: |
||
| 770 | * |
||
| 771 | * <code> |
||
| 772 | * // [bartag foo="bar"] |
||
| 773 | * function bartag_func($atts) { |
||
| 774 | * $args = shortcode_atts(array( |
||
| 775 | * 'foo' => 'no foo', |
||
| 776 | * 'baz' => 'default baz', |
||
| 777 | * ), $atts); |
||
| 778 | * |
||
| 779 | * return "foo = {$args['foo']}"; |
||
| 780 | * } |
||
| 781 | * add_shortcode('bartag', 'bartag_func'); |
||
| 782 | * </code> |
||
| 783 | * |
||
| 784 | * Example with enclosed content: |
||
| 785 | * |
||
| 786 | * <code> |
||
| 787 | * // [baztag]content[/baztag] |
||
| 788 | * function baztag_func($atts, $content='') { |
||
| 789 | * return "content = $content"; |
||
| 790 | * } |
||
| 791 | * add_shortcode('baztag', 'baztag_func'); |
||
| 792 | * </code> |
||
| 793 | * |
||
| 794 | * @since 1.0.0 |
||
| 795 | * |
||
| 796 | * @param string $tag Shortcode tag to be searched in post content. |
||
| 797 | * @param callable $func Hook to run when shortcode is found. |
||
| 798 | * |
||
| 799 | * @return bool |
||
| 800 | */ |
||
| 801 | 2 | public function add_shortcode($tag, $func) |
|
| 811 | |||
| 812 | /** |
||
| 813 | * Removes hook for shortcode. |
||
| 814 | * |
||
| 815 | * @since 1.0.0 |
||
| 816 | * |
||
| 817 | * @param string $tag shortcode tag to remove hook for. |
||
| 818 | * |
||
| 819 | * @return bool |
||
| 820 | */ |
||
| 821 | 1 | public function remove_shortcode($tag) |
|
| 831 | |||
| 832 | /** |
||
| 833 | * This function is simple, it clears all of the shortcode tags by replacing the |
||
| 834 | * shortcodes by a empty array. This is actually a very efficient method |
||
| 835 | * for removing all shortcodes. |
||
| 836 | * |
||
| 837 | * @since 1.0.0 |
||
| 838 | * |
||
| 839 | * @return bool |
||
| 840 | */ |
||
| 841 | 1 | public function remove_all_shortcodes() |
|
| 847 | |||
| 848 | /** |
||
| 849 | * Whether a registered shortcode exists named $tag |
||
| 850 | * |
||
| 851 | * @since 1.0.0 |
||
| 852 | * |
||
| 853 | * @param string $tag |
||
| 854 | * |
||
| 855 | * @return boolean |
||
| 856 | */ |
||
| 857 | 1 | public function shortcode_exists($tag) |
|
| 861 | |||
| 862 | /** |
||
| 863 | * Whether the passed content contains the specified shortcode |
||
| 864 | * |
||
| 865 | * @since 1.0.0 |
||
| 866 | * |
||
| 867 | * @param $content |
||
| 868 | * @param $tag |
||
| 869 | * |
||
| 870 | * @return bool |
||
| 871 | */ |
||
| 872 | public function has_shortcode($content, $tag) |
||
| 897 | |||
| 898 | /** |
||
| 899 | * Search content for shortcodes and filter shortcodes through their hooks. |
||
| 900 | * |
||
| 901 | * If there are no shortcode tags defined, then the content will be returned |
||
| 902 | * without any filtering. This might cause issues when plugins are disabled but |
||
| 903 | * the shortcode will still show up in the post or content. |
||
| 904 | * |
||
| 905 | * @since 1.0.0 |
||
| 906 | * |
||
| 907 | * @param string $content Content to search for shortcodes |
||
| 908 | * |
||
| 909 | * @return string Content with shortcodes filtered out. |
||
| 910 | */ |
||
| 911 | 2 | View Code Duplication | public function do_shortcode($content) |
| 928 | |||
| 929 | /** |
||
| 930 | * Retrieve the shortcode regular expression for searching. |
||
| 931 | * |
||
| 932 | * The regular expression combines the shortcode tags in the regular expression |
||
| 933 | * in a regex class. |
||
| 934 | * |
||
| 935 | * The regular expression contains 6 different sub matches to help with parsing. |
||
| 936 | * |
||
| 937 | * 1 - An extra [ to allow for escaping shortcodes with double [[]] |
||
| 938 | * 2 - The shortcode name |
||
| 939 | * 3 - The shortcode argument list |
||
| 940 | * 4 - The self closing / |
||
| 941 | * 5 - The content of a shortcode when it wraps some content. |
||
| 942 | * 6 - An extra ] to allow for escaping shortcodes with double [[]] |
||
| 943 | * |
||
| 944 | * @since 1.0.0 |
||
| 945 | * |
||
| 946 | * @return string The shortcode search regular expression |
||
| 947 | */ |
||
| 948 | 2 | public function get_shortcode_regex() |
|
| 985 | |||
| 986 | /** |
||
| 987 | * Regular Expression callable for do_shortcode() for calling shortcode hook. |
||
| 988 | * |
||
| 989 | * @see get_shortcode_regex for details of the match array contents. |
||
| 990 | * |
||
| 991 | * @since 1.0.0 |
||
| 992 | * @access private |
||
| 993 | * |
||
| 994 | * @param array $m Regular expression match array |
||
| 995 | * |
||
| 996 | * @return mixed False on failure. |
||
| 997 | */ |
||
| 998 | 2 | private function _do_shortcode_tag($m) |
|
| 1016 | |||
| 1017 | /** |
||
| 1018 | * Retrieve all attributes from the shortcodes tag. |
||
| 1019 | * |
||
| 1020 | * The attributes list has the attribute name as the key and the value of the |
||
| 1021 | * attribute as the value in the key/value pair. This allows for easier |
||
| 1022 | * retrieval of the attributes, since all attributes have to be known. |
||
| 1023 | * |
||
| 1024 | * @since 1.0.0 |
||
| 1025 | * |
||
| 1026 | * @param string $text |
||
| 1027 | * |
||
| 1028 | * @return array List of attributes and their value. |
||
| 1029 | */ |
||
| 1030 | 2 | public function shortcode_parse_atts($text) |
|
| 1055 | |||
| 1056 | /** |
||
| 1057 | * Combine user attributes with known attributes and fill in defaults when needed. |
||
| 1058 | * |
||
| 1059 | * The pairs should be considered to be all of the attributes which are |
||
| 1060 | * supported by the caller and given as a list. The returned attributes will |
||
| 1061 | * only contain the attributes in the $pairs list. |
||
| 1062 | * |
||
| 1063 | * If the $atts list has unsupported attributes, then they will be ignored and |
||
| 1064 | * removed from the final returned list. |
||
| 1065 | * |
||
| 1066 | * @since 1.0.0 |
||
| 1067 | * |
||
| 1068 | * @param array $pairs Entire list of supported attributes and their defaults. |
||
| 1069 | * @param array $atts User defined attributes in shortcode tag. |
||
| 1070 | * @param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering |
||
| 1071 | * |
||
| 1072 | * @return array Combined and filtered attribute list. |
||
| 1073 | */ |
||
| 1074 | 2 | public function shortcode_atts($pairs, $atts, $shortcode = '') |
|
| 1108 | |||
| 1109 | /** |
||
| 1110 | * Remove all shortcode tags from the given content. |
||
| 1111 | * |
||
| 1112 | * @since 1.0.0 |
||
| 1113 | * |
||
| 1114 | * @param string $content Content to remove shortcode tags. |
||
| 1115 | * |
||
| 1116 | * @return string Content without shortcode tags. |
||
| 1117 | */ |
||
| 1118 | 1 | View Code Duplication | public function strip_shortcodes($content) |
| 1136 | |||
| 1137 | /** |
||
| 1138 | * Strip shortcode by tag. |
||
| 1139 | * |
||
| 1140 | * @access private |
||
| 1141 | * |
||
| 1142 | * @param $m |
||
| 1143 | * |
||
| 1144 | * @return string |
||
| 1145 | */ |
||
| 1146 | 1 | private function _strip_shortcode_tag($m) |
|
| 1155 | |||
| 1156 | } |
||
| 1157 |
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: