WordPress.org

Make WordPress Core

Changeset 16849


Ignore:
Timestamp:
12/09/10 19:29:21 (6 years ago)
Author:
scribu
Message:

Introduce WP_Tax_Query. Fix canonical redirects in the process. See #15752

Location:
trunk/wp-includes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/canonical.php

    r16797 r16849  
    147147 
    148148            $term_count = 0; 
    149             foreach ( $wp_query->tax_query as $tax_query ) 
     149            foreach ( $wp_query->tax_query->queries as $tax_query ) 
    150150                $term_count += count( $tax_query['terms'] ); 
    151151 
  • trunk/wp-includes/query.php

    r16844 r16849  
    715715     * @since 3.1.0 
    716716     * @access public 
    717      * @var array 
    718      */ 
    719     var $tax_query = array(); 
     717     * @var object WP_Tax_Query 
     718     */ 
     719    var $tax_query; 
    720720 
    721721    /** 
     
    15851585        } 
    15861586 
    1587         _set_tax_query_defaults( $tax_query ); 
    1588  
    1589         foreach ( $tax_query as $query ) { 
    1590             if ( ! is_array( $query ) ) 
    1591                 continue; 
    1592  
     1587        $tax_query_obj = new WP_Tax_Query( $tax_query ); 
     1588 
     1589        foreach ( $tax_query_obj->queries as $query ) { 
    15931590            if ( 'IN' == $query['operator'] ) { 
    15941591                switch ( $query['taxonomy'] ) { 
     
    16051602        } 
    16061603 
    1607         return $tax_query; 
     1604        return $tax_query_obj; 
    16081605    } 
    16091606 
     
    19431940            $this->tax_query = $this->parse_tax_query( $q ); 
    19441941 
    1945             $clauses = call_user_func_array( 'get_tax_sql', array( $this->tax_query, $wpdb->posts, 'ID', &$this) ); 
     1942            $clauses = $this->tax_query->get_sql( $wpdb->posts, 'ID' ); 
    19461943 
    19471944            $join .= $clauses['join']; 
     
    19581955 
    19591956            // Back-compat 
    1960             $tax_query_in = wp_list_filter( $this->tax_query, array( 'operator' => 'IN' ) ); 
     1957            $tax_query_in = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'IN' ) ); 
    19611958            if ( !empty( $tax_query_in ) ) { 
    19621959                if ( !isset( $q['taxonomy'] ) ) { 
     
    26582655        $this->queried_object_id = 0; 
    26592656 
    2660         $tax_query_in = wp_list_filter( $this->tax_query, array( 'operator' => 'IN' ) ); 
     2657        $tax_query_in = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'IN' ) ); 
    26612658        if ( !empty( $tax_query_in ) ) { 
    26622659            $query = reset( $tax_query_in ); 
  • trunk/wp-includes/taxonomy.php

    r16845 r16849  
    528528 */ 
    529529function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) { 
    530     global $wpdb; 
    531  
    532     $join = ''; 
    533     $where = array(); 
    534     $i = 0; 
    535  
    536     _set_tax_query_defaults( $tax_query ); 
    537  
    538     if ( strtoupper( $tax_query['relation'] ) == 'OR' ) { 
    539         $relation = 'OR'; 
    540     } else { 
    541         $relation = 'AND'; 
    542     } 
    543  
    544     foreach ( $tax_query as $query ) { 
    545         if ( ! is_array( $query ) ) 
    546             continue; 
    547  
    548         extract( $query ); 
    549  
    550         if ( ! taxonomy_exists( $taxonomy ) ) 
    551             return array( 'join' => '', 'where' => ' AND 0 = 1'); 
    552  
    553         $terms = array_unique( (array) $terms ); 
    554  
    555         if ( empty( $terms ) ) 
    556             continue; 
    557  
    558         if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) { 
    559             _transform_terms( $terms, $taxonomy, $field, 'term_id' ); 
    560  
    561             $children = array(); 
    562             foreach ( $terms as $term ) { 
    563                 $children = array_merge( $children, get_term_children( $term, $taxonomy ) ); 
    564                 $children[] = $term; 
    565             } 
    566             $terms = $children; 
    567  
    568             _transform_terms( $terms, $taxonomy, 'term_id', 'term_taxonomy_id' ); 
    569         } 
    570         else { 
    571             _transform_terms( $terms, $taxonomy, $field, 'term_taxonomy_id' ); 
    572         } 
    573  
    574         if ( 'IN' == $operator ) { 
    575  
    576             if ( empty( $terms ) ) { 
    577                 if ( 'OR' == $relation ) 
    578                     continue; 
    579                 else 
    580                     return array( 'join' => '', 'where' => ' AND 0 = 1' ); 
    581             } 
    582  
    583             $terms = implode( ',', $terms ); 
    584  
    585             $alias = $i ? 'tt' . $i : $wpdb->term_relationships; 
    586  
    587             $join .= " INNER JOIN $wpdb->term_relationships"; 
    588             $join .= $i ? " AS $alias" : ''; 
    589             $join .= " ON ($primary_table.$primary_id_column = $alias.object_id)"; 
    590  
    591             $where[] = "$alias.term_taxonomy_id $operator ($terms)"; 
    592         } 
    593         elseif ( 'NOT IN' == $operator ) { 
     530    $tax_query_obj = new WP_Tax_Query( $tax_query ); 
     531    return $tax_query_obj->get_sql( $primary_table, $primary_id_column ); 
     532} 
     533 
     534class WP_Tax_Query { 
     535    var $relation = ''; 
     536    var $queries = array(); 
     537 
     538    function __construct( &$tax_query ) { 
     539        if ( isset( $tax_query['relation'] ) && strtoupper( $tax_query['relation'] ) == 'OR' ) { 
     540            $this->relation = 'OR'; 
     541        } else { 
     542            $this->relation = 'AND'; 
     543        } 
     544 
     545        $defaults = array( 
     546            'taxonomy' => '', 
     547            'terms' => array(), 
     548            'include_children' => true, 
     549            'field' => 'term_id', 
     550            'operator' => 'IN', 
     551        ); 
     552 
     553        foreach ( $tax_query as $query ) { 
     554            if ( ! is_array( $query ) ) 
     555                continue; 
     556 
     557            $query = array_merge( $defaults, $query ); 
     558 
     559            $query['terms'] = (array) $query['terms']; 
     560             
     561            $this->queries[] = $query; 
     562        } 
     563    } 
     564 
     565    function get_sql( $primary_table, $primary_id_column ) { 
     566        global $wpdb; 
     567 
     568        $join = ''; 
     569        $where = array(); 
     570        $i = 0; 
     571 
     572        foreach ( $this->queries as $query ) { 
     573            extract( $query ); 
     574 
     575            if ( ! taxonomy_exists( $taxonomy ) ) 
     576                return array( 'join' => '', 'where' => ' AND 0 = 1'); 
     577 
     578            $terms = array_unique( (array) $terms ); 
    594579 
    595580            if ( empty( $terms ) ) 
    596581                continue; 
    597582 
    598             $terms = implode( ',', $terms ); 
    599  
    600             $where[] = "$primary_table.$primary_id_column NOT IN ( 
    601                 SELECT object_id 
    602                 FROM $wpdb->term_relationships 
    603                 WHERE term_taxonomy_id IN ($terms) 
    604             )"; 
    605         } 
    606  
    607         $i++; 
    608     } 
    609  
    610     if ( !empty( $where ) ) 
    611         $where = ' AND ( ' . implode( " $relation ", $where ) . ' )'; 
    612     else 
    613         $where = ''; 
    614  
    615     return compact( 'join', 'where' ); 
    616 } 
    617  
    618 function _set_tax_query_defaults( &$tax_query ) { 
    619     if ( ! isset( $tax_query['relation'] ) ) 
    620         $tax_query['relation'] = 'AND'; 
    621  
    622     $defaults = array( 
    623         'taxonomy' => '', 
    624         'terms' => array(), 
    625         'include_children' => true, 
    626         'field' => 'term_id', 
    627         'operator' => 'IN', 
    628     ); 
    629  
    630     foreach ( $tax_query as $i => $query ) { 
    631         if ( ! is_array( $query ) ) 
    632             continue; 
    633  
    634         $tax_query[$i] = array_merge( $defaults, $query ); 
    635  
    636         $tax_query[$i]['terms'] = (array) $tax_query[$i]['terms']; 
    637     } 
    638 } 
    639  
    640 function _transform_terms( &$terms, $taxonomy, $field, $resulting_field ) { 
    641     global $wpdb; 
    642  
    643     if ( empty( $terms ) ) 
    644         return; 
    645  
    646     if ( $field == $resulting_field ) 
    647         return; 
    648  
    649     $resulting_field = esc_sql( $resulting_field ); 
    650  
    651     switch ( $field ) { 
    652         case 'slug': 
    653         case 'name': 
    654             $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $terms ) ) . "'"; 
    655             $terms = $wpdb->get_col( " 
    656                 SELECT $wpdb->term_taxonomy.$resulting_field 
    657                 FROM $wpdb->term_taxonomy 
    658                 INNER JOIN $wpdb->terms USING (term_id) 
    659                 WHERE taxonomy = '$taxonomy' 
    660                 AND $wpdb->terms.$field IN ($terms) 
    661             " ); 
    662             break; 
    663  
    664         default: 
    665             $terms = implode( ',', array_map( 'intval', $terms ) ); 
    666             $terms = $wpdb->get_col( " 
    667                 SELECT $resulting_field 
    668                 FROM $wpdb->term_taxonomy 
    669                 WHERE taxonomy = '$taxonomy' 
    670                 AND term_id IN ($terms) 
    671             " ); 
     583            if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) { 
     584                $this->_transform_terms( $terms, $taxonomy, $field, 'term_id' ); 
     585 
     586                $children = array(); 
     587                foreach ( $terms as $term ) { 
     588                    $children = array_merge( $children, get_term_children( $term, $taxonomy ) ); 
     589                    $children[] = $term; 
     590                } 
     591                $terms = $children; 
     592 
     593                $this->_transform_terms( $terms, $taxonomy, 'term_id', 'term_taxonomy_id' ); 
     594            } 
     595            else { 
     596                $this->_transform_terms( $terms, $taxonomy, $field, 'term_taxonomy_id' ); 
     597            } 
     598 
     599            if ( 'IN' == $operator ) { 
     600 
     601                if ( empty( $terms ) ) { 
     602                    if ( 'OR' == $relation ) 
     603                        continue; 
     604                    else 
     605                        return array( 'join' => '', 'where' => ' AND 0 = 1' ); 
     606                } 
     607 
     608                $terms = implode( ',', $terms ); 
     609 
     610                $alias = $i ? 'tt' . $i : $wpdb->term_relationships; 
     611 
     612                $join .= " INNER JOIN $wpdb->term_relationships"; 
     613                $join .= $i ? " AS $alias" : ''; 
     614                $join .= " ON ($primary_table.$primary_id_column = $alias.object_id)"; 
     615 
     616                $where[] = "$alias.term_taxonomy_id $operator ($terms)"; 
     617            } 
     618            elseif ( 'NOT IN' == $operator ) { 
     619 
     620                if ( empty( $terms ) ) 
     621                    continue; 
     622 
     623                $terms = implode( ',', $terms ); 
     624 
     625                $where[] = "$primary_table.$primary_id_column NOT IN ( 
     626                    SELECT object_id 
     627                    FROM $wpdb->term_relationships 
     628                    WHERE term_taxonomy_id IN ($terms) 
     629                )"; 
     630            } 
     631 
     632            $i++; 
     633        } 
     634 
     635        if ( !empty( $where ) ) 
     636            $where = ' AND ( ' . implode( " $relation ", $where ) . ' )'; 
     637        else 
     638            $where = ''; 
     639 
     640        return compact( 'join', 'where' ); 
     641    } 
     642 
     643    function _transform_terms( &$terms, $taxonomy, $field, $resulting_field ) { 
     644        global $wpdb; 
     645 
     646        if ( empty( $terms ) ) 
     647            return; 
     648 
     649        if ( $field == $resulting_field ) 
     650            return; 
     651 
     652        $resulting_field = esc_sql( $resulting_field ); 
     653 
     654        switch ( $field ) { 
     655            case 'slug': 
     656            case 'name': 
     657                $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $terms ) ) . "'"; 
     658                $terms = $wpdb->get_col( " 
     659                    SELECT $wpdb->term_taxonomy.$resulting_field 
     660                    FROM $wpdb->term_taxonomy 
     661                    INNER JOIN $wpdb->terms USING (term_id) 
     662                    WHERE taxonomy = '$taxonomy' 
     663                    AND $wpdb->terms.$field IN ($terms) 
     664                " ); 
     665                break; 
     666 
     667            default: 
     668                $terms = implode( ',', array_map( 'intval', $terms ) ); 
     669                $terms = $wpdb->get_col( " 
     670                    SELECT $resulting_field 
     671                    FROM $wpdb->term_taxonomy 
     672                    WHERE taxonomy = '$taxonomy' 
     673                    AND term_id IN ($terms) 
     674                " ); 
     675        } 
    672676    } 
    673677} 
Note: See TracChangeset for help on using the changeset viewer.