Make WordPress Core


Ignore:
Timestamp:
09/13/2010 04:44:14 PM (14 years ago)
Author:
scribu
Message:

Clean up taxonomy queries in WP_Query. See #12891

File:
1 edited

Legend:

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

    r15590 r15613  
    661661     */
    662662    var $query_vars = array();
     663
     664    /**
     665     * Taxonomy query, after parsing
     666     *
     667     * @since 3.1.0
     668     * @access public
     669     * @var array
     670     */
     671    var $tax_query = array();
    663672
    664673    /**
     
    15291538        // First let's clear some variables
    15301539        $distinct = '';
    1531         $whichcat = '';
    15321540        $whichauthor = '';
    15331541        $whichmimetype = '';
     
    17861794        $search = apply_filters_ref_array('posts_search', array( $search, &$this ) );
    17871795
     1796        // Taxonomies
     1797        $tax_query = array();
     1798
     1799        if ( $this->is_tax ) {
     1800            foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
     1801                if ( $t->query_var && !empty( $q[$t->query_var] ) ) {
     1802                    $tax_query_defaults = array(
     1803                        'taxonomy' => $taxonomy,
     1804                        'field' => 'slug',
     1805                        'operator' => 'IN'
     1806                    );
     1807
     1808                    $term = str_replace( ' ', '+', $q[$t->query_var] );
     1809
     1810                    if ( strpos($term, '+') !== false ) {
     1811                        $terms = preg_split( '/[+\s]+/', $term );
     1812                        foreach ( $terms as $term ) {
     1813                            $tax_query[] = array_merge( $tax_query_defaults, array(
     1814                                'terms' => array( $term )
     1815                            ) );
     1816                        }
     1817                    } else {
     1818                        $tax_query[] = array_merge( $tax_query_defaults, array(
     1819                            'terms' => preg_split('/[,\s]+/', $term)
     1820                        ) );
     1821                    }
     1822                }
     1823            }
     1824        }
     1825
    17881826        // Category stuff
    1789 
    1790         if ( empty($q['cat']) || ($q['cat'] == '0') ||
    1791                 // Bypass cat checks if fetching specific posts
    1792                 $this->is_singular ) {
    1793             $whichcat = '';
    1794         } else {
     1827        if ( !empty($q['cat']) && '0' != $q['cat'] && !$this->is_singular ) {
    17951828            $q['cat'] = ''.urldecode($q['cat']).'';
    17961829            $q['cat'] = addslashes_gpc($q['cat']);
     
    18051838                if ( $in ) {
    18061839                    $q['category__in'][] = $cat;
    1807                     $q['category__in'] = array_merge($q['category__in'], get_term_children($cat, 'category'));
    18081840                } else {
    18091841                    $q['category__not_in'][] = $cat;
    1810                     $q['category__not_in'] = array_merge($q['category__not_in'], get_term_children($cat, 'category'));
    18111842                }
    18121843            }
     
    18151846
    18161847        if ( !empty($q['category__in']) ) {
    1817             $join = " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
    1818             $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'category' ";
    1819             $include_cats = "'" . implode("', '", $q['category__in']) . "'";
    1820             $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_cats) ";
     1848            $tax_query[] = array(
     1849                'taxonomy' => 'category',
     1850                'terms' => $q['category__in'],
     1851                'operator' => 'IN',
     1852                'field' => 'term_id'
     1853            );
    18211854        }
    18221855
    18231856        if ( !empty($q['category__not_in']) ) {
    1824             $cat_string = "'" . implode("', '", $q['category__not_in']) . "'";
    1825             $whichcat .= " AND $wpdb->posts.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND tt.term_id IN ($cat_string) )";
     1857            $tax_query[] = array(
     1858                'taxonomy' => 'category',
     1859                'terms' => $q['category__not_in'],
     1860                'operator' => 'NOT IN',
     1861                'field' => 'term_id'
     1862            );
    18261863        }
    18271864
     
    18521889            $q['cat'] = $reqcat;
    18531890
    1854             $join = " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
    1855             $whichcat = " AND $wpdb->term_taxonomy.taxonomy = 'category' ";
    1856             $in_cats = array($q['cat']);
    1857             $in_cats = array_merge($in_cats, get_term_children($q['cat'], 'category'));
    1858             $in_cats = "'" . implode("', '", $in_cats) . "'";
    1859             $whichcat .= "AND $wpdb->term_taxonomy.term_id IN ($in_cats)";
     1891            $tax_query[] = array(
     1892                'taxonomy' => 'category',
     1893                'terms' => array( $q['cat'] ),
     1894                'operator' => 'IN',
     1895                'field' => 'term_id'
     1896            );
     1897        }
     1898
     1899        // Tag stuff
     1900        if ( !empty($qv['tag_id']) ) {
     1901            $tax_query[] = array(
     1902                'taxonomy' => 'post_tag',
     1903                'terms' => $qv['tag_id'],
     1904                'operator' => 'IN',
     1905                'field' => 'term_id'
     1906            );
     1907        }
     1908
     1909        if ( !empty($q['tag__in']) ) {
     1910            $tax_query[] = array(
     1911                'taxonomy' => 'post_tag',
     1912                'terms' => $q['tag__in'],
     1913                'operator' => 'IN',
     1914                'field' => 'term_id'
     1915            );
     1916        }
     1917
     1918        if ( !empty($q['tag__not_in']) ) {
     1919            $tax_query[] = array(
     1920                'taxonomy' => 'post_tag',
     1921                'terms' => $q['tag__not_in'],
     1922                'operator' => 'NOT IN',
     1923                'field' => 'term_id'
     1924            );
     1925        }
     1926
     1927        if ( !empty( $tax_query ) ) {
     1928            $this->tax_query = $tax_query;
     1929
     1930            $where .= " AND $wpdb->posts.ID IN( " . implode( ', ', wp_tax_query( $tax_query ) ) . ")";
     1931        }
     1932
     1933        if ( !empty($q['meta_key']) ) {
    18601934            $groupby = "{$wpdb->posts}.ID";
    1861         }
    1862 
    1863         // Tags
    1864         if ( '' != $q['tag'] ) {
    1865             if ( strpos($q['tag'], ',') !== false ) {
    1866                 $tags = preg_split('/[,\s]+/', $q['tag']);
    1867                 foreach ( (array) $tags as $tag ) {
    1868                     $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
    1869                     $q['tag_slug__in'][] = $tag;
    1870                 }
    1871             } else if ( preg_match('/[+\s]+/', $q['tag']) || !empty($q['cat']) ) {
    1872                 $tags = preg_split('/[+\s]+/', $q['tag']);
    1873                 foreach ( (array) $tags as $tag ) {
    1874                     $tag = sanitize_term_field('slug', $tag, 0, 'post_tag', 'db');
    1875                     $q['tag_slug__and'][] = $tag;
    1876                 }
    1877             } else {
    1878                 $q['tag'] = sanitize_term_field('slug', $q['tag'], 0, 'post_tag', 'db');
    1879                 $q['tag_slug__in'][] = $q['tag'];
    1880             }
    1881         }
    1882 
    1883         if ( !empty($q['category__in']) || !empty($q['meta_key']) || !empty($q['tag__in']) || !empty($q['tag_slug__in']) ) {
    1884             $groupby = "{$wpdb->posts}.ID";
    1885         }
    1886 
    1887         if ( !empty($q['tag__in']) && empty($q['cat']) ) {
    1888             $join = " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
    1889             $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' ";
    1890             $include_tags = "'" . implode("', '", $q['tag__in']) . "'";
    1891             $whichcat .= " AND $wpdb->term_taxonomy.term_id IN ($include_tags) ";
    1892             $reqtag = term_exists( $q['tag__in'][0], 'post_tag' );
    1893             if ( !empty($reqtag) )
    1894                 $q['tag_id'] = $reqtag['term_id'];
    1895         }
    1896 
    1897         if ( !empty($q['tag_slug__in']) && empty($q['cat']) ) {
    1898             $join = " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) INNER JOIN $wpdb->terms ON ($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id) ";
    1899             $whichcat .= " AND $wpdb->term_taxonomy.taxonomy = 'post_tag' ";
    1900             $include_tags = "'" . implode("', '", $q['tag_slug__in']) . "'";
    1901             $whichcat .= " AND $wpdb->terms.slug IN ($include_tags) ";
    1902             $reqtag = get_term_by( 'slug', $q['tag_slug__in'][0], 'post_tag' );
    1903             if ( !empty($reqtag) )
    1904                 $q['tag_id'] = $reqtag->term_id;
    1905         }
    1906 
    1907         if ( !empty($q['tag__not_in']) ) {
    1908             $tag_string = "'" . implode("', '", $q['tag__not_in']) . "'";
    1909             $whichcat .= " AND $wpdb->posts.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'post_tag' AND tt.term_id IN ($tag_string) )";
    1910         }
    1911 
    1912         // Tag and slug intersections.
    1913         $intersections = array('category__and' => 'category', 'tag__and' => 'post_tag', 'tag_slug__and' => 'post_tag', 'tag__in' => 'post_tag', 'tag_slug__in' => 'post_tag');
    1914         $tagin = array('tag__in', 'tag_slug__in'); // These are used to make some exceptions below
    1915         foreach ( $intersections as $item => $taxonomy ) {
    1916             if ( empty($q[$item]) ) continue;
    1917             if ( in_array($item, $tagin) && empty($q['cat']) ) continue; // We should already have what we need if categories aren't being used
    1918 
    1919             if ( $item != 'category__and' ) {
    1920                 $reqtag = term_exists( $q[$item][0], 'post_tag' );
    1921                 if ( !empty($reqtag) )
    1922                     $q['tag_id'] = $reqtag['term_id'];
    1923             }
    1924 
    1925             if ( in_array( $item, array('tag_slug__and', 'tag_slug__in' ) ) )
    1926                 $taxonomy_field = 'slug';
    1927             else
    1928                 $taxonomy_field = 'term_id';
    1929 
    1930             $q[$item] = array_unique($q[$item]);
    1931             $tsql = "SELECT p.ID FROM $wpdb->posts p INNER JOIN $wpdb->term_relationships tr ON (p.ID = tr.object_id) INNER JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) INNER JOIN $wpdb->terms t ON (tt.term_id = t.term_id)";
    1932             $tsql .= " WHERE tt.taxonomy = '$taxonomy' AND t.$taxonomy_field IN ('" . implode("', '", $q[$item]) . "')";
    1933             if ( !in_array($item, $tagin) ) { // This next line is only helpful if we are doing an and relationship
    1934                 $tsql .= " GROUP BY p.ID HAVING count(p.ID) = " . count($q[$item]);
    1935             }
    1936             $post_ids = $wpdb->get_col($tsql);
    1937 
    1938             if ( count($post_ids) )
    1939                 $whichcat .= " AND $wpdb->posts.ID IN (" . implode(', ', $post_ids) . ") ";
    1940             else {
    1941                 $whichcat = " AND 0 = 1";
    1942                 break;
    1943             }
    1944         }
    1945 
    1946         // Taxonomies
    1947         if ( $this->is_tax ) {
    1948             if ( '' != $q['taxonomy'] ) {
    1949                 $taxonomy = $q['taxonomy'];
    1950                 $tt[$taxonomy] = $q['term'];
    1951             } else {
    1952                 foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) {
    1953                     if ( $t->query_var && '' != $q[$t->query_var] ) {
    1954                         $tt[$taxonomy] = $q[$t->query_var];
    1955                         break;
    1956                     }
    1957                 }
    1958             }
    1959 
    1960             $terms = get_terms($taxonomy, array('slug' => $tt[$taxonomy], 'hide_empty' => !is_taxonomy_hierarchical($taxonomy)));
    1961 
    1962             if ( is_wp_error($terms) || empty($terms) ) {
    1963                 $whichcat = " AND 0 ";
    1964             } else {
    1965                 foreach ( $terms as $term ) {
    1966                     $term_ids[] = $term->term_id;
    1967                     if ( is_taxonomy_hierarchical($taxonomy) ) {
    1968                         $children = get_term_children($term->term_id, $taxonomy);
    1969                         $term_ids = array_merge($term_ids, $children);
    1970                     }
    1971                 }
    1972                 $post_ids = get_objects_in_term($term_ids, $taxonomy);
    1973                 if ( !is_wp_error($post_ids) && !empty($post_ids) ) {
    1974                     $whichcat .= " AND $wpdb->posts.ID IN (" . implode(', ', $post_ids) . ") ";
    1975                     if ( empty($post_type) ) {
    1976                         $post_type = 'any';
    1977                         $post_status_join = true;
    1978                     } elseif ( in_array('attachment', (array)$post_type) ) {
    1979                         $post_status_join = true;
    1980                     }
    1981                 } else {
    1982                     $whichcat = " AND 0 ";
    1983                 }
    1984             }
    19851935        }
    19861936
     
    20341984        }
    20351985
    2036         $where .= $search . $whichcat . $whichauthor . $whichmimetype;
     1986        $where .= $search . $whichauthor . $whichmimetype;
    20371987
    20381988        if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC')) )
     
    26262576        $this->queried_object_id = 0;
    26272577
    2628         if ( $this->is_category ) {
    2629             $cat = $this->get('cat');
    2630             $category = &get_category($cat);
    2631             if ( is_wp_error( $category ) )
    2632                 return NULL;
    2633             $this->queried_object = &$category;
    2634             $this->queried_object_id = (int) $cat;
    2635         } elseif ( $this->is_tag ) {
    2636             $tag_id = $this->get('tag_id');
    2637             $tag = &get_term($tag_id, 'post_tag');
    2638             if ( is_wp_error( $tag ) )
    2639                 return NULL;
    2640             $this->queried_object = &$tag;
    2641             $this->queried_object_id = (int) $tag_id;
    2642         } elseif ( $this->is_tax ) {
    2643             $tax = $this->get('taxonomy');
    2644             $slug = $this->get('term');
    2645             $term = &get_terms($tax, array( 'slug' => $slug, 'hide_empty' => false ) );
    2646             if ( is_wp_error($term) || empty($term) )
    2647                 return NULL;
    2648             $term = $term[0];
     2578        if ( $this->tax_query ) {
     2579            $query = reset( $this->tax_query );
     2580            if ( 'term_id' == $query['field']  )
     2581                $term = get_term( reset( $query['terms'] ), $query['taxonomy'] );
     2582            else
     2583                $term = get_term_by( $query['field'], reset( $query['terms'] ), $query['taxonomy'] );
     2584
    26492585            $this->queried_object = $term;
    26502586            $this->queried_object_id = $term->term_id;
Note: See TracChangeset for help on using the changeset viewer.