Make WordPress Core


Ignore:
Timestamp:
10/14/2014 04:02:41 AM (9 years ago)
Author:
boonebgorges
Message:

Introduce support for nested queries in WP_Tax_Query.

Previously, tax query arguments could be joined by a single AND or OR relation.
Now, these queries can be arbitrarily nested, allowing clauses to be linked
together with multiple relations.

In a few places, WP_Query runs through a list of clauses in a tax_query in order
to set certain query vars for backward compatibility. The necessary changes have
been made to WP_Query to support this feature with the new complex structure of
tax_query. Unit tests are included for these backward compatibility fixes.

Unit tests for the new nesting syntax are included.

Props boonebgorges.
Fixes #29718. See #29738.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/query.php

    r29855 r29891  
    16731673
    16741674            foreach ( $this->tax_query->queries as $tax_query ) {
    1675                 if ( 'NOT IN' != $tax_query['operator'] ) {
     1675                if ( ! is_array( $tax_query ) ) {
     1676                    continue;
     1677                }
     1678
     1679                if ( isset( $tax_query['operator'] ) && 'NOT IN' != $tax_query['operator'] ) {
    16761680                    switch ( $tax_query['taxonomy'] ) {
    16771681                        case 'category':
     
    26882692                // Do a fully inclusive search for currently registered post types of queried taxonomies
    26892693                $post_type = array();
    2690                 $taxonomies = wp_list_pluck( $this->tax_query->queries, 'taxonomy' );
     2694                $taxonomies = array_keys( $this->tax_query->queried_terms );
    26912695                foreach ( get_post_types( array( 'exclude_from_search' => false ) ) as $pt ) {
    26922696                    $object_taxonomies = $pt === 'attachment' ? get_taxonomies_for_attachments() : get_object_taxonomies( $pt );
     
    27052709        }
    27062710
    2707         // Back-compat
    2708         if ( !empty($this->tax_query->queries) ) {
    2709             $tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );
    2710             if ( !empty( $tax_query_in_and ) ) {
    2711                 if ( !isset( $q['taxonomy'] ) ) {
    2712                     foreach ( $tax_query_in_and as $a_tax_query ) {
    2713                         if ( !in_array( $a_tax_query['taxonomy'], array( 'category', 'post_tag' ) ) ) {
    2714                             $q['taxonomy'] = $a_tax_query['taxonomy'];
    2715                             if ( 'slug' == $a_tax_query['field'] )
    2716                                 $q['term'] = $a_tax_query['terms'][0];
    2717                             else
    2718                                 $q['term_id'] = $a_tax_query['terms'][0];
    2719 
    2720                             break;
     2711        /*
     2712         * Ensure that 'taxonomy', 'term', 'term_id', 'cat', and
     2713         * 'category_name' vars are set for backward compatibility.
     2714         */
     2715        if ( ! empty( $this->tax_query->queried_terms ) ) {
     2716
     2717            /*
     2718             * Set 'taxonomy', 'term', and 'term_id' to the
     2719             * first taxonomy other than 'post_tag' or 'category'.
     2720             */
     2721            if ( ! isset( $q['taxonomy'] ) ) {
     2722                foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
     2723                    if ( empty( $queried_items['terms'][0] ) ) {
     2724                        continue;
     2725                    }
     2726
     2727                    if ( ! in_array( $queried_taxonomy, array( 'category', 'post_tag' ) ) ) {
     2728                        $q['taxonomy'] = $queried_taxonomy;
     2729
     2730                        if ( 'slug' === $queried_items['field'] ) {
     2731                            $q['term'] = $queried_items['terms'][0];
     2732                        } else {
     2733                            $q['term_id'] = $queried_items['terms'][0];
    27212734                        }
    27222735                    }
    27232736                }
    2724 
    2725                 $cat_query = wp_list_filter( $tax_query_in_and, array( 'taxonomy' => 'category' ) );
    2726                 if ( ! empty( $cat_query ) ) {
    2727                     $cat_query = reset( $cat_query );
    2728 
    2729                     if ( ! empty( $cat_query['terms'][0] ) ) {
    2730                         $the_cat = get_term_by( $cat_query['field'], $cat_query['terms'][0], 'category' );
    2731                         if ( $the_cat ) {
    2732                             $this->set( 'cat', $the_cat->term_id );
    2733                             $this->set( 'category_name', $the_cat->slug );
    2734                         }
    2735                         unset( $the_cat );
     2737            }
     2738
     2739            // 'cat', 'category_name', 'tag_id'
     2740            foreach ( $this->tax_query->queried_terms as $queried_taxonomy => $queried_items ) {
     2741                if ( empty( $queried_items['terms'][0] ) ) {
     2742                    continue;
     2743                }
     2744
     2745                if ( 'category' === $queried_taxonomy ) {
     2746                    $the_cat = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'category' );
     2747                    if ( $the_cat ) {
     2748                        $this->set( 'cat', $the_cat->term_id );
     2749                        $this->set( 'category_name', $the_cat->slug );
    27362750                    }
     2751                    unset( $the_cat );
    27372752                }
    2738                 unset( $cat_query );
    2739 
    2740                 $tag_query = wp_list_filter( $tax_query_in_and, array( 'taxonomy' => 'post_tag' ) );
    2741                 if ( ! empty( $tag_query ) ) {
    2742                     $tag_query = reset( $tag_query );
    2743 
    2744                     if ( ! empty( $tag_query['terms'][0] ) ) {
    2745                         $the_tag = get_term_by( $tag_query['field'], $tag_query['terms'][0], 'post_tag' );
    2746                         if ( $the_tag )
    2747                             $this->set( 'tag_id', $the_tag->term_id );
    2748                         unset( $the_tag );
     2753
     2754                if ( 'post_tag' === $queried_taxonomy ) {
     2755                    $the_tag = get_term_by( $queried_items['field'], $queried_items['terms'][0], 'post_tag' );
     2756                    if ( $the_tag ) {
     2757                        $this->set( 'tag_id', $the_tag->term_id );
    27492758                    }
     2759                    unset( $the_tag );
    27502760                }
    2751                 unset( $tag_query );
    27522761            }
    27532762        }
Note: See TracChangeset for help on using the changeset viewer.