Make WordPress Core

Ticket #17817: 17817.24.diff

File 17817.24.diff, 64.8 KB (added by aaroncampbell, 8 years ago)
  • src/wp-includes/class-wp-hook.php

    diff --git a/src/wp-includes/class-wp-hook.php b/src/wp-includes/class-wp-hook.php
    index e69de29..0bdde1d 100644
    a b  
     1<?php
     2/**
     3 * Plugin API: WP_Hook class
     4 *
     5 * @package WordPress
     6 * @subpackage Plugin
     7 * @since 4.7.0
     8 */
     9
     10/**
     11 * Core class used to implement action and filter hook functionality.
     12 *
     13 * @since 4.7.0
     14 *
     15 * @see Iterator
     16 * @see ArrayAccess
     17 */
     18final class WP_Hook implements Iterator, ArrayAccess {
     19
     20        /**
     21         * Hook callbacks.
     22         *
     23         * @since 4.7.0
     24         * @access public
     25         * @var array
     26         */
     27        public $callbacks = array();
     28
     29        /**
     30         * The priority keys of actively running iterations of a hook.
     31         *
     32         * @since 4.7.0
     33         * @access private
     34         * @var array
     35         */
     36        private $iterations = array();
     37
     38        /**
     39         * The current priority of actively running iterations of a hook.
     40         *
     41         * @since 4.7.0
     42         * @access private
     43         * @var array
     44         */
     45        private $current_priority = array();
     46
     47        /**
     48         * Number of levels this hook can be recursively called.
     49         *
     50         * @since 4.7.0
     51         * @access private
     52         * @var int
     53         */
     54        private $nesting_level = 0;
     55
     56        /**
     57         * Flag for if we're current doing an action, rather than a filter.
     58         *
     59         * @since 4.7.0
     60         * @access private
     61         * @var boolean
     62         */
     63        private $doing_action = false;
     64
     65        /**
     66         * Hooks a function or method to a specific filter action.
     67         *
     68         * @since 4.7.0
     69         * @access public
     70         *
     71         * @param string   $tag             The name of the filter to hook the $function_to_add callback to.
     72         * @param callable $function_to_add The callback to be run when the filter is applied.
     73         * @param int      $priority        The order in which the functions associated with a
     74         *                                  particular action are executed. Lower numbers correspond with
     75         *                                  earlier execution, and functions with the same priority are executed
     76         *                                  in the order in which they were added to the action.
     77         * @param int      $accepted_args   The number of arguments the function accepts.
     78         */
     79        public function add_filter( $tag, $function_to_add, $priority, $accepted_args ) {
     80                $idx = _wp_filter_build_unique_id( $tag, $function_to_add, $priority );
     81                $priority_existed = isset( $this->callbacks[ $priority ] );
     82
     83                $this->callbacks[ $priority ][ $idx ] = array(
     84                        'function' => $function_to_add,
     85                        'accepted_args' => $accepted_args
     86                );
     87
     88                // if we're adding a new priority to the list, put them back in sorted order
     89                if ( ! $priority_existed && count( $this->callbacks ) > 1 ) {
     90                        ksort( $this->callbacks, SORT_NUMERIC );
     91                }
     92
     93                if ( $this->nesting_level > 0 ) {
     94                        $this->resort_active_iterations( $priority, $priority_existed );
     95                }
     96        }
     97
     98        /**
     99         * Handles reseting callback priority keys mid-iteration.
     100         *
     101         * @since 4.7.0
     102         * @access private
     103         *
     104         * @param bool|int $new_priority      The priority of the new filter being added. Default false, for no priority being added.
     105         * @param bool     $priority_existed  Flag for whether the priority already existed before the new filter was added.
     106         */
     107        private function resort_active_iterations( $new_priority = false, $priority_existed = false ) {
     108                $new_priorities = array_keys( $this->callbacks );
     109
     110                // If there are no remaining hooks, clear out all running iterations.
     111                if ( ! $new_priorities ) {
     112                        foreach ( $this->iterations as $index => $iteration ) {
     113                                $this->iterations[ $index ] = $new_priorities;
     114                        }
     115                        return;
     116                }
     117
     118                $min = min( $new_priorities );
     119                foreach ( $this->iterations as $index => &$iteration ) {
     120                        $current = current( $iteration );
     121                        // If we're already at the end of this iteration, just leave the array pointer where it is.
     122                        if ( false === $current ) {
     123                                continue;
     124                        }
     125
     126                        $iteration = $new_priorities;
     127
     128                        if ( $current < $min ) {
     129                                array_unshift( $iteration, $current );
     130                                continue;
     131                        }
     132
     133                        while ( current( $iteration ) < $current ) {
     134                                if ( false === next( $iteration ) ) {
     135                                        break;
     136                                }
     137                        }
     138
     139                        // If we have a new priority that didn't exist, but ::apply_filters() or ::do_action() thinks it's the current priority...
     140                        if ( $new_priority === $this->current_priority[ $index ] && ! $priority_existed ) {
     141                                // ... and the new priority is the same as what $this->iterations thinks is the previous priority,
     142                                // We need to move back to it.
     143
     144                                if ( false === current( $iteration ) ) {
     145                                        // If we've already moved off the end of the array, go back to the last element.
     146                                        $prev = end( $iteration );
     147                                } else {
     148                                        // Otherwise, just go back to the previous element.
     149                                        $prev = prev( $iteration );
     150                                }
     151                                if ( false === $prev ) {
     152                                        // Start of the array. Reset, and go about our day.
     153                                        reset( $iteration );
     154                                } elseif ( $new_priority !== $prev ) {
     155                                        // Previous wasn't the same. Move forward again.
     156                                        next( $iteration );
     157                                }
     158                        }
     159                }
     160                unset( $iteration );
     161        }
     162
     163        /**
     164         * Unhooks a function or method from a specific filter action.
     165         *
     166         * @since 4.7.0
     167         * @access public
     168         *
     169         * @param string   $tag                The filter hook to which the function to be removed is hooked. Used
     170         *                                     for building the callback ID when SPL is not available.
     171         * @param callable $function_to_remove The callback to be removed from running when the filter is applied.
     172         * @param int      $priority           The exact priority used when adding the original filter callback.
     173         * @return bool Whether the callback existed before it was removed.
     174         */
     175        public function remove_filter( $tag, $function_to_remove, $priority ) {
     176                $function_key = _wp_filter_build_unique_id( $tag, $function_to_remove, $priority );
     177
     178                $exists = isset( $this->callbacks[ $priority ][ $function_key ] );
     179                if ( $exists ) {
     180                        unset( $this->callbacks[ $priority ][ $function_key ] );
     181                        if ( ! $this->callbacks[ $priority ] ) {
     182                                unset( $this->callbacks[ $priority ] );
     183                                if ( $this->nesting_level > 0 ) {
     184                                        $this->resort_active_iterations();
     185                                }
     186                        }
     187                }
     188                return $exists;
     189        }
     190
     191        /**
     192         * Checks if a specific action has been registered for this hook.
     193         *
     194         * @since 4.7.0
     195         * @access public
     196         *
     197         * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
     198         * @param string        $tag               Optional. The name of the filter hook. Default empty.
     199         *                                         Used for building the callback ID when SPL is not available.
     200         * @return bool|int The priority of that hook is returned, or false if the function is not attached.
     201         */
     202        public function has_filter( $tag = '', $function_to_check = false ) {
     203                if ( false === $function_to_check ) {
     204                        return $this->has_filters();
     205                }
     206
     207                $function_key = _wp_filter_build_unique_id( $tag, $function_to_check, false );
     208                if ( ! $function_key ) {
     209                        return false;
     210                }
     211
     212                foreach ( $this->callbacks as $priority => $callbacks ) {
     213                        if ( isset( $callbacks[ $function_key ] ) ) {
     214                                return $priority;
     215                        }
     216                }
     217
     218                return false;
     219        }
     220
     221        /**
     222         * Checks if any callbacks have been registered for this hook.
     223         *
     224         * @since 4.7.0
     225         * @access public
     226         *
     227         * @return bool True if callbacks have been registered for the current hook, false otherwise.
     228         */
     229        public function has_filters() {
     230                foreach ( $this->callbacks as $callbacks ) {
     231                        if ( $callbacks ) {
     232                                return true;
     233                        }
     234                }
     235                return false;
     236        }
     237
     238        /**
     239         * Removes all callbacks from the current filter.
     240         *
     241         * @since 4.7.0
     242         * @access public
     243         *
     244         * @param int|bool $priority Optional. The priority number to remove. Default false.
     245         */
     246        public function remove_all_filters( $priority = false ) {
     247                if ( ! $this->callbacks ) {
     248                        return;
     249                }
     250
     251                if ( false === $priority ) {
     252                        $this->callbacks = array();
     253                } else if ( isset( $this->callbacks[ $priority ] ) ) {
     254                        unset( $this->callbacks[ $priority ] );
     255                }
     256
     257                if ( $this->nesting_level > 0 ) {
     258                        $this->resort_active_iterations();
     259                }
     260        }
     261
     262        /**
     263         * Calls the callback functions added to a filter hook.
     264         *
     265         * @since 4.7.0
     266         * @access public
     267         *
     268         * @param mixed $value The value to filter.
     269         * @param array $args  Arguments to pass to callbacks.
     270         * @return mixed The filtered value after all hooked functions are applied to it.
     271         */
     272        public function apply_filters( $value, $args ) {
     273                if ( ! $this->callbacks ) {
     274                        return $value;
     275                }
     276
     277                $nesting_level = $this->nesting_level++;
     278
     279                $this->iterations[ $nesting_level ] = array_keys( $this->callbacks );
     280                $num_args = count( $args );
     281
     282                do {
     283                        $this->current_priority[ $nesting_level ] = $priority = current( $this->iterations[ $nesting_level ] );
     284
     285                        foreach ( $this->callbacks[ $priority ] as $the_ ) {
     286                                if( ! $this->doing_action ) {
     287                                        $args[ 0 ] = $value;
     288                                }
     289
     290                                // Avoid the array_slice if possible.
     291                                if ( $the_['accepted_args'] == 0 ) {
     292                                        $value = call_user_func_array( $the_['function'], array() );
     293                                } elseif ( $the_['accepted_args'] >= $num_args ) {
     294                                        $value = call_user_func_array( $the_['function'], $args );
     295                                } else {
     296                                        $value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int)$the_['accepted_args'] ) );
     297                                }
     298                        }
     299                } while ( false !== next( $this->iterations[ $nesting_level ] ) );
     300
     301                unset( $this->iterations[ $nesting_level ] );
     302                unset( $this->current_priority[ $nesting_level ] );
     303
     304                $this->nesting_level--;
     305
     306                return $value;
     307        }
     308
     309        /**
     310         * Executes the callback functions hooked on a specific action hook.
     311         *
     312         * @since 4.7.0
     313         * @access public
     314         *
     315         * @param mixed $args Arguments to pass to the hook callbacks.
     316         */
     317        public function do_action( $args ) {
     318                $this->doing_action = true;
     319                $this->apply_filters( '', $args );
     320
     321                // If there are recursive calls to the current action, we haven't finished it until we get to the last one.
     322                if ( ! $this->nesting_level ) {
     323                        $this->doing_action = false;
     324                }
     325        }
     326
     327        /**
     328         * Processes the functions hooked into the 'all' hook.
     329         *
     330         * @since 4.7.0
     331         * @access public
     332         *
     333         * @param array $args Arguments to pass to the hook callbacks. Passed by reference.
     334         */
     335        public function do_all_hook( &$args ) {
     336                $nesting_level = $this->nesting_level++;
     337                $this->iterations[ $nesting_level ] = array_keys( $this->callbacks );
     338
     339                do {
     340                        $priority = current( $this->iterations[ $nesting_level ] );
     341                        foreach ( $this->callbacks[ $priority ] as $the_ ) {
     342                                call_user_func_array( $the_['function'], $args );
     343                        }
     344                } while ( false !== next( $this->iterations[ $nesting_level ] ) );
     345
     346                unset( $this->iterations[ $nesting_level ] );
     347                $this->nesting_level--;
     348        }
     349
     350        /**
     351         * Normalizes filters setup before WordPress has initialized to WP_Hook objects.
     352         *
     353         * @since 4.7.0
     354         * @access public
     355         * @static
     356         *
     357         * @param array $filters Filters to normalize.
     358         * @return WP_Hook[] Array of normalized filters.
     359         */
     360        public static function build_preinitialized_hooks( $filters ) {
     361                /** @var WP_Hook[] $normalized */
     362                $normalized = array();
     363
     364                foreach ( $filters as $tag => $callback_groups ) {
     365                        if ( is_object( $callback_groups ) && $callback_groups instanceof WP_Hook ) {
     366                                $normalized[ $tag ] = $callback_groups;
     367                                continue;
     368                        }
     369                        $hook = new WP_Hook();
     370
     371                        // Loop through callback groups.
     372                        foreach ( $callback_groups as $priority => $callbacks ) {
     373
     374                                // Loop through callbacks.
     375                                foreach ( $callbacks as $cb ) {
     376                                        $hook->add_filter( $tag, $cb['function'], $priority, $cb['accepted_args'] );
     377                                }
     378                        }
     379                        $normalized[ $tag ] = $hook;
     380                }
     381                return $normalized;
     382        }
     383
     384        /**
     385         * Determines whether an offset value exists.
     386         *
     387         * @since 4.7.0
     388         * @access public
     389         *
     390         * @link http://php.net/manual/en/arrayaccess.offsetexists.php
     391         *
     392         * @param mixed $offset An offset to check for.
     393         * @return bool True if the offset exists, false otherwise.
     394         */
     395        public function offsetExists( $offset ) {
     396                return isset( $this->callbacks[ $offset ] );
     397        }
     398
     399        /**
     400         * Retrieves a value at a specified offset.
     401         *
     402         * @since 4.7.0
     403         * @access public
     404         *
     405         * @link http://php.net/manual/en/arrayaccess.offsetget.php
     406         *
     407         * @param mixed $offset The offset to retrieve.
     408         * @return mixed If set, the value at the specified offset, null otherwise.
     409         */
     410        public function offsetGet( $offset ) {
     411                return isset( $this->callbacks[ $offset ] ) ? $this->callbacks[ $offset ] : null;
     412        }
     413
     414        /**
     415         * Sets a value at a specified offset.
     416         *
     417         * @since 4.7.0
     418         * @access public
     419         *
     420         * @link http://php.net/manual/en/arrayaccess.offsetset.php
     421         *
     422         * @param mixed $offset The offset to assign the value to.
     423         * @param mixed $value The value to set.
     424         */
     425        public function offsetSet( $offset, $value ) {
     426                if ( is_null( $offset ) ) {
     427                        $this->callbacks[] = $value;
     428                } else {
     429                        $this->callbacks[ $offset ] = $value;
     430                }
     431        }
     432
     433        /**
     434         * Unsets a specified offset.
     435         *
     436         * @since 4.7.0
     437         * @access public
     438         *
     439         * @link http://php.net/manual/en/arrayaccess.offsetunset.php
     440         *
     441         * @param mixed $offset The offset to unset.
     442         */
     443        public function offsetUnset( $offset ) {
     444                unset( $this->callbacks[ $offset ] );
     445        }
     446
     447        /**
     448         * Return the current element
     449         *
     450         * @since 4.7.0
     451         * @access public
     452         *
     453         * @link http://php.net/manual/en/iterator.current.php
     454         *
     455         * @return array Of callbacks at current priority.
     456         */
     457        public function current() {
     458                return current( $this->callbacks );
     459        }
     460
     461        /**
     462         * Move forward to the next element
     463         *
     464         * @since 4.7.0
     465         * @access public
     466         *
     467         * @link http://php.net/manual/en/iterator.next.php
     468         *
     469         * @return array Of callbacks at next priority.
     470         */
     471        public function next() {
     472                return next( $this->callbacks );
     473        }
     474
     475        /**
     476         * Return the key of the current element
     477         *
     478         * @since 4.7.0
     479         * @access public
     480         *
     481         * @link http://php.net/manual/en/iterator.key.php
     482         *
     483         * @return mixed Returns current priority on success, or NULL on failure
     484         */
     485        public function key() {
     486                return key( $this->callbacks );
     487        }
     488
     489        /**
     490         * Checks if current position is valid
     491         *
     492         * @since 4.7.0
     493         * @access public
     494         *
     495         * @link http://php.net/manual/en/iterator.valid.php
     496         *
     497         * @return boolean
     498         */
     499        public function valid() {
     500                return key( $this->callbacks ) !== null;
     501        }
     502
     503        /**
     504         * Rewind the Iterator to the first element
     505         *
     506         * @since 4.7.0
     507         * @access public
     508         *
     509         * @link http://php.net/manual/en/iterator.rewind.php
     510         */
     511        public function rewind() {
     512                reset( $this->callbacks );
     513        }
     514
     515
     516}
  • src/wp-includes/plugin.php

    diff --git a/src/wp-includes/plugin.php b/src/wp-includes/plugin.php
    old mode 100644
    new mode 100755
    index bdb9ebd..f2585c5
    a b  
    2222 */
    2323
    2424// Initialize the filter globals.
    25 global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
     25require( ABSPATH . WPINC . '/class-wp-hook.php' );
    2626
    27 if ( ! isset( $wp_filter ) )
     27/** @var WP_Hook[] $wp_filter */
     28global $wp_filter, $wp_actions, $wp_current_filter;
     29
     30if ( $wp_filter ) {
     31        $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
     32} else {
    2833        $wp_filter = array();
     34}
    2935
    3036if ( ! isset( $wp_actions ) )
    3137        $wp_actions = array();
    3238
    33 if ( ! isset( $merged_filters ) )
    34         $merged_filters = array();
    35 
    3639if ( ! isset( $wp_current_filter ) )
    3740        $wp_current_filter = array();
    3841
    if ( ! isset( $wp_current_filter ) ) 
    8992 * @since 0.71
    9093 *
    9194 * @global array $wp_filter      A multidimensional array of all hooks and the callbacks hooked to them.
    92  * @global array $merged_filters Tracks the tags that need to be merged for later. If the hook is added,
    93  *                               it doesn't need to run through that process.
    9495 *
    9596 * @param string   $tag             The name of the filter to hook the $function_to_add callback to.
    9697 * @param callable $function_to_add The callback to be run when the filter is applied.
    if ( ! isset( $wp_current_filter ) ) 
    103104 * @return true
    104105 */
    105106function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
    106         global $wp_filter, $merged_filters;
    107 
    108         $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
    109         $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
    110         unset( $merged_filters[ $tag ] );
     107        global $wp_filter;
     108        if ( ! isset( $wp_filter[ $tag ] ) ) {
     109                $wp_filter[ $tag ] = new WP_Hook();
     110        }
     111        $wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args );
    111112        return true;
    112113}
    113114
    function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 
    128129 *                   return value.
    129130 */
    130131function has_filter($tag, $function_to_check = false) {
    131         // Don't reset the internal array pointer
    132         $wp_filter = $GLOBALS['wp_filter'];
    133 
    134         $has = ! empty( $wp_filter[ $tag ] );
    135 
    136         // Make sure at least one priority has a filter callback
    137         if ( $has ) {
    138                 $exists = false;
    139                 foreach ( $wp_filter[ $tag ] as $callbacks ) {
    140                         if ( ! empty( $callbacks ) ) {
    141                                 $exists = true;
    142                                 break;
    143                         }
    144                 }
    145 
    146                 if ( ! $exists ) {
    147                         $has = false;
    148                 }
    149         }
    150 
    151         if ( false === $function_to_check || false === $has )
    152                 return $has;
     132        global $wp_filter;
    153133
    154         if ( !$idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )
     134        if ( ! isset( $wp_filter[ $tag ] ) ) {
    155135                return false;
    156 
    157         foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {
    158                 if ( isset($wp_filter[$tag][$priority][$idx]) )
    159                         return $priority;
    160136        }
    161137
    162         return false;
     138        return $wp_filter[ $tag ]->has_filter( $tag, $function_to_check );
    163139}
    164140
    165141/**
    function has_filter($tag, $function_to_check = false) { 
    190166 * @since 0.71
    191167 *
    192168 * @global array $wp_filter         Stores all of the filters.
    193  * @global array $merged_filters    Merges the filter hooks using this function.
    194169 * @global array $wp_current_filter Stores the list of current filters with the current one last.
    195170 *
    196171 * @param string $tag     The name of the filter hook.
    function has_filter($tag, $function_to_check = false) { 
    199174 * @return mixed The filtered value after all hooked functions are applied to it.
    200175 */
    201176function apply_filters( $tag, $value ) {
    202         global $wp_filter, $merged_filters, $wp_current_filter;
     177        global $wp_filter, $wp_current_filter;
    203178
    204179        $args = array();
    205180
    function apply_filters( $tag, $value ) { 
    219194        if ( !isset($wp_filter['all']) )
    220195                $wp_current_filter[] = $tag;
    221196
    222         // Sort.
    223         if ( !isset( $merged_filters[ $tag ] ) ) {
    224                 ksort($wp_filter[$tag]);
    225                 $merged_filters[ $tag ] = true;
    226         }
    227 
    228         reset( $wp_filter[ $tag ] );
    229 
    230197        if ( empty($args) )
    231198                $args = func_get_args();
    232199
    233         do {
    234                 foreach ( (array) current($wp_filter[$tag]) as $the_ )
    235                         if ( !is_null($the_['function']) ){
    236                                 $args[1] = $value;
    237                                 $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
    238                         }
     200        // don't pass the tag name to WP_Hook
     201        array_shift( $args );
    239202
    240         } while ( next($wp_filter[$tag]) !== false );
     203        $filtered = $wp_filter[ $tag ]->apply_filters( $value, $args );
    241204
    242205        array_pop( $wp_current_filter );
    243206
    244         return $value;
     207        return $filtered;
    245208}
    246209
    247210/**
    function apply_filters( $tag, $value ) { 
    253216 * functions hooked to `$tag` are supplied using an array.
    254217 *
    255218 * @global array $wp_filter         Stores all of the filters
    256  * @global array $merged_filters    Merges the filter hooks using this function.
    257219 * @global array $wp_current_filter Stores the list of current filters with the current one last
    258220 *
    259221 * @param string $tag  The name of the filter hook.
    function apply_filters( $tag, $value ) { 
    261223 * @return mixed The filtered value after all hooked functions are applied to it.
    262224 */
    263225function apply_filters_ref_array($tag, $args) {
    264         global $wp_filter, $merged_filters, $wp_current_filter;
     226        global $wp_filter, $wp_current_filter;
    265227
    266228        // Do 'all' actions first
    267229        if ( isset($wp_filter['all']) ) {
    function apply_filters_ref_array($tag, $args) { 
    279241        if ( !isset($wp_filter['all']) )
    280242                $wp_current_filter[] = $tag;
    281243
    282         // Sort
    283         if ( !isset( $merged_filters[ $tag ] ) ) {
    284                 ksort($wp_filter[$tag]);
    285                 $merged_filters[ $tag ] = true;
    286         }
    287 
    288         reset( $wp_filter[ $tag ] );
    289 
    290         do {
    291                 foreach ( (array) current($wp_filter[$tag]) as $the_ )
    292                         if ( !is_null($the_['function']) )
    293                                 $args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    294 
    295         } while ( next($wp_filter[$tag]) !== false );
     244        $filtered = $wp_filter[ $tag ]->apply_filters( $args[0], $args );
    296245
    297246        array_pop( $wp_current_filter );
    298247
    299         return $args[0];
     248        return $filtered;
    300249}
    301250
    302251/**
    function apply_filters_ref_array($tag, $args) { 
    313262 * @since 1.2.0
    314263 *
    315264 * @global array $wp_filter         Stores all of the filters
    316  * @global array $merged_filters    Merges the filter hooks using this function.
    317265 *
    318266 * @param string   $tag                The filter hook to which the function to be removed is hooked.
    319267 * @param callable $function_to_remove The name of the function which should be removed.
    function apply_filters_ref_array($tag, $args) { 
    321269 * @return bool    Whether the function existed before it was removed.
    322270 */
    323271function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
    324         $function_to_remove = _wp_filter_build_unique_id( $tag, $function_to_remove, $priority );
    325 
    326         $r = isset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] );
     272        global $wp_filter;
    327273
    328         if ( true === $r ) {
    329                 unset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] );
    330                 if ( empty( $GLOBALS['wp_filter'][ $tag ][ $priority ] ) ) {
    331                         unset( $GLOBALS['wp_filter'][ $tag ][ $priority ] );
     274        $r = false;
     275        if ( isset( $wp_filter[ $tag ] ) ) {
     276                $r = $wp_filter[ $tag ]->remove_filter( $tag, $function_to_remove, $priority );
     277                if ( ! $wp_filter[ $tag ]->callbacks ) {
     278                        unset( $wp_filter[ $tag ] );
    332279                }
    333                 if ( empty( $GLOBALS['wp_filter'][ $tag ] ) ) {
    334                         $GLOBALS['wp_filter'][ $tag ] = array();
    335                 }
    336                 unset( $GLOBALS['merged_filters'][ $tag ] );
    337280        }
    338281
    339282        return $r;
    function remove_filter( $tag, $function_to_remove, $priority = 10 ) { 
    344287 *
    345288 * @since 2.7.0
    346289 *
    347  * @global array $wp_filter         Stores all of the filters
    348  * @global array $merged_filters    Merges the filter hooks using this function.
     290 * @global array $wp_filter  Stores all of the filters
    349291 *
    350292 * @param string   $tag      The filter to remove hooks from.
    351293 * @param int|bool $priority Optional. The priority number to remove. Default false.
    352294 * @return true True when finished.
    353295 */
    354296function remove_all_filters( $tag, $priority = false ) {
    355         global $wp_filter, $merged_filters;
     297        global $wp_filter;
    356298
    357299        if ( isset( $wp_filter[ $tag ]) ) {
    358                 if ( false === $priority ) {
    359                         $wp_filter[ $tag ] = array();
    360                 } elseif ( isset( $wp_filter[ $tag ][ $priority ] ) ) {
    361                         $wp_filter[ $tag ][ $priority ] = array();
     300                $wp_filter[ $tag ]->remove_all_filters( $priority );
     301                if ( ! $wp_filter[ $tag ]->has_filters() ) {
     302                        unset( $wp_filter[ $tag ] );
    362303                }
    363304        }
    364305
    365         unset( $merged_filters[ $tag ] );
    366 
    367306        return true;
    368307}
    369308
    function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) 
    473412 *
    474413 * @global array $wp_filter         Stores all of the filters
    475414 * @global array $wp_actions        Increments the amount of times action was triggered.
    476  * @global array $merged_filters    Merges the filter hooks using this function.
    477415 * @global array $wp_current_filter Stores the list of current filters with the current one last
    478416 *
    479417 * @param string $tag     The name of the action to be executed.
    function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) 
    481419 *                        functions hooked to the action. Default empty.
    482420 */
    483421function do_action($tag, $arg = '') {
    484         global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
     422        global $wp_filter, $wp_actions, $wp_current_filter;
    485423
    486424        if ( ! isset($wp_actions[$tag]) )
    487425                $wp_actions[$tag] = 1;
    function do_action($tag, $arg = '') { 
    512450        for ( $a = 2, $num = func_num_args(); $a < $num; $a++ )
    513451                $args[] = func_get_arg($a);
    514452
    515         // Sort
    516         if ( !isset( $merged_filters[ $tag ] ) ) {
    517                 ksort($wp_filter[$tag]);
    518                 $merged_filters[ $tag ] = true;
    519         }
    520 
    521         reset( $wp_filter[ $tag ] );
    522 
    523         do {
    524                 foreach ( (array) current($wp_filter[$tag]) as $the_ )
    525                         if ( !is_null($the_['function']) )
    526                                 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    527 
    528         } while ( next($wp_filter[$tag]) !== false );
     453        $wp_filter[ $tag ]->do_action( $args );
    529454
    530455        array_pop($wp_current_filter);
    531456}
    function did_action($tag) { 
    558483 *                  functions hooked to $tag< are supplied using an array.
    559484 * @global array $wp_filter         Stores all of the filters
    560485 * @global array $wp_actions        Increments the amount of times action was triggered.
    561  * @global array $merged_filters    Merges the filter hooks using this function.
    562486 * @global array $wp_current_filter Stores the list of current filters with the current one last
    563487 *
    564488 * @param string $tag  The name of the action to be executed.
    565489 * @param array  $args The arguments supplied to the functions hooked to `$tag`.
    566490 */
    567491function do_action_ref_array($tag, $args) {
    568         global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
     492        global $wp_filter, $wp_actions, $wp_current_filter;
    569493
    570494        if ( ! isset($wp_actions[$tag]) )
    571495                $wp_actions[$tag] = 1;
    function do_action_ref_array($tag, $args) { 
    588512        if ( !isset($wp_filter['all']) )
    589513                $wp_current_filter[] = $tag;
    590514
    591         // Sort
    592         if ( !isset( $merged_filters[ $tag ] ) ) {
    593                 ksort($wp_filter[$tag]);
    594                 $merged_filters[ $tag ] = true;
    595         }
    596 
    597         reset( $wp_filter[ $tag ] );
    598 
    599         do {
    600                 foreach ( (array) current($wp_filter[$tag]) as $the_ )
    601                         if ( !is_null($the_['function']) )
    602                                 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    603 
    604         } while ( next($wp_filter[$tag]) !== false );
     515        $wp_filter[ $tag ]->do_action( $args );
    605516
    606517        array_pop($wp_current_filter);
    607518}
    function register_uninstall_hook( $file, $callback ) { 
    923834function _wp_call_all_hook($args) {
    924835        global $wp_filter;
    925836
    926         reset( $wp_filter['all'] );
    927         do {
    928                 foreach ( (array) current($wp_filter['all']) as $the_ )
    929                         if ( !is_null($the_['function']) )
    930                                 call_user_func_array($the_['function'], $args);
    931 
    932         } while ( next($wp_filter['all']) !== false );
     837        $wp_filter['all']->do_all_hook( $args );
    933838}
    934839
    935840/**
  • tests/phpunit/includes/functions.php

    diff --git a/tests/phpunit/includes/functions.php b/tests/phpunit/includes/functions.php
    old mode 100644
    new mode 100755
    index 7a9ef13..ce8ea69
    a b function tests_reset__SERVER() { 
    2121
    2222// For adding hooks before loading WP
    2323function tests_add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    24         global $wp_filter, $merged_filters;
     24        global $wp_filter;
    2525
    2626        $idx = _test_filter_build_unique_id($tag, $function_to_add, $priority);
    2727        $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
    28         unset( $merged_filters[ $tag ] );
    2928        return true;
    3029}
    3130
    3231function _test_filter_build_unique_id($tag, $function, $priority) {
    33         global $wp_filter;
    34         static $filter_id_count = 0;
    35 
    3632        if ( is_string($function) )
    3733                return $function;
    3834
  • tests/phpunit/includes/testcase.php

    diff --git a/tests/phpunit/includes/testcase.php b/tests/phpunit/includes/testcase.php
    old mode 100644
    new mode 100755
    index 288f7fe..1c4d758
    a b class WP_UnitTestCase extends PHPUnit_Framework_TestCase { 
    223223         * @return void
    224224         */
    225225        protected function _backup_hooks() {
    226                 $globals = array( 'merged_filters', 'wp_actions', 'wp_current_filter', 'wp_filter' );
     226                $globals = array( 'wp_actions', 'wp_current_filter' );
    227227                foreach ( $globals as $key ) {
    228228                        self::$hooks_saved[ $key ] = $GLOBALS[ $key ];
    229229                }
     230                self::$hooks_saved['wp_filter'] = array();
     231                foreach ( $GLOBALS['wp_filter'] as $hook_name => $hook_object ) {
     232                        self::$hooks_saved['wp_filter'][ $hook_name ] = clone $hook_object;
     233                }
    230234        }
    231235
    232236        /**
    class WP_UnitTestCase extends PHPUnit_Framework_TestCase { 
    240244         * @return void
    241245         */
    242246        protected function _restore_hooks() {
    243                 $globals = array( 'merged_filters', 'wp_actions', 'wp_current_filter', 'wp_filter' );
     247                $globals = array( 'wp_actions', 'wp_current_filter' );
    244248                foreach ( $globals as $key ) {
    245249                        if ( isset( self::$hooks_saved[ $key ] ) ) {
    246250                                $GLOBALS[ $key ] = self::$hooks_saved[ $key ];
    247251                        }
    248252                }
     253                if ( isset( self::$hooks_saved['wp_filter'] ) ) {
     254                        $GLOBALS['wp_filter'] = array();
     255                        foreach ( self::$hooks_saved['wp_filter'] as $hook_name => $hook_object ) {
     256                                $GLOBALS['wp_filter'][ $hook_name ] = clone $hook_object;
     257                        }
     258                }
    249259        }
    250260
    251261        static function flush_cache() {
  • tests/phpunit/tests/actions.php

    diff --git a/tests/phpunit/tests/actions.php b/tests/phpunit/tests/actions.php
    old mode 100644
    new mode 100755
    index 9bafdca..0f2789a
    a b class Tests_Actions extends WP_UnitTestCase { 
    114114                $this->assertEquals( array( $val1 ), array_pop( $argsvar2 ) );
    115115        }
    116116
     117        /**
     118         * Test that multiple callbacks receive the correct number of args even when the number
     119         * is less than, or greater than previous hooks.
     120         *
     121         * @see https://core.trac.wordpress.org/ticket/17817#comment:72
     122         * @ticket 17817
     123         */
     124        function test_action_args_3() {
     125                $a1 = new MockAction();
     126                $a2 = new MockAction();
     127                $a3 = new MockAction();
     128                $tag = rand_str();
     129                $val1 = rand_str();
     130                $val2 = rand_str();
     131
     132                // a1 accepts two arguments, a2 doesn't, a3 accepts two arguments
     133                add_action( $tag, array( &$a1, 'action' ), 10, 2 );
     134                add_action( $tag, array( &$a2, 'action' ) );
     135                add_action( $tag, array( &$a3, 'action' ), 10, 2 );
     136                // call the action with two arguments
     137                do_action( $tag, $val1, $val2 );
     138
     139                $call_count = $a1->get_call_count();
     140                // a1 should be called with both args
     141                $this->assertEquals( 1, $call_count );
     142                $argsvar1 = $a1->get_args();
     143                $this->assertEquals( array( $val1, $val2 ), array_pop( $argsvar1 ) );
     144
     145                // a2 should be called with one only
     146                $this->assertEquals( 1, $a2->get_call_count() );
     147                $argsvar2 = $a2->get_args();
     148                $this->assertEquals( array( $val1 ), array_pop( $argsvar2 ) );
     149
     150                // a3 should be called with both args
     151                $this->assertEquals( 1, $a3->get_call_count() );
     152                $argsvar3 = $a3->get_args();
     153                $this->assertEquals( array( $val1, $val2 ), array_pop( $argsvar3 ) );
     154        }
     155
    117156        function test_action_priority() {
    118157                $a = new MockAction();
    119158                $tag = rand_str();
    class Tests_Actions extends WP_UnitTestCase { 
    258297        }
    259298
    260299        /**
     300         * @ticket 17817
     301         */
     302        function test_action_recursion() {
     303                $tag = rand_str();
     304                $a = new MockAction();
     305                $b = new MockAction();
     306
     307                add_action( $tag, array( $a, 'action' ), 11, 1 );
     308                add_action( $tag, array( $b, 'action' ), 13, 1 );
     309                add_action( $tag, array( $this, 'action_that_causes_recursion' ), 12, 1 );
     310                do_action( $tag, $tag );
     311
     312                $this->assertEquals( 2, $a->get_call_count(), 'recursive actions should call all callbacks with earlier priority' );
     313                $this->assertEquals( 2, $b->get_call_count(), 'recursive actions should call callbacks with later priority' );
     314        }
     315
     316        function action_that_causes_recursion( $tag ) {
     317                static $recursing = false;
     318                if ( ! $recursing ) {
     319                        $recursing = true;
     320                        do_action( $tag, $tag );
     321                }
     322                $recursing = false;
     323        }
     324
     325        /**
     326         * @ticket 9968
     327         * @ticket 17817
     328         */
     329        function test_action_callback_manipulation_while_running() {
     330                $tag = rand_str();
     331                $a = new MockAction();
     332                $b = new MockAction();
     333                $c = new MockAction();
     334                $d = new MockAction();
     335                $e = new MockAction();
     336
     337                add_action( $tag, array( $a, 'action' ), 11, 2 );
     338                add_action( $tag, array( $this, 'action_that_manipulates_a_running_hook' ), 12, 2 );
     339                add_action( $tag, array( $b, 'action' ), 12, 2 );
     340
     341                do_action( $tag, $tag, array( $a, $b, $c, $d, $e ) );
     342                do_action( $tag, $tag, array( $a, $b, $c, $d, $e ) );
     343
     344                $this->assertEquals( 2, $a->get_call_count(), 'callbacks should run unless otherwise instructed' );
     345                $this->assertEquals( 1, $b->get_call_count(), 'callback removed by same priority callback should still get called' );
     346                $this->assertEquals( 1, $c->get_call_count(), 'callback added by same priority callback should not get called' );
     347                $this->assertEquals( 2, $d->get_call_count(), 'callback added by earlier priority callback should get called' );
     348                $this->assertEquals( 1, $e->get_call_count(), 'callback added by later priority callback should not get called' );
     349        }
     350
     351        function action_that_manipulates_a_running_hook( $tag, $mocks ) {
     352                remove_action( $tag, array( $mocks[ 1 ], 'action' ), 12, 2 );
     353                add_action( $tag, array( $mocks[ 2 ], 'action' ), 12, 2 );
     354                add_action( $tag, array( $mocks[ 3 ], 'action' ), 13, 2 );
     355                add_action( $tag, array( $mocks[ 4 ], 'action' ), 10, 2 );
     356        }
     357
     358        /**
     359         * @ticket 17817
     360         *
     361         * This specificaly addresses the concern raised at
     362         * https://core.trac.wordpress.org/ticket/17817#comment:52
     363         */
     364        function test_remove_anonymous_callback() {
     365                $tag = rand_str();
     366                $a = new MockAction();
     367                add_action( $tag, array( $a, 'action' ), 12, 1 );
     368                $this->assertTrue( has_action( $tag ) );
     369
     370                $hook = $GLOBALS['wp_filter'][ $tag ];
     371
     372                // From http://wordpress.stackexchange.com/a/57088/6445
     373                foreach ( $hook as $priority => $filter ) {
     374                        foreach ( $filter as $identifier => $function ) {
     375                                if ( is_array( $function )
     376                                        && is_a( $function['function'][ 0 ], 'MockAction' )
     377                                        && 'action' === $function['function'][ 1 ]
     378                                ) {
     379                                        remove_filter(
     380                                                $tag,
     381                                                array( $function['function'][ 0 ], 'action' ),
     382                                                $priority
     383                                        );
     384                                }
     385                        }
     386                }
     387
     388                $this->assertFalse( has_action( $tag ) );
     389        }
     390
     391
     392        /**
     393         * Test the ArrayAccess methods of WP_Hook
     394         *
     395         * @ticket 17817
     396         */
     397        function test_array_access_of_wp_filter_global() {
     398                global $wp_filter;
     399                $tag = rand_str();
     400
     401                add_action( $tag, '__return_null', 11, 1 );
     402
     403                $this->assertTrue( isset( $wp_filter[ $tag ][ 11 ] ) );
     404                $this->assertArrayHasKey( '__return_null', $wp_filter[ $tag ][ 11 ] );
     405
     406                unset( $wp_filter[ $tag ][ 11 ] );
     407                $this->assertFalse( has_action( $tag, '__return_null' ) );
     408
     409                $wp_filter[ $tag ][ 11 ] = array( '__return_null' => array( 'function' => '__return_null', 'accepted_args' => 1 ) );
     410                $this->assertEquals( 11, has_action( $tag, '__return_null' ) );
     411        }
     412
     413        /**
    261414         * Make sure current_action() behaves as current_filter()
    262415         *
    263416         * @ticket 14994
  • tests/phpunit/tests/filters.php

    diff --git a/tests/phpunit/tests/filters.php b/tests/phpunit/tests/filters.php
    old mode 100644
    new mode 100755
    index 88fa713..d2e6ddf
    a b class Tests_Filters extends WP_UnitTestCase { 
    296296        }
    297297
    298298        /**
    299          * @ticket 29070
    300          */
    301          function test_has_filter_doesnt_reset_wp_filter() {
    302                 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 1 );
    303                 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 2 );
    304                 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', '__return_null', 3 );
    305                 add_action( 'action_test_has_filter_doesnt_reset_wp_filter', array( $this, '_action_test_has_filter_doesnt_reset_wp_filter' ), 4 );
    306 
    307                 do_action( 'action_test_has_filter_doesnt_reset_wp_filter' );
    308          }
    309          function _action_test_has_filter_doesnt_reset_wp_filter() {
    310                 global $wp_filter;
    311 
    312                 has_action( 'action_test_has_filter_doesnt_reset_wp_filter', '_function_that_doesnt_exist' );
    313 
    314                 $filters = current( $wp_filter['action_test_has_filter_doesnt_reset_wp_filter'] );
    315                 $the_ = current( $filters );
    316                 $this->assertEquals( $the_['function'], array( $this, '_action_test_has_filter_doesnt_reset_wp_filter' ) );
    317          }
    318 
    319         /**
    320299         * @ticket 10441
    321300         * @expectedDeprecated tests_apply_filters_deprecated
    322301         */
  • tests/phpunit/tests/hooks/add_filter.php

    diff --git a/tests/phpunit/tests/hooks/add_filter.php b/tests/phpunit/tests/hooks/add_filter.php
    index e69de29..35ac55e 100644
    a b  
     1<?php
     2
     3
     4/**
     5 * Test the add_filter method of WP_Hook
     6 *
     7 * @group hooks
     8 */
     9class Tests_WP_Hook_Add_Filter extends WP_UnitTestCase {
     10
     11        public $hook;
     12
     13        public function test_add_filter_with_function() {
     14                $callback = '__return_null';
     15                $hook = new WP_Hook();
     16                $tag = rand_str();
     17                $priority = rand( 1, 100 );
     18                $accepted_args = rand( 1, 100 );
     19
     20                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     21
     22                $function_index = _wp_filter_build_unique_id( $tag, $callback, $priority );
     23                $this->assertEquals( $callback, $hook->callbacks[ $priority ][ $function_index ]['function'] );
     24                $this->assertEquals( $accepted_args, $hook->callbacks[ $priority ][ $function_index ]['accepted_args'] );
     25        }
     26
     27        public function test_add_filter_with_object() {
     28                $a = new MockAction();
     29                $callback = array( $a, 'action' );
     30                $hook = new WP_Hook();
     31                $tag = rand_str();
     32                $priority = rand( 1, 100 );
     33                $accepted_args = rand( 1, 100 );
     34
     35                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     36
     37                $function_index = _wp_filter_build_unique_id( $tag, $callback, $priority );
     38                $this->assertEquals( $callback, $hook->callbacks[ $priority ][ $function_index ]['function'] );
     39                $this->assertEquals( $accepted_args, $hook->callbacks[ $priority ][ $function_index ]['accepted_args'] );
     40        }
     41
     42        public function test_add_filter_with_static_method() {
     43                $callback = array( 'MockAction', 'action' );
     44                $hook = new WP_Hook();
     45                $tag = rand_str();
     46                $priority = rand( 1, 100 );
     47                $accepted_args = rand( 1, 100 );
     48
     49                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     50
     51                $function_index = _wp_filter_build_unique_id( $tag, $callback, $priority );
     52                $this->assertEquals( $callback, $hook->callbacks[ $priority ][ $function_index ]['function'] );
     53                $this->assertEquals( $accepted_args, $hook->callbacks[ $priority ][ $function_index ]['accepted_args'] );
     54        }
     55
     56        public function test_add_two_filters_with_same_priority() {
     57                $callback_one = '__return_null';
     58                $callback_two = '__return_false';
     59                $hook = new WP_Hook();
     60                $tag = rand_str();
     61                $priority = rand( 1, 100 );
     62                $accepted_args = rand( 1, 100 );
     63
     64                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     65                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     66
     67                $hook->add_filter( $tag, $callback_two, $priority, $accepted_args );
     68                $this->assertCount( 2, $hook->callbacks[ $priority ] );
     69        }
     70
     71        public function test_add_two_filters_with_different_priority() {
     72                $callback_one = '__return_null';
     73                $callback_two = '__return_false';
     74                $hook = new WP_Hook();
     75                $tag = rand_str();
     76                $priority = rand( 1, 100 );
     77                $accepted_args = rand( 1, 100 );
     78
     79                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     80                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     81
     82                $hook->add_filter( $tag, $callback_two, $priority + 1, $accepted_args );
     83                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     84                $this->assertCount( 1, $hook->callbacks[ $priority + 1 ] );
     85        }
     86
     87        public function test_readd_filter() {
     88                $callback = '__return_null';
     89                $hook = new WP_Hook();
     90                $tag = rand_str();
     91                $priority = rand( 1, 100 );
     92                $accepted_args = rand( 1, 100 );
     93
     94                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     95                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     96
     97                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     98                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     99        }
     100
     101        public function test_readd_filter_with_different_priority() {
     102                $callback = '__return_null';
     103                $hook = new WP_Hook();
     104                $tag = rand_str();
     105                $priority = rand( 1, 100 );
     106                $accepted_args = rand( 1, 100 );
     107
     108                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     109                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     110
     111                $hook->add_filter( $tag, $callback, $priority + 1, $accepted_args );
     112                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     113                $this->assertCount( 1, $hook->callbacks[ $priority + 1 ] );
     114        }
     115
     116        public function test_sort_after_add_filter() {
     117                $a = new MockAction();
     118                $b = new MockAction();
     119                $c = new MockAction();
     120                $hook = new WP_Hook();
     121                $tag = rand_str();
     122
     123                $hook->add_filter( $tag, array( $a, 'action' ), 10, 1 );
     124                $hook->add_filter( $tag, array( $b, 'action' ), 5, 1 );
     125                $hook->add_filter( $tag, array( $c, 'action' ), 8, 1 );
     126
     127                $this->assertEquals( array( 5, 8, 10 ), array_keys( $hook->callbacks ) );
     128        }
     129
     130        public function test_remove_and_add() {
     131                $this->hook = new Wp_Hook();
     132
     133                $this->hook->add_filter( 'remove_and_add', '__return_empty_string', 10, 0 );
     134
     135                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add2' ), 11, 1 );
     136
     137                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add4' ), 12, 1 );
     138
     139                $value = $this->hook->apply_filters( '', array() );
     140
     141                $this->assertSame( '24', $value );
     142        }
     143
     144        public function test_remove_and_add_last_filter() {
     145                $this->hook = new Wp_Hook();
     146
     147                $this->hook->add_filter( 'remove_and_add', '__return_empty_string', 10, 0 );
     148
     149                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add1' ), 11, 1 );
     150
     151                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add2' ), 12, 1 );
     152
     153                $value = $this->hook->apply_filters( '', array() );
     154
     155                $this->assertSame( '12', $value );
     156        }
     157
     158        public function test_remove_and_recurse_and_add() {
     159                $this->hook = new Wp_Hook();
     160
     161                $this->hook->add_filter( 'remove_and_add', '__return_empty_string', 10, 0 );
     162
     163                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add1' ), 11, 1 );
     164                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_recurse_and_add2' ), 11, 1 );
     165                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add3' ), 11, 1 );
     166
     167                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add4' ), 12, 1 );
     168
     169                $value = $this->hook->apply_filters( '', array() );
     170
     171                $this->assertSame( '1-134-234', $value );
     172        }
     173
     174        public function _filter_remove_and_add1( $string ) {
     175                return $string . '1';
     176        }
     177
     178        public function _filter_remove_and_add2( $string ) {
     179                $this->hook->remove_filter( 'remove_and_add', array( $this, '_filter_remove_and_add2' ), 11 );
     180                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_add2' ), 11, 1 );
     181
     182                return $string . '2';
     183        }
     184
     185        public function _filter_remove_and_recurse_and_add2( $string ) {
     186                $this->hook->remove_filter( 'remove_and_add', array( $this, '_filter_remove_and_recurse_and_add2' ), 11 );
     187
     188                $string .= '-' . $this->hook->apply_filters( '', array() ) . '-';
     189
     190                $this->hook->add_filter( 'remove_and_add', array( $this, '_filter_remove_and_recurse_and_add2' ), 11, 1 );
     191
     192                return $string . '2';
     193        }
     194
     195        public function _filter_remove_and_add3( $string ) {
     196                return $string . '3';
     197        }
     198
     199        public function _filter_remove_and_add4( $string ) {
     200                return $string . '4';
     201        }
     202
     203        public function test_remove_and_add_action() {
     204                $this->hook = new Wp_Hook();
     205                $this->action_output = '';
     206
     207                $this->hook->add_filter( 'remove_and_add_action', '__return_empty_string', 10, 0 );
     208
     209                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add2' ), 11, 0 );
     210
     211                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add4' ), 12, 0 );
     212
     213                $this->hook->do_action( array() );
     214
     215                $this->assertSame( '24', $this->action_output );
     216        }
     217
     218        public function test_remove_and_add_last_action() {
     219                $this->hook = new Wp_Hook();
     220                $this->action_output = '';
     221
     222                $this->hook->add_filter( 'remove_and_add_action', '__return_empty_string', 10, 0 );
     223
     224                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add1' ), 11, 0 );
     225
     226                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add2' ), 12, 0 );
     227
     228                $this->hook->do_action( array() );
     229
     230                $this->assertSame( '12', $this->action_output );
     231        }
     232
     233        public function test_remove_and_recurse_and_add_action() {
     234                $this->hook = new Wp_Hook();
     235                $this->action_output = '';
     236
     237                $this->hook->add_filter( 'remove_and_add_action', '__return_empty_string', 10, 0 );
     238
     239                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add1' ), 11, 0 );
     240                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_recurse_and_add2' ), 11, 0 );
     241                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add3' ), 11, 0 );
     242
     243                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add4' ), 12, 0 );
     244
     245                $this->hook->do_action( array() );
     246
     247                $this->assertSame( '1-134-234', $this->action_output );
     248        }
     249
     250        public function _action_remove_and_add1() {
     251                $this->action_output .= 1;
     252        }
     253
     254        public function _action_remove_and_add2() {
     255                $this->hook->remove_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add2' ), 11 );
     256                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_add2' ), 11, 0 );
     257
     258                $this->action_output .= '2';
     259        }
     260
     261        public function _action_remove_and_recurse_and_add2() {
     262                $this->hook->remove_filter( 'remove_and_add_action', array( $this, '_action_remove_and_recurse_and_add2' ), 11 );
     263
     264                $this->action_output .= '-';
     265                $this->hook->do_action( array() );
     266                $this->action_output .= '-';
     267
     268                $this->hook->add_filter( 'remove_and_add_action', array( $this, '_action_remove_and_recurse_and_add2' ), 11, 0 );
     269
     270                $this->action_output .= '2';
     271        }
     272
     273        public function _action_remove_and_add3() {
     274                $this->action_output .= '3';
     275        }
     276
     277        public function _action_remove_and_add4() {
     278                $this->action_output .= '4';
     279        }
     280}
  • tests/phpunit/tests/hooks/apply_filters.php

    diff --git a/tests/phpunit/tests/hooks/apply_filters.php b/tests/phpunit/tests/hooks/apply_filters.php
    index e69de29..048a00a 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the apply_filters method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Apply_Filters extends WP_UnitTestCase {
     9
     10        public function test_apply_filters_with_callback() {
     11                $a = new MockAction();
     12                $callback = array( $a, 'filter' );
     13                $hook = new WP_Hook();
     14                $tag = rand_str();
     15                $priority = rand( 1, 100 );
     16                $accepted_args = rand( 1, 100 );
     17                $arg = rand_str();
     18
     19                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     20
     21                $returned = $hook->apply_filters( $arg, array( $arg ) );
     22
     23                $this->assertEquals( $returned, $arg );
     24                $this->assertEquals( 1, $a->get_call_count() );
     25        }
     26
     27        public function test_apply_filters_with_multiple_calls() {
     28                $a = new MockAction();
     29                $callback = array( $a, 'filter' );
     30                $hook = new WP_Hook();
     31                $tag = rand_str();
     32                $priority = rand( 1, 100 );
     33                $accepted_args = rand( 1, 100 );
     34                $arg = rand_str();
     35
     36                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     37
     38                $returned_one = $hook->apply_filters( $arg, array( $arg ) );
     39                $returned_two = $hook->apply_filters( $returned_one, array( $returned_one ) );
     40
     41                $this->assertEquals( $returned_two, $arg );
     42                $this->assertEquals( 2, $a->get_call_count() );
     43        }
     44
     45}
  • tests/phpunit/tests/hooks/do_action.php

    diff --git a/tests/phpunit/tests/hooks/do_action.php b/tests/phpunit/tests/hooks/do_action.php
    index e69de29..b810d46 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the do_action method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Do_Action extends WP_UnitTestCase {
     9        private $events = array();
     10        private $action_output = '';
     11        private $hook;
     12
     13        public function setUp() {
     14                parent::setUp();
     15                $this->events = array();
     16        }
     17
     18        public function test_do_action_with_callback() {
     19                $a = new MockAction();
     20                $callback = array( $a, 'action' );
     21                $hook = new WP_Hook();
     22                $tag = rand_str();
     23                $priority = rand( 1, 100 );
     24                $accepted_args = rand( 1, 100 );
     25                $arg = rand_str();
     26
     27                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     28                $hook->do_action( array( $arg ) );
     29
     30                $this->assertEquals( 1, $a->get_call_count() );
     31        }
     32
     33        public function test_do_action_with_multiple_calls() {
     34                $a = new MockAction();
     35                $callback = array( $a, 'filter' );
     36                $hook = new WP_Hook();
     37                $tag = rand_str();
     38                $priority = rand( 1, 100 );
     39                $accepted_args = rand( 1, 100 );
     40                $arg = rand_str();
     41
     42                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     43                $hook->do_action( array( $arg ) );
     44                $hook->do_action( array( $arg ) );
     45
     46                $this->assertEquals( 2, $a->get_call_count() );
     47        }
     48
     49        public function test_do_action_with_multiple_callbacks_on_same_priority() {
     50                $a = new MockAction();
     51                $b = new MockAction();
     52                $callback_one = array( $a, 'filter' );
     53                $callback_two = array( $b, 'filter' );
     54                $hook = new WP_Hook();
     55                $tag = rand_str();
     56                $priority = rand( 1, 100 );
     57                $accepted_args = rand( 1, 100 );
     58                $arg = rand_str();
     59
     60                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     61                $hook->add_filter( $tag, $callback_two, $priority, $accepted_args );
     62                $hook->do_action( array( $arg ) );
     63
     64                $this->assertEquals( 1, $a->get_call_count() );
     65                $this->assertEquals( 1, $a->get_call_count() );
     66        }
     67
     68        public function test_do_action_with_multiple_callbacks_on_different_priorities() {
     69                $a = new MockAction();
     70                $b = new MockAction();
     71                $callback_one = array( $a, 'filter' );
     72                $callback_two = array( $b, 'filter' );
     73                $hook = new WP_Hook();
     74                $tag = rand_str();
     75                $priority = rand( 1, 100 );
     76                $accepted_args = rand( 1, 100 );
     77                $arg = rand_str();
     78
     79                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     80                $hook->add_filter( $tag, $callback_two, $priority, $accepted_args );
     81                $hook->do_action( array( $arg ) );
     82
     83                $this->assertEquals( 1, $a->get_call_count() );
     84                $this->assertEquals( 1, $a->get_call_count() );
     85        }
     86
     87        public function test_do_action_with_no_accepted_args() {
     88                $callback = array( $this, '_action_callback' );
     89                $hook = new WP_Hook();
     90                $tag = rand_str();
     91                $priority = rand( 1, 100 );
     92                $accepted_args = 0;
     93                $arg = rand_str();
     94
     95                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     96                $hook->do_action( array( $arg ) );
     97
     98                $this->assertEmpty( $this->events[0]['args'] );
     99        }
     100
     101        public function test_do_action_with_one_accepted_arg() {
     102                $callback = array( $this, '_action_callback' );
     103                $hook = new WP_Hook();
     104                $tag = rand_str();
     105                $priority = rand( 1, 100 );
     106                $accepted_args = 1;
     107                $arg = rand_str();
     108
     109                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     110                $hook->do_action( array( $arg ) );
     111
     112                $this->assertCount( 1, $this->events[0]['args'] );
     113        }
     114
     115        public function test_do_action_with_more_accepted_args() {
     116                $callback = array( $this, '_action_callback' );
     117                $hook = new WP_Hook();
     118                $tag = rand_str();
     119                $priority = rand( 1, 100 );
     120                $accepted_args = 1000;
     121                $arg = rand_str();
     122
     123                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     124                $hook->do_action( array( $arg ) );
     125
     126                $this->assertCount( 1, $this->events[0]['args'] );
     127        }
     128
     129        public function test_do_action_doesnt_change_value() {
     130                $this->hook = new WP_Hook();
     131                $this->action_output = '';
     132
     133                $this->hook->add_filter( 'do_action_doesnt_change_value', array( $this, '_filter_do_action_doesnt_change_value1' ), 10, 1 );
     134                $this->hook->add_filter( 'do_action_doesnt_change_value', array( $this, '_filter_do_action_doesnt_change_value2' ), 10, 1 );
     135                $this->hook->add_filter( 'do_action_doesnt_change_value', array( $this, '_filter_do_action_doesnt_change_value3' ), 11, 1 );
     136
     137                $this->hook->do_action( array( 'a' ) );
     138
     139                $this->assertSame( 'a1-b1b3-a2a3', $this->action_output );
     140        }
     141
     142        public function _filter_do_action_doesnt_change_value1( $value ) {
     143                $this->action_output .= $value . 1;
     144                return 'x1';
     145        }
     146        public function _filter_do_action_doesnt_change_value2( $value ) {
     147                $this->hook->remove_filter( 'do_action_doesnt_change_value', array( $this, '_filter_do_action_doesnt_change_value2' ), 10 );
     148
     149                $this->action_output .= '-';
     150                $this->hook->do_action( array( 'b' ) );
     151                $this->action_output .= '-';
     152
     153                $this->hook->add_filter( 'do_action_doesnt_change_value', array( $this, '_filter_do_action_doesnt_change_value2' ), 10, 1 );
     154
     155                $this->action_output .= $value . 2;
     156
     157                return 'x2';
     158        }
     159
     160        public function _filter_do_action_doesnt_change_value3( $value ) {
     161                $this->action_output .= $value . 3;
     162                return 'x3';
     163        }
     164
     165        /**
     166         * Use this rather than MockAction so we can test callbacks with no args
     167         */
     168        public function _action_callback() {
     169                $args = func_get_args();
     170                $this->events[] = array('action' => __FUNCTION__, 'args'=>$args);
     171        }
     172}
  • tests/phpunit/tests/hooks/do_all_hook.php

    diff --git a/tests/phpunit/tests/hooks/do_all_hook.php b/tests/phpunit/tests/hooks/do_all_hook.php
    index e69de29..a1e3586 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the do_all_hook method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Do_All_Hook extends WP_UnitTestCase {
     9
     10        public function test_do_all_hook_with_multiple_calls() {
     11                $a = new MockAction();
     12                $callback = array( $a, 'action' );
     13                $hook = new WP_Hook();
     14                $tag = 'all';
     15                $priority = rand( 1, 100 );
     16                $accepted_args = rand( 1, 100 );
     17                $arg = rand_str();
     18
     19                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     20                $args = array( $arg );
     21                $hook->do_all_hook( $args );
     22                $hook->do_all_hook( $args );
     23
     24                $this->assertEquals( 2, $a->get_call_count() );
     25        }
     26}
  • tests/phpunit/tests/hooks/has_filter.php

    diff --git a/tests/phpunit/tests/hooks/has_filter.php b/tests/phpunit/tests/hooks/has_filter.php
    index e69de29..0e65b42 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the has_filter method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Has_Filter extends WP_UnitTestCase {
     9
     10        public function test_has_filter_with_function() {
     11                $callback = '__return_null';
     12                $hook = new WP_Hook();
     13                $tag = rand_str();
     14                $priority = rand( 1, 100 );
     15                $accepted_args = rand( 1, 100 );
     16
     17                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     18
     19                $this->assertEquals( $priority, $hook->has_filter( $tag, $callback ) );
     20        }
     21
     22        public function test_has_filter_with_object() {
     23                $a = new MockAction();
     24                $callback = array( $a, 'action' );
     25                $hook = new WP_Hook();
     26                $tag = rand_str();
     27                $priority = rand( 1, 100 );
     28                $accepted_args = rand( 1, 100 );
     29
     30                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     31
     32                $this->assertEquals( $priority, $hook->has_filter( $tag, $callback ) );
     33        }
     34
     35        public function test_has_filter_with_static_method() {
     36                $callback = array( 'MockAction', 'action' );
     37                $hook = new WP_Hook();
     38                $tag = rand_str();
     39                $priority = rand( 1, 100 );
     40                $accepted_args = rand( 1, 100 );
     41
     42                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     43
     44                $this->assertEquals( $priority, $hook->has_filter( $tag, $callback ) );
     45        }
     46
     47        public function test_has_filter_without_callback() {
     48                $callback = '__return_null';
     49                $hook = new WP_Hook();
     50                $tag = rand_str();
     51                $priority = rand( 1, 100 );
     52                $accepted_args = rand( 1, 100 );
     53
     54                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     55
     56                $this->assertTrue( $hook->has_filter() );
     57        }
     58
     59        public function test_not_has_filter_without_callback() {
     60                $hook = new WP_Hook();
     61                $this->assertFalse( $hook->has_filter() );
     62        }
     63
     64        public function test_not_has_filter_with_callback() {
     65                $callback = '__return_null';
     66                $hook = new WP_Hook();
     67                $tag = rand_str();
     68
     69                $this->assertFalse( $hook->has_filter( $tag, $callback ) );
     70        }
     71
     72        public function test_has_filter_with_wrong_callback() {
     73                $callback = '__return_null';
     74                $hook = new WP_Hook();
     75                $tag = rand_str();
     76                $priority = rand( 1, 100 );
     77                $accepted_args = rand( 1, 100 );
     78
     79                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     80
     81                $this->assertFalse( $hook->has_filter( $tag, '__return_false' ) );
     82        }
     83}
  • tests/phpunit/tests/hooks/has_filters.php

    diff --git a/tests/phpunit/tests/hooks/has_filters.php b/tests/phpunit/tests/hooks/has_filters.php
    index e69de29..becf441 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the has_filters method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Has_Filters extends WP_UnitTestCase {
     9
     10        public function test_has_filters_with_callback() {
     11                $callback = '__return_null';
     12                $hook = new WP_Hook();
     13                $tag = rand_str();
     14                $priority = rand( 1, 100 );
     15                $accepted_args = rand( 1, 100 );
     16
     17                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     18
     19                $this->assertTrue( $hook->has_filters() );
     20        }
     21
     22        public function test_has_filters_without_callback() {
     23                $hook = new WP_Hook();
     24                $this->assertFalse( $hook->has_filters() );
     25        }
     26
     27        public function test_not_has_filters_with_removed_callback() {
     28                $callback = '__return_null';
     29                $hook = new WP_Hook();
     30                $tag = rand_str();
     31                $priority = rand( 1, 100 );
     32                $accepted_args = rand( 1, 100 );
     33
     34                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     35                $hook->remove_filter( $tag, $callback, $priority );
     36                $this->assertFalse( $hook->has_filters() );
     37        }
     38
     39        public function test_not_has_filter_with_directly_removed_callback() {
     40                $callback = '__return_null';
     41                $hook = new WP_Hook();
     42                $tag = rand_str();
     43                $priority = rand( 1, 100 );
     44                $accepted_args = rand( 1, 100 );
     45
     46                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     47                $function_key = _wp_filter_build_unique_id( $tag, $callback, $priority );
     48                unset( $hook->callbacks[ $priority ][ $function_key ] );
     49
     50                $this->assertFalse( $hook->has_filters() );
     51        }
     52}
  • tests/phpunit/tests/hooks/iterator.php

    diff --git a/tests/phpunit/tests/hooks/iterator.php b/tests/phpunit/tests/hooks/iterator.php
    index e69de29..344d31d 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the Iterator implementation of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Iterator extends WP_UnitTestCase {
     9
     10        public function test_foreach() {
     11                $callback_one = '__return_null';
     12                $callback_two = '__return_false';
     13                $hook = new WP_Hook();
     14                $tag = rand_str();
     15                $priority = rand( 1, 100 );
     16                $accepted_args = rand( 1, 100 );
     17
     18                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     19                $hook->add_filter( $tag, $callback_two, $priority + 1, $accepted_args );
     20
     21                $functions = array();
     22                $priorities = array();
     23                foreach ( $hook as $key => $callbacks ) {
     24                        $priorities[] = $key;
     25                        foreach ( $callbacks as $function_index => $the_ ) {
     26                                $functions[] = $the_['function'];
     27                        }
     28                }
     29                $this->assertEqualSets( array( $priority, $priority + 1 ), $priorities );
     30                $this->assertEqualSets( array( $callback_one, $callback_two ), $functions );
     31        }
     32}
  • tests/phpunit/tests/hooks/preinit_hooks.php

    diff --git a/tests/phpunit/tests/hooks/preinit_hooks.php b/tests/phpunit/tests/hooks/preinit_hooks.php
    index e69de29..e1d991c 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the IteratorAggregate implementation of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Preinit_Hooks extends WP_UnitTestCase {
     9
     10        public function test_array_to_hooks() {
     11                $tag1 = rand_str();
     12                $priority1 = rand( 1, 100 );
     13                $tag2 = rand_str();
     14                $priority2 = rand( 1, 100 );
     15                $filters = array(
     16                        $tag1 => array(
     17                                $priority1 => array(
     18                                        'test1' => array(
     19                                                'function' => '__return_false',
     20                                                'accepted_args' => 2,
     21                                        ),
     22                                ),
     23                        ),
     24                        $tag2 => array(
     25                                $priority2 => array(
     26                                        'test1' => array(
     27                                                'function' => '__return_null',
     28                                                'accepted_args' => 1,
     29                                        ),
     30                                ),
     31                        ),
     32                );
     33
     34                $hooks = WP_Hook::build_preinitialized_hooks( $filters );
     35
     36                $this->assertEquals( $priority1, $hooks[ $tag1 ]->has_filter( $tag1, '__return_false' ) );
     37                $this->assertEquals( $priority2, $hooks[ $tag2 ]->has_filter( $tag2, '__return_null' ) );
     38        }
     39}
  • tests/phpunit/tests/hooks/remove_all_filters.php

    diff --git a/tests/phpunit/tests/hooks/remove_all_filters.php b/tests/phpunit/tests/hooks/remove_all_filters.php
    index e69de29..57f4d83 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the remove_all_filters method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Remove_All_Filters extends WP_UnitTestCase {
     9
     10        public function test_remove_all_filters() {
     11                $callback = '__return_null';
     12                $hook = new WP_Hook();
     13                $tag = rand_str();
     14                $priority = rand( 1, 100 );
     15                $accepted_args = rand( 1, 100 );
     16
     17                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     18
     19                $hook->remove_all_filters();
     20
     21                $this->assertFalse( $hook->has_filters() );
     22        }
     23
     24        public function test_remove_all_filters_with_priority() {
     25                $callback_one = '__return_null';
     26                $callback_two = '__return_false';
     27                $hook = new WP_Hook();
     28                $tag = rand_str();
     29                $priority = rand( 1, 100 );
     30                $accepted_args = rand( 1, 100 );
     31
     32                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     33                $hook->add_filter( $tag, $callback_two, $priority + 1, $accepted_args );
     34
     35                $hook->remove_all_filters( $priority );
     36
     37                $this->assertFalse( $hook->has_filter( $tag, $callback_one ) );
     38                $this->assertTrue( $hook->has_filters() );
     39                $this->assertEquals( $priority + 1, $hook->has_filter( $tag, $callback_two ) );
     40        }
     41}
  • tests/phpunit/tests/hooks/remove_filter.php

    diff --git a/tests/phpunit/tests/hooks/remove_filter.php b/tests/phpunit/tests/hooks/remove_filter.php
    index e69de29..42a3f84 100644
    a b  
     1<?php
     2
     3/**
     4 * Test the remove_filter method of WP_Hook
     5 *
     6 * @group hooks
     7 */
     8class Tests_WP_Hook_Remove_Filter extends WP_UnitTestCase {
     9
     10        public function test_remove_filter_with_function() {
     11                $callback = '__return_null';
     12                $hook = new WP_Hook();
     13                $tag = rand_str();
     14                $priority = rand( 1, 100 );
     15                $accepted_args = rand( 1, 100 );
     16
     17                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     18                $hook->remove_filter( $tag, $callback, $priority );
     19
     20                $this->assertFalse( isset( $hook->callbacks[ $priority ] ) );
     21        }
     22
     23        public function test_remove_filter_with_object() {
     24                $a = new MockAction();
     25                $callback = array( $a, 'action' );
     26                $hook = new WP_Hook();
     27                $tag = rand_str();
     28                $priority = rand( 1, 100 );
     29                $accepted_args = rand( 1, 100 );
     30
     31                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     32                $hook->remove_filter( $tag, $callback, $priority );
     33
     34                $this->assertFalse( isset( $hook->callbacks[ $priority ] ) );
     35        }
     36
     37        public function test_remove_filter_with_static_method() {
     38                $callback = array( 'MockAction', 'action' );
     39                $hook = new WP_Hook();
     40                $tag = rand_str();
     41                $priority = rand( 1, 100 );
     42                $accepted_args = rand( 1, 100 );
     43
     44                $hook->add_filter( $tag, $callback, $priority, $accepted_args );
     45                $hook->remove_filter( $tag, $callback, $priority );
     46
     47                $this->assertFalse( isset( $hook->callbacks[ $priority ] ) );
     48        }
     49
     50        public function test_remove_filters_with_another_at_same_priority() {
     51                $callback_one = '__return_null';
     52                $callback_two = '__return_false';
     53                $hook = new WP_Hook();
     54                $tag = rand_str();
     55                $priority = rand( 1, 100 );
     56                $accepted_args = rand( 1, 100 );
     57
     58                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     59                $hook->add_filter( $tag, $callback_two, $priority, $accepted_args );
     60
     61                $hook->remove_filter( $tag, $callback_one, $priority );
     62
     63                $this->assertCount( 1, $hook->callbacks[ $priority ] );
     64        }
     65
     66        public function test_remove_filter_with_another_at_different_priority() {
     67                $callback_one = '__return_null';
     68                $callback_two = '__return_false';
     69                $hook = new WP_Hook();
     70                $tag = rand_str();
     71                $priority = rand( 1, 100 );
     72                $accepted_args = rand( 1, 100 );
     73
     74                $hook->add_filter( $tag, $callback_one, $priority, $accepted_args );
     75                $hook->add_filter( $tag, $callback_two, $priority + 1, $accepted_args );
     76
     77                $hook->remove_filter( $tag, $callback_one, $priority );
     78                $this->assertFalse( isset( $hook->callbacks[ $priority ] ) );
     79                $this->assertCount( 1, $hook->callbacks[ $priority + 1 ] );
     80        }
     81}
  • tests/phpunit/tests/post/types.php

    diff --git a/tests/phpunit/tests/post/types.php b/tests/phpunit/tests/post/types.php
    old mode 100644
    new mode 100755
    index 489266f..e7dcf84
    a b class Tests_Post_Types extends WP_UnitTestCase { 
    446446
    447447                $this->assertSame( 1, count( $wp_filter['future_foo'] ) );
    448448                $this->assertTrue( unregister_post_type( 'foo' ) );
    449                 $this->assertSame( array(), $wp_filter['future_foo'] );
     449                $this->assertArrayNotHasKey( 'future_foo', $wp_filter );
    450450        }
    451451
    452452        /**
    class Tests_Post_Types extends WP_UnitTestCase { 
    462462
    463463                $this->assertSame( 1, count( $wp_filter['add_meta_boxes_foo'] ) );
    464464                $this->assertTrue( unregister_post_type( 'foo' ) );
    465                 $this->assertSame( array(), $wp_filter['add_meta_boxes_foo'] );
     465                $this->assertArrayNotHasKey( 'add_meta_boxes_foo', $wp_filter );
    466466        }
    467467
    468468        /**
  • tests/phpunit/tests/taxonomy.php

    diff --git a/tests/phpunit/tests/taxonomy.php b/tests/phpunit/tests/taxonomy.php
    old mode 100644
    new mode 100755
    index 4fa9550..ca317bb
    a b class Tests_Taxonomy extends WP_UnitTestCase { 
    697697
    698698                $this->assertSame( 1, count( $wp_filter['wp_ajax_add-foo'] ) );
    699699                $this->assertTrue( unregister_taxonomy( 'foo' ) );
    700                 $this->assertSame( array(), $wp_filter['wp_ajax_add-foo'] );
     700                $this->assertArrayNotHasKey( 'wp_ajax_add-foo', $wp_filter );
    701701        }
    702702
    703703        /**