Make WordPress Core

Ticket #14789: 14789.4.patch

File 14789.4.patch, 15.4 KB (added by hakre, 15 years ago)

Touched other functions as well.

  • wp-includes/plugin.php

     
    6565function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    6666        global $wp_filter, $merged_filters;
    6767
    68         $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
    69         $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
     68        $accepted_args = max(0, (int) $accepted_args );
     69        $unique_id     = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
     70        $wp_filter[$tag][$priority][$unique_id] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
    7071        unset( $merged_filters[ $tag ] );
    7172        return true;
    7273}
     
    8586 */
    8687function has_filter($tag, $function_to_check = false) {
    8788        global $wp_filter;
    88 
    89         $has = !empty($wp_filter[$tag]);
    90         if ( false === $function_to_check || false == $has )
    91                 return $has;
    92 
    93         if ( !$idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )
     89       
     90        if ( empty( $wp_filter[$tag] ) )
    9491                return false;
     92       
     93        if ( false === $function_to_check )
     94                return true;
     95       
     96        if ( !( $unique_id = _wp_filter_build_unique_id( $tag, $function_to_check, false ) ) )
     97                return false;
    9598
    96         foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {
    97                 if ( isset($wp_filter[$tag][$priority][$idx]) )
     99        foreach ( array_keys( $wp_filter[$tag] ) as $priority )
     100                if ( isset( $wp_filter[$tag][$priority][$unique_id] ) )
    98101                        return $priority;
    99         }
    100102
    101103        return false;
    102104}
     
    132134 * @return mixed The filtered value after all hooked functions are applied to it.
    133135 */
    134136function apply_filters($tag, $value) {
    135         global $wp_filter, $merged_filters, $wp_current_filter;
    136 
    137         $args = array();
    138         $wp_current_filter[] = $tag;
    139 
    140         // Do 'all' actions first
    141         if ( isset($wp_filter['all']) ) {
    142                 $args = func_get_args();
    143                 _wp_call_all_hook($args);
    144         }
    145 
    146         if ( !isset($wp_filter[$tag]) ) {
    147                 array_pop($wp_current_filter);
    148                 return $value;
    149         }
    150 
    151         // Sort
    152         if ( !isset( $merged_filters[ $tag ] ) ) {
    153                 ksort($wp_filter[$tag]);
    154                 $merged_filters[ $tag ] = true;
    155         }
    156 
    157         reset( $wp_filter[ $tag ] );
    158 
    159         if ( empty($args) )
    160                 $args = func_get_args();
    161 
    162         do {
    163                 foreach( (array) current($wp_filter[$tag]) as $the_ )
    164                         if ( !is_null($the_['function']) ){
    165                                 $args[1] = $value;
    166                                 $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
    167                         }
    168 
    169         } while ( next($wp_filter[$tag]) !== false );
    170 
    171         array_pop( $wp_current_filter );
    172 
    173         return $value;
     137        $args = func_get_args();
     138        $tag  = array_shift( $args );
     139        return _wp_call_hook(true, $tag, $args);
    174140}
    175141
    176142/**
     
    191157 * @return mixed The filtered value after all hooked functions are applied to it.
    192158 */
    193159function apply_filters_ref_array($tag, $args) {
    194         global $wp_filter, $merged_filters, $wp_current_filter;
    195 
    196         $wp_current_filter[] = $tag;
    197 
    198         // Do 'all' actions first
    199         if ( isset($wp_filter['all']) ) {
    200                 $all_args = func_get_args();
    201                 _wp_call_all_hook($all_args);
    202         }
    203 
    204         if ( !isset($wp_filter[$tag]) ) {
    205                 array_pop($wp_current_filter);
    206                 return $args[0];
    207         }
    208 
    209         // Sort
    210         if ( !isset( $merged_filters[ $tag ] ) ) {
    211                 ksort($wp_filter[$tag]);
    212                 $merged_filters[ $tag ] = true;
    213         }
    214 
    215         reset( $wp_filter[ $tag ] );
    216 
    217         do {
    218                 foreach( (array) current($wp_filter[$tag]) as $the_ )
    219                         if ( !is_null($the_['function']) )
    220                                 $args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    221 
    222         } while ( next($wp_filter[$tag]) !== false );
    223 
    224         array_pop( $wp_current_filter );
    225 
    226         return $args[0];
     160        return _wp_call_hook( true, $tag, $args );
    227161}
    228162
    229163/**
     
    245179 * @param callback $function_to_remove The name of the function which should be removed.
    246180 * @param int $priority optional. The priority of the function (default: 10).
    247181 * @param int $accepted_args optional. The number of arguments the function accpets (default: 1).
    248  * @return boolean Whether the function existed before it was removed.
     182 * @return boolean True if there was a function to remove, False if not.
    249183 */
    250184function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1) {
    251         $function_to_remove = _wp_filter_build_unique_id($tag, $function_to_remove, $priority);
     185        global $wp_filter, $merged_filters;
     186       
     187        $unique_id = _wp_filter_build_unique_id($tag, $function_to_remove, $priority);
    252188
    253         $r = isset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
     189        if ( false === isset( $wp_filter[$tag][$priority][$unique_id] ) )
     190                return false;
    254191
    255         if ( true === $r) {
    256                 unset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
    257                 if ( empty($GLOBALS['wp_filter'][$tag][$priority]) )
    258                         unset($GLOBALS['wp_filter'][$tag][$priority]);
    259                 unset($GLOBALS['merged_filters'][$tag]);
    260         }
     192        unset( $merged_filters[$tag] );
     193        unset( $wp_filter[$tag][$priority][$unique_id] );
     194               
     195        if ( empty( $wp_filter[$tag][$priority] ) )
     196                unset( $wp_filter[$tag][$priority] );
    261197
    262         return $r;
     198        return true;
    263199}
    264200
    265201/**
     
    268204 * @since 2.7
    269205 *
    270206 * @param string $tag The filter to remove hooks from.
    271  * @param int $priority The priority number to remove.
    272  * @return bool True when finished.
     207 * @param int $priority (optional) The priority to remove.
     208 * @return bool True
    273209 */
    274210function remove_all_filters($tag, $priority = false) {
    275211        global $wp_filter, $merged_filters;
    276 
    277         if( isset($wp_filter[$tag]) ) {
    278                 if( false !== $priority && isset($wp_filter[$tag][$priority]) )
    279                         unset($wp_filter[$tag][$priority]);
    280                 else
    281                         unset($wp_filter[$tag]);
     212       
     213        if ( !isset( $wp_filter[$tag] ) )
     214                return true;
     215       
     216        if ( false === $priority ) {
     217                unset( $wp_filter[$tag] );
     218        } else {
     219                unset( $wp_filter[$tag][$priority] );
    282220        }
    283221
    284         if( isset($merged_filters[$tag]) )
    285                 unset($merged_filters[$tag]);
     222        unset( $merged_filters[$tag] );
    286223
    287224        return true;
    288225}
     
    350287 * @return null Will return null if $tag does not exist in $wp_filter array
    351288 */
    352289function do_action($tag, $arg = '') {
    353         global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
    354 
    355         if ( ! isset($wp_actions) )
    356                 $wp_actions = array();
    357 
    358         if ( ! isset($wp_actions[$tag]) )
    359                 $wp_actions[$tag] = 1;
    360         else
    361                 ++$wp_actions[$tag];
    362 
    363         $wp_current_filter[] = $tag;
    364 
    365         // Do 'all' actions first
    366         if ( isset($wp_filter['all']) ) {
    367                 $all_args = func_get_args();
    368                 _wp_call_all_hook($all_args);
    369         }
    370 
    371         if ( !isset($wp_filter[$tag]) ) {
    372                 array_pop($wp_current_filter);
    373                 return;
    374         }
    375 
    376         $args = array();
    377         if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
    378                 $args[] =& $arg[0];
    379         else
    380                 $args[] = $arg;
    381         for ( $a = 2; $a < func_num_args(); $a++ )
    382                 $args[] = func_get_arg($a);
    383 
    384         // Sort
    385         if ( !isset( $merged_filters[ $tag ] ) ) {
    386                 ksort($wp_filter[$tag]);
    387                 $merged_filters[ $tag ] = true;
    388         }
    389 
    390         reset( $wp_filter[ $tag ] );
    391 
    392         do {
    393                 foreach ( (array) current($wp_filter[$tag]) as $the_ )
    394                         if ( !is_null($the_['function']) )
    395                                 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    396 
    397         } while ( next($wp_filter[$tag]) !== false );
    398 
    399         array_pop($wp_current_filter);
     290        $args = func_get_args();
     291        $tag  = array_shift( $args );
     292        _wp_call_hook(false, $tag, $args);
    400293}
    401294
    402295/**
     
    436329 * @return null Will return null if $tag does not exist in $wp_filter array
    437330 */
    438331function do_action_ref_array($tag, $args) {
    439         global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
    440 
    441         if ( ! isset($wp_actions) )
    442                 $wp_actions = array();
    443 
    444         if ( ! isset($wp_actions[$tag]) )
    445                 $wp_actions[$tag] = 1;
    446         else
    447                 ++$wp_actions[$tag];
    448 
    449         $wp_current_filter[] = $tag;
    450 
    451         // Do 'all' actions first
    452         if ( isset($wp_filter['all']) ) {
    453                 $all_args = func_get_args();
    454                 _wp_call_all_hook($all_args);
    455         }
    456 
    457         if ( !isset($wp_filter[$tag]) ) {
    458                 array_pop($wp_current_filter);
    459                 return;
    460         }
    461 
    462         // Sort
    463         if ( !isset( $merged_filters[ $tag ] ) ) {
    464                 ksort($wp_filter[$tag]);
    465                 $merged_filters[ $tag ] = true;
    466         }
    467 
    468         reset( $wp_filter[ $tag ] );
    469 
    470         do {
    471                 foreach( (array) current($wp_filter[$tag]) as $the_ )
    472                         if ( !is_null($the_['function']) )
    473                                 call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
    474 
    475         } while ( next($wp_filter[$tag]) !== false );
    476 
    477         array_pop($wp_current_filter);
     332        _wp_call_hook( false, $tag, $args );
    478333}
    479334
    480335/**
     
    490345 * @return int|boolean Optionally returns the priority on that hook for the specified function.
    491346 */
    492347function has_action($tag, $function_to_check = false) {
    493         return has_filter($tag, $function_to_check);
     348        return has_filter( $tag, $function_to_check );
    494349}
    495350
    496351/**
     
    511366 * @return boolean Whether the function is removed.
    512367 */
    513368function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args = 1) {
    514         return remove_filter($tag, $function_to_remove, $priority, $accepted_args);
     369        return remove_filter( $tag, $function_to_remove, $priority, $accepted_args );
    515370}
    516371
    517372/**
     
    524379 * @return bool True when finished.
    525380 */
    526381function remove_all_actions($tag, $priority = false) {
    527         return remove_all_filters($tag, $priority);
     382        return remove_all_filters( $tag, $priority );
    528383}
    529384
    530385//
     
    547402 * @uses WP_PLUGIN_DIR
    548403 */
    549404function plugin_basename($file) {
    550         $file = str_replace('\\','/',$file); // sanitize for Win32 installs
    551         $file = preg_replace('|/+|','/', $file); // remove any duplicate slash
    552         $plugin_dir = str_replace('\\','/',WP_PLUGIN_DIR); // sanitize for Win32 installs
    553         $plugin_dir = preg_replace('|/+|','/', $plugin_dir); // remove any duplicate slash
    554         $mu_plugin_dir = str_replace('\\','/',WPMU_PLUGIN_DIR); // sanitize for Win32 installs
    555         $mu_plugin_dir = preg_replace('|/+|','/', $mu_plugin_dir); // remove any duplicate slash
    556         $file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#','',$file); // get relative path from plugins dir
    557         $file = trim($file, '/');
     405        $subject = array ( $file, WP_PLUGIN_DIR, WPMU_PLUGIN_DIR );
     406       
     407        $subject = str_replace(  '\\',   '/', $subject ); // sanitize for Win32 installs
     408        $subject = preg_replace( '|/+|', '/', $subject ); // remove any duplicate slash
     409       
     410        $file    = array_shift($subject);
     411       
     412        // get relative path from plugins dir
     413        $subject = array_map( 'preg_quote', $subject, array ( '#', '#' ) );
     414        list ( $plugin_dir, $mu_plugin_dir ) = $subject;
     415        $pattern = sprintf( '#^(%s|%s)/#', $plugin_dir, $mu_plugin_dir );
     416        $file    = preg_replace( $pattern, '', $file );
     417       
     418        $file    = trim( $file, '/' );
     419       
    558420        return $file;
    559421}
    560422
     
    604466 * @param callback $function the function hooked to the 'activate_PLUGIN' action.
    605467 */
    606468function register_activation_hook($file, $function) {
    607         $file = plugin_basename($file);
    608         add_action('activate_' . $file, $function);
     469        $file = plugin_basename( $file );
     470        add_action( 'activate_' . $file, $function );
    609471}
    610472
    611473/**
     
    629491 * @param callback $function the function hooked to the 'activate_PLUGIN' action.
    630492 */
    631493function register_deactivation_hook($file, $function) {
    632         $file = plugin_basename($file);
    633         add_action('deactivate_' . $file, $function);
     494        $file = plugin_basename( $file );
     495        add_action( 'deactivate_' . $file, $function );
    634496}
    635497
    636498/**
     
    662524        // The option should not be autoloaded, because it is not needed in most
    663525        // cases. Emphasis should be put on using the 'uninstall.php' way of
    664526        // uninstalling the plugin.
    665         $uninstallable_plugins = (array) get_option('uninstall_plugins');
    666         $uninstallable_plugins[plugin_basename($file)] = $callback;
    667         update_option('uninstall_plugins', $uninstallable_plugins);
     527        $file                         = plugin_basename($file);
     528        $uninstallable_plugins        = (array) get_option( 'uninstall_plugins' );
     529        $uninstallable_plugins[$file] = $callback;
     530        update_option( 'uninstall_plugins', $uninstallable_plugins );
    668531}
    669532
    670533/**
     
    688551 * @param array $args The collected parameters from the hook that was called.
    689552 * @param string $hook Optional. The hook name that was used to call the 'all' hook.
    690553 */
    691 function _wp_call_all_hook($args) {
     554function _wp_call_all_hook( $args ) {
    692555        global $wp_filter;
     556       
     557        foreach( $wp_filter['all'] as $priority )
     558                foreach( $priority as $the_ )
     559                        null !== $the_['function']
     560                        && call_user_func_array( $the_['function'], $args );
     561}
    693562
    694         reset( $wp_filter['all'] );
    695         do {
    696                 foreach( (array) current($wp_filter['all']) as $the_ )
    697                         if ( !is_null($the_['function']) )
    698                                 call_user_func_array($the_['function'], $args);
     563/**
     564 * Calls a hook
     565 *
     566 * @since 3.1
     567 * @access private
     568 * @param bool   $filter True: apply_filter, False: do_action
     569 * @param string $tag The name of the filter hook.
     570 * @param array  $args The arguments supplied to the functions hooked on <tt>$tag</tt>
     571 * @return mixed first element of $args, filtered if applicable
     572 */
     573function _wp_call_hook($filter, $tag, $args) {
     574        global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
     575       
     576        // Count actions (not filters)
     577        $filter || isset( $wp_actions[$tag] ) && $wp_actions[$tag]++ || $wp_actions[$tag] = 1;
    699578
    700         } while ( next($wp_filter['all']) !== false );
     579        // Add hook to stack
     580        $wp_current_filter[] = $tag;
     581
     582        // Do 'all' actions
     583        isset( $wp_filter['all'] ) && _wp_call_all_hook( array_merge( array($tag), $args ) );
     584
     585        if ( isset( $wp_filter[$tag] ) ) {
     586                // Sort
     587                isset( $merged_filters[$tag] ) || $merged_filters[$tag] = ksort( $wp_filter[$tag] );
     588
     589                for ( $prio = reset( $wp_filter[$tag] ); false !== $prio ; $prio = next( $wp_filter[$tag] ) ) {
     590                        foreach( $prio as $the_ ) {
     591                                if ( null === $the_['function'] )
     592                                        continue;
     593
     594                                $callback  = $the_['function'];
     595                                $parameter = array_slice( $args, 0, $the_['accepted_args'] );
     596
     597                                $filter
     598                                ? $args[0] = call_user_func_array( $callback, $parameter)
     599                                : call_user_func_array( $callback, $parameter);
     600                        }
     601                }
     602        }
     603
     604        // Remove hook from stack
     605        array_pop( $wp_current_filter );
     606        return isset( $args[0] ) ? $args[0] : null;
    701607}
    702608
    703609/**
     
    734640        global $wp_filter;
    735641        static $filter_id_count = 0;
    736642
    737         if ( is_string($function) )
     643        if ( is_string( $function ) )
    738644                return $function;
    739645
    740         if ( is_object($function) ) {
     646        if ( is_object( $function ) ) {
    741647                // Closures are currently implemented as objects
    742648                $function = array( $function, '' );
    743649        } else {
    744650                $function = (array) $function;
    745651        }
    746652
    747         if (is_object($function[0]) ) {
    748                 // Object Class Calling
    749                 if ( function_exists('spl_object_hash') ) {
    750                         return spl_object_hash($function[0]) . $function[1];
     653        if ( is_object( $function[0] ) ) {
     654                // Object Instance Calling
     655                if ( function_exists( 'spl_object_hash' ) ) {
     656                        return spl_object_hash( $function[0] ) . $function[1];
    751657                } else {
    752                         $obj_idx = get_class($function[0]).$function[1];
    753                         if ( !isset($function[0]->wp_filter_id) ) {
     658                        $obj_idx = get_class( $function[0] ) . $function[1];
     659                        if ( !isset( $function[0]->wp_filter_id ) ) {
    754660                                if ( false === $priority )
    755661                                        return false;
    756                                 $obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count;
     662                                $obj_idx .= isset( $wp_filter[$tag][$priority] ) ? count( (array) $wp_filter[$tag][$priority] ) : $filter_id_count;
    757663                                $function[0]->wp_filter_id = $filter_id_count;
    758664                                ++$filter_id_count;
    759665                        } else {
     
    762668
    763669                        return $obj_idx;
    764670                }
    765         } else if ( is_string($function[0]) ) {
    766                 // Static Calling
     671        } else if ( is_string( $function[0] ) ) {
     672                // Object Static Calling
    767673                return $function[0].$function[1];
    768674        }
    769675}