WordPress.org

Make WordPress Core

Ticket #17093: apply_query_filters.diff

File apply_query_filters.diff, 13.1 KB (added by kevinB, 4 years ago)

new plugin API for query filtering :add_query_filter() and apply_query_filters()

  • wp-includes/plugin.php

     
    7272} 
    7373 
    7474/** 
     75 * Hooks a function or method to a specific filter action, specifying a required context for application. 
     76 * 
     77 * @package WordPress 
     78 * @subpackage Plugin 
     79 * @global array $wp_filter Stores all of the filters added in the form of 
     80 *      wp_filter['tag']['array of priorities']['array of functions serialized']['array of ['array (functions, accepted_args)']'] 
     81 * @global array $merged_filters Tracks the tags that need to be merged for later. If the hook is added, it doesn't need to run through that process. 
     82 * 
     83 * @param string $tag The name of the filter to hook the $function_to_add to. 
     84 * @param callback $function_to_add The name of the function to be called when the filter is applied. 
     85 * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. 
     86 * @param int $accepted_args optional. The number of arguments the function accept (default 1). 
     87 * @param string $context optional. Context to require for filter application (default '').  Nullstring means filter is applied for all query contexts.  
     88 * @return boolean true 
     89 */ 
     90function add_query_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1, $context = '') { 
     91        global $wp_filter, $merged_filters; 
     92 
     93        $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); 
     94        $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args, 'context' => $context); 
     95        unset( $merged_filters[ $tag ] ); 
     96        return true; 
     97} 
     98 
     99/** 
    75100 * Check if any filter has been registered for a hook. 
    76101 * 
    77102 * @package WordPress 
     
    173198        return $value; 
    174199} 
    175200 
     201 
    176202/** 
     203 * Call the functions added to a query filter hook, applying return value validation and context check. 
     204 * 
     205 * @package WordPress 
     206 * @subpackage Plugin 
     207 * @global array $wp_filter Stores all of the filters 
     208 * @global array $merged_filters Merges the filter hooks using this function. 
     209 * @global array $wp_current_filter stores the list of current filters with the current one last 
     210 * 
     211 * @param string $tag The name of the filter hook. 
     212 * @param mixed $value The value on which the filters hooked to <tt>$tag</tt> are applied on. 
     213 * @param object $query_obj Query object which triggered filter application. 
     214 * @return mixed The filtered value after all hooked functions are applied to it. 
     215 */ 
     216function apply_query_filters($tag, $value, $query_obj) { 
     217        global $wp_filter, $merged_filters, $wp_current_filter; 
     218 
     219        $wp_current_filter[] = $tag; 
     220 
     221        // Do 'all' actions first 
     222        if ( isset($wp_filter['all']) ) { 
     223                _wp_call_all_hook( func_get_args() ); 
     224        } 
     225 
     226        if ( !isset($wp_filter[$tag]) ) { 
     227                array_pop($wp_current_filter); 
     228                return $value; 
     229        } 
     230 
     231        // Sort 
     232        if ( !isset( $merged_filters[ $tag ] ) ) { 
     233                ksort($wp_filter[$tag]); 
     234                $merged_filters[ $tag ] = true; 
     235        } 
     236 
     237        reset( $wp_filter[ $tag ] ); 
     238 
     239        $context = $query_obj->query_vars['query_context']; 
     240 
     241        do { 
     242                foreach( (array) current($wp_filter[$tag]) as $the_ ) { 
     243                        // Each valid filter hooked to this tag is applied if it was not added for a specific context or if the current context matches 
     244                        if ( !is_null($the_['function']) && ( empty($the_['context']) || ( $context == $the_['context'] ) ) ) { 
     245                                if ( (int) $the_['accepted_args'] > 1 ) 
     246                                        $_value = call_user_func($the_['function'], $value, $query_obj); 
     247                                else 
     248                                        $_value = call_user_func($the_['function'], $value); 
     249 
     250                                if ( is_null($_value) ) { 
     251                                        if ( WP_DEBUG ) { 
     252                                                trigger_error( sprintf( __('Query filter returned null value for %s hook.'), $tag ), E_USER_WARNING ); 
     253                                        } 
     254                                } else 
     255                                        $value = $_value; 
     256                        } 
     257                } 
     258 
     259        } while ( next($wp_filter[$tag]) !== false ); 
     260 
     261        array_pop( $wp_current_filter ); 
     262 
     263        return $value; 
     264} 
     265 
     266/** 
    177267 * Execute functions hooked on a specific filter hook, specifying arguments in an array. 
    178268 * 
    179269 * @see apply_filters() This function is identical, but the arguments passed to the 
  • wp-includes/query.php

     
    13691369                        , 's' 
    13701370                        , 'sentence' 
    13711371                        , 'fields' 
     1372                        , 'query_context' 
    13721373                ); 
    13731374 
    13741375                foreach ( $keys as $key ) { 
     
    21672168                } 
    21682169 
    21692170                // Allow plugins to contextually add/remove/modify the search section of the database query 
    2170                 $search = apply_filters_ref_array('posts_search', array( $search, &$this ) ); 
     2171                $search = apply_query_filters('posts_search', $search, $this); 
    21712172 
    21722173                // Taxonomies 
    21732174                if ( !$this->is_singular ) { 
     
    24832484                // Apply filters on where and join prior to paging so that any 
    24842485                // manipulations to them are reflected in the paging by day queries. 
    24852486                if ( !$q['suppress_filters'] ) { 
    2486                         $where = apply_filters_ref_array('posts_where', array( $where, &$this ) ); 
    2487                         $join = apply_filters_ref_array('posts_join', array( $join, &$this ) ); 
     2487                        $where = apply_query_filters('posts_where', $where, $this); 
     2488                        $join = apply_query_filters('posts_join', $join, $this); 
    24882489                } 
    24892490 
    24902491                // Paging 
     
    25172518                        } 
    25182519 
    25192520                        if ( !$q['suppress_filters'] ) { 
    2520                                 $cjoin = apply_filters_ref_array('comment_feed_join', array( $cjoin, &$this ) ); 
    2521                                 $cwhere = apply_filters_ref_array('comment_feed_where', array( $cwhere, &$this ) ); 
    2522                                 $cgroupby = apply_filters_ref_array('comment_feed_groupby', array( $cgroupby, &$this ) ); 
    2523                                 $corderby = apply_filters_ref_array('comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) ); 
    2524                                 $climits = apply_filters_ref_array('comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) ); 
     2521                                $cjoin = apply_query_filters('comment_feed_join', $cjoin, $this); 
     2522                                $cwhere = apply_query_filters('comment_feed_where', $cwhere, $this); 
     2523                                $cgroupby = apply_query_filters('comment_feed_groupby', $cgroupby, $this); 
     2524                                $corderby = apply_query_filters('comment_feed_orderby', 'comment_date_gmt DESC', $this); 
     2525                                $climits = apply_query_filters('comment_feed_limits', 'LIMIT ' . get_option('posts_per_rss'), $this); 
    25252526                        } 
    25262527                        $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : ''; 
    25272528                        $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : ''; 
     
    25492550                // Apply post-paging filters on where and join.  Only plugins that 
    25502551                // manipulate paging queries should use these hooks. 
    25512552                if ( !$q['suppress_filters'] ) { 
    2552                         $where          = apply_filters_ref_array( 'posts_where_paged', array( $where, &$this ) ); 
    2553                         $groupby        = apply_filters_ref_array( 'posts_groupby',             array( $groupby, &$this ) ); 
    2554                         $join           = apply_filters_ref_array( 'posts_join_paged',  array( $join, &$this ) ); 
    2555                         $orderby        = apply_filters_ref_array( 'posts_orderby',             array( $orderby, &$this ) ); 
    2556                         $distinct       = apply_filters_ref_array( 'posts_distinct',    array( $distinct, &$this ) ); 
    2557                         $limits         = apply_filters_ref_array( 'post_limits',               array( $limits, &$this ) ); 
    2558                         $fields         = apply_filters_ref_array( 'posts_fields',              array( $fields, &$this ) ); 
     2553                        $where          = apply_query_filters( 'posts_where_paged',      $where, $this ); 
     2554                        $groupby        = apply_query_filters( 'posts_groupby',          $groupby, $this ); 
     2555                        $join           = apply_query_filters( 'posts_join_paged',       $join, $this ); 
     2556                        $orderby        = apply_query_filters( 'posts_orderby',          $orderby, $this ); 
     2557                        $distinct       = apply_query_filters( 'posts_distinct',         $distinct, $this ); 
     2558                        $limits         = apply_query_filters( 'post_limits',            $limits, $this ); 
     2559                        $fields         = apply_query_filters( 'posts_fields',           $fields, $this ); 
    25592560 
    25602561                        // Filter all clauses at once, for convenience 
    2561                         $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) ); 
     2562                        $clauses = (array) apply_query_filters( 'posts_clauses', compact( $pieces ), $this ); 
    25622563                        foreach ( $pieces as $piece ) 
    25632564                                $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : ''; 
    25642565                } 
     
    25682569 
    25692570                // Filter again for the benefit of caching plugins.  Regular plugins should use the hooks above. 
    25702571                if ( !$q['suppress_filters'] ) { 
    2571                         $where          = apply_filters_ref_array( 'posts_where_request',               array( $where, &$this ) ); 
    2572                         $groupby        = apply_filters_ref_array( 'posts_groupby_request',             array( $groupby, &$this ) ); 
    2573                         $join           = apply_filters_ref_array( 'posts_join_request',                array( $join, &$this ) ); 
    2574                         $orderby        = apply_filters_ref_array( 'posts_orderby_request',             array( $orderby, &$this ) ); 
    2575                         $distinct       = apply_filters_ref_array( 'posts_distinct_request',    array( $distinct, &$this ) ); 
    2576                         $fields         = apply_filters_ref_array( 'posts_fields_request',              array( $fields, &$this ) ); 
    2577                         $limits         = apply_filters_ref_array( 'post_limits_request',               array( $limits, &$this ) ); 
     2572                        $where          = apply_query_filters( 'posts_where_request',           $where, $this ); 
     2573                        $groupby        = apply_query_filters( 'posts_groupby_request',         $groupby, $this ); 
     2574                        $join           = apply_query_filters( 'posts_join_request',            $join, $this ); 
     2575                        $orderby        = apply_query_filters( 'posts_orderby_request',         $orderby, $this ); 
     2576                        $distinct       = apply_query_filters( 'posts_distinct_request',        $distinct, $this ); 
     2577                        $fields         = apply_query_filters( 'posts_fields_request',          $fields, $this ); 
     2578                        $limits         = apply_query_filters( 'post_limits_request',           $limits, $this ); 
    25782579 
    25792580                        // Filter all clauses at once, for convenience 
    2580                         $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) ); 
     2581                        $clauses = (array) apply_query_filters( 'posts_clauses_request', compact( $pieces ), $this ); 
    25812582                        foreach ( $pieces as $piece ) 
    25822583                                $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : ''; 
    25832584                } 
     
    25932594 
    25942595                $this->request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits"; 
    25952596                if ( !$q['suppress_filters'] ) 
    2596                         $this->request = apply_filters_ref_array('posts_request', array( $this->request, &$this ) ); 
     2597                        $this->request = apply_query_filters('posts_request', $this->request, $this); 
    25972598 
    25982599                if ( 'ids' == $q['fields'] ) { 
    25992600                        $this->posts = $wpdb->get_col($this->request); 
     
    26152616 
    26162617                // Raw results filter.  Prior to status checks. 
    26172618                if ( !$q['suppress_filters'] ) 
    2618                         $this->posts = apply_filters_ref_array('posts_results', array( $this->posts, &$this ) ); 
     2619                        $this->posts = apply_query_filters('posts_results', $this->posts, $this); 
    26192620 
    26202621                if ( !empty($this->posts) && $this->is_comment_feed && $this->is_singular ) { 
    2621                         $cjoin = apply_filters_ref_array('comment_feed_join', array( '', &$this ) ); 
    2622                         $cwhere = apply_filters_ref_array('comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", &$this ) ); 
    2623                         $cgroupby = apply_filters_ref_array('comment_feed_groupby', array( '', &$this ) ); 
     2622                        $cjoin = apply_query_filters('comment_feed_join', '', $this); 
     2623                        $cwhere = apply_query_filters('comment_feed_where', "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'", $this); 
     2624                        $cgroupby = apply_query_filters('comment_feed_groupby', '', $this); 
    26242625                        $cgroupby = ( ! empty( $cgroupby ) ) ? 'GROUP BY ' . $cgroupby : ''; 
    2625                         $corderby = apply_filters_ref_array('comment_feed_orderby', array( 'comment_date_gmt DESC', &$this ) ); 
     2626                        $corderby = apply_query_filters('comment_feed_orderby', 'comment_date_gmt DESC', $this); 
    26262627                        $corderby = ( ! empty( $corderby ) ) ? 'ORDER BY ' . $corderby : ''; 
    2627                         $climits = apply_filters_ref_array('comment_feed_limits', array( 'LIMIT ' . get_option('posts_per_rss'), &$this ) ); 
     2628                        $climits = apply_query_filters('comment_feed_limits', 'LIMIT ' . get_option('posts_per_rss'), $this); 
    26282629                        $comments_request = "SELECT $wpdb->comments.* FROM $wpdb->comments $cjoin $cwhere $cgroupby $corderby $climits"; 
    26292630                        $this->comments = $wpdb->get_results($comments_request); 
    26302631                        $this->comment_count = count($this->comments); 
    26312632                } 
    26322633 
    26332634                if ( !$q['no_found_rows'] && !empty($limits) ) { 
    2634                         $found_posts_query = apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) ); 
     2635                        $found_posts_query = apply_query_filters( 'found_posts_query', 'SELECT FOUND_ROWS()', $this); 
    26352636                        $this->found_posts = $wpdb->get_var( $found_posts_query ); 
    2636                         $this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) ); 
     2637                        $this->found_posts = apply_query_filters( 'found_posts', $this->found_posts, $this); 
    26372638                        $this->max_num_pages = ceil($this->found_posts / $q['posts_per_page']); 
    26382639                } 
    26392640 
     
    26662667                        } 
    26672668 
    26682669                        if ( $this->is_preview && current_user_can( $edit_cap, $this->posts[0]->ID ) ) 
    2669                                 $this->posts[0] = apply_filters_ref_array('the_preview', array( $this->posts[0], &$this )); 
     2670                                $this->posts[0] = apply_query_filters('the_preview', $this->posts[0], $this); 
    26702671                } 
    26712672 
    26722673                // Put sticky posts at the top of the posts array 
     
    27202721                } 
    27212722 
    27222723                if ( !$q['suppress_filters'] ) 
    2723                         $this->posts = apply_filters_ref_array('the_posts', array( $this->posts, &$this ) ); 
     2724                        $this->posts = apply_query_filters('the_posts', $this->posts, $this); 
    27242725 
    27252726                $this->post_count = count($this->posts); 
    27262727