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: