├── advanced-hooks-api.php ├── class-r-hook-handler.php ├── composer.json └── readme.md /advanced-hooks-api.php: -------------------------------------------------------------------------------- 1 | ' == $caller['type'] ) ? $caller['object'] : $caller['class']; 226 | } 227 | 228 | if ( ! is_array( $tags ) ) 229 | $tags = array( $tags ); 230 | 231 | foreach ( $tags as $tag ) { 232 | 233 | if ( method_exists( $class, $tag ) ) 234 | add_action( $tag, array( $class, $tag ), $priority, $accepted_args ); 235 | } 236 | 237 | return true; 238 | } 239 | } -------------------------------------------------------------------------------- /class-r-hook-handler.php: -------------------------------------------------------------------------------- 1 | data = $data; 22 | $this->callback = $callback; 23 | } 24 | 25 | /** 26 | * Executes callback with custom arguments, ignores what hook passes. 27 | * 28 | * @return mixed|null 29 | */ 30 | function action() { 31 | 32 | call_user_func_array( $this->callback, $this->data ); 33 | 34 | // compatibility with filters 35 | if ( func_num_args() ) 36 | return func_get_arg( 0 ); 37 | 38 | return null; 39 | } 40 | 41 | /** 42 | * Returns custom data to filter. 43 | * 44 | * @return mixed 45 | */ 46 | function filter() { 47 | 48 | return $this->data; 49 | } 50 | 51 | /** 52 | * Searches and replaces data as array or substring, depending on passed filter value. 53 | * 54 | * @param mixed $input 55 | * 56 | * @return array|mixed 57 | */ 58 | function replace( $input ) { 59 | 60 | if ( is_array( $input ) ) 61 | $input[$this->data['search']] = $this->data['replace']; 62 | else 63 | $input = str_replace( $this->data['search'], $this->data['replace'], $input ); 64 | 65 | return $input; 66 | } 67 | 68 | /** 69 | * Prepends data to array or string, passed by filter. 70 | * 71 | * @param mixed $input 72 | * 73 | * @return array|string 74 | */ 75 | function prepend( $input ) { 76 | 77 | if ( is_array( $input ) ) { 78 | 79 | if ( is_array( $this->data ) ) { 80 | 81 | foreach ( array_reverse( $this->data ) as $value ) { 82 | 83 | array_unshift( $input, $value ); 84 | } 85 | } 86 | else { 87 | 88 | array_unshift( $input, $this->data ); 89 | } 90 | } 91 | else { 92 | 93 | $input = $this->data . $input; 94 | } 95 | 96 | return $input; 97 | } 98 | 99 | 100 | /** 101 | * Appends data to array or string, passed by filter. 102 | * 103 | * @param mixed $input 104 | * 105 | * @return array|string 106 | */ 107 | function append( $input ) { 108 | 109 | if ( is_array( $input ) ) { 110 | 111 | if ( is_array( $this->data ) ) { 112 | 113 | foreach ( $this->data as $value ) { 114 | 115 | $input[] = $value; 116 | } 117 | } 118 | else { 119 | 120 | $input[] = $this->data; 121 | } 122 | } 123 | else { 124 | 125 | $input .= $this->data; 126 | } 127 | 128 | return $input; 129 | } 130 | 131 | /** 132 | * Executes callback once and removes it from hook. 133 | * 134 | * @return mixed 135 | */ 136 | function once() { 137 | 138 | remove_filter( current_filter(), array( $this, __FUNCTION__ ), $this->data['priority'] ); 139 | 140 | return call_user_func_array( $this->callback, array_slice( func_get_args(), 0, $this->data['accepted_args'] ) ); 141 | } 142 | 143 | /** 144 | * Remove matching handlers from specified hook and priority. 145 | * 146 | * @param string $tag 147 | * @param int $priority 148 | * @param mixed $data 149 | * @param string $method of handler class 150 | * @param string|null $callback 151 | */ 152 | static function remove_action( $tag, $priority, $data, $method, $callback = null ) { 153 | 154 | global $wp_filter; 155 | 156 | foreach ( $wp_filter[$tag][$priority] as $event ) { 157 | 158 | $function = $event['function']; 159 | 160 | /** 161 | * @var R_Hook_Handler $object 162 | */ 163 | if ( is_array( $function ) && is_a( $object = $function[0], __CLASS__ ) ) 164 | $object->remove_if_match( $tag, $priority, $event['accepted_args'], $data, $method, $callback ); 165 | } 166 | } 167 | 168 | /** 169 | * Unhook this instance from hook if data matches. 170 | * 171 | * @param string $tag 172 | * @param int $priority 173 | * @param int $accepted_args 174 | * @param mixed $data 175 | * @param string $method of handler class 176 | * @param string|null $callback 177 | */ 178 | function remove_if_match( $tag, $priority, $accepted_args, $data, $method, $callback = null ) { 179 | 180 | if ( $data === $this->data && $callback === $this->callback ) 181 | remove_action( $tag, array( $this, $method ), $priority, $accepted_args ); 182 | } 183 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "rarst/advanced-hooks-api", 3 | "description" : "Set of (experimental) wrappers that allow to hook more elaborate WordPress events without coding intermediary functions", 4 | "keywords" : ["wordpress"], 5 | "type" : "wordpress-plugin", 6 | "homepage" : "https://github.com/Rarst/advanced-hooks-api", 7 | "license" : "MIT", 8 | "authors" : [ 9 | { 10 | "name" : "Andrey Savchenko", 11 | "email" : "contact@rarst.net", 12 | "homepage": "http://www.Rarst.net/" 13 | } 14 | ], 15 | "support" : { 16 | "issues": "https://github.com/Rarst/advanced-hooks-api/issues" 17 | }, 18 | "require" : { 19 | "composer/installers": "~1.0" 20 | } 21 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Advanced WordPress Hooks API 2 | 3 | Set of (experimental) wrappers that allow to hook more elaborate WordPress events without coding intermediary functions. 4 | 5 | WordPress only operates with callbacks for actions and filters. That means that you always need to use callback, either: 6 | 7 | - provided by core (limited) 8 | - closures (messy) 9 | - coded by yourself (this - a lot) 10 | 11 | This plugins offers number of custom `add_*` functions to hook more elaborate events: 12 | 13 | - `add_action_with_args()` - hook callback **and** arguments to run it with 14 | - `add_filter_return()` - override filter with arbitrary value 15 | - `add_filter_prepend()` and `add_filter_append()` - hook suffix/prefix values for filtered string and arrays 16 | - `add_filter_replace()` - edit substrings or array values in filter 17 | - `add_action_once()` and `add_filter_once()` - hook callback to only fire once 18 | - `add_method()` - quickly add class methods to hooks of same name 19 | 20 | Both implementation and set of functions are experimental. 21 | 22 | # Changelog 23 | 24 | ## 0.7 25 | 26 | * _(enhancement)_ implemented `add_action_once()` and `add_filter_once()`, props Eric Mann 27 | 28 | ## 0.6 29 | 30 | * _(enhancement)_ changed license to MIT 31 | * _(enhancement)_ cleaned up coding style 32 | * _(enhancement)_ moved handler class to separate file 33 | * _(enhancement)_ implemented removing of handler from hooks 34 | * **(breaking change)** changed signatures to make priority optional 35 | 36 | ## 0.5 37 | 38 | * _(enhancement)_ new add_method() function 39 | * _(enhancement)_ more return points for better logic and compatibility 40 | 41 | ## 0.4.1 42 | 43 | * _(bugfix)_ action() method expected argument passed (to be compatible with filters), changed to func_get_arg() 44 | 45 | ## 0.4 46 | 47 | * Initial public repository release. 48 | --------------------------------------------------------------------------------