Make WordPress Core


Ignore:
Timestamp:
12/09/2010 07:29:21 PM (16 years ago)
Author:
scribu
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.