Make WordPress Core


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

Clean up taxonomy queries in WP_Query. See #12891

File:
1 edited

Legend:

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

    r15590 r15613  
    2424                'show_ui' => true,
    2525                '_builtin' => true,
    26         ) ) ;
     26        ) );
    2727
    2828        register_taxonomy( 'post_tag', 'post', array(
    2929                'hierarchical' => false,
    3030                'update_count_callback' => '_update_post_term_count',
    31                 'query_var' => false,
     31                'query_var' => 'tag',
    3232                'rewrite' => false,
    3333                'public' => true,
     
    433433 * @uses wp_parse_args() Creates an array from string $args.
    434434 *
    435  * @param int|array $term_ids Term id or array of term ids of terms that will be used
     435 * @param mixed $terms Term id/slug/name or array of such to match against
    436436 * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names
    437  * @param array|string $args Change the order of the object_ids, either ASC or DESC
    438  * @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success
    439  *      the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found.
    440  */
    441 function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
     437 * @param array|string $args
     438 *   'include_children' bool Wether to include term children (hierarchical taxonomies only)
     439 *   'field' string Which term field is being used. Can be 'term_id', 'slug' or 'name'
     440 *   'operator' string Can be 'IN' and 'NOT IN'
     441 *   'do_query' bool Wether to execute the query or return the SQL string
     442 *
     443 * @return WP_Error If the taxonomy does not exist
     444 * @return array The list of found object_ids
     445 * @return string The SQL string, if do_query is set to false
     446 */
     447function get_objects_in_term( $terms, $taxonomies, $args = array() ) {
    442448        global $wpdb;
    443449
    444         if ( ! is_array( $term_ids ) )
    445                 $term_ids = array( $term_ids );
    446 
    447         if ( ! is_array( $taxonomies ) )
    448                 $taxonomies = array( $taxonomies );
    449 
    450         foreach ( (array) $taxonomies as $taxonomy ) {
     450        extract( wp_parse_args( $args, array(
     451                'include_children' => false,
     452                'field' => 'term_id',
     453                'operator' => 'IN',
     454                'do_query' => true,
     455        ) ), EXTR_SKIP );
     456
     457        $taxonomies = (array) $taxonomies;
     458
     459        foreach ( $taxonomies as $taxonomy ) {
    451460                if ( ! taxonomy_exists( $taxonomy ) )
    452                         return new WP_Error( 'invalid_taxonomy', __( 'Invalid Taxonomy' ) );
    453         }
    454 
    455         $defaults = array( 'order' => 'ASC' );
    456         $args = wp_parse_args( $args, $defaults );
    457         extract( $args, EXTR_SKIP );
    458 
    459         $order = ( 'desc' == strtolower( $order ) ) ? 'DESC' : 'ASC';
    460 
    461         $term_ids = array_map('intval', $term_ids );
     461                        return new WP_Error( 'invalid_taxonomy', sprintf( __( 'Invalid Taxonomy: %s' ), $taxonomy ) );
     462        }
     463
     464        $terms = array_unique( (array) $terms );
     465        if ( empty($terms) )
     466                continue;
     467
     468        if ( !in_array( $field, array( 'term_id', 'slug', 'name' ) ) )
     469                $field = 'term_id';
     470
     471        if ( !in_array( $operator, array( 'IN', 'NOT IN' ) ) )
     472                $operator = 'IN';
    462473
    463474        $taxonomies = "'" . implode( "', '", $taxonomies ) . "'";
    464         $term_ids = "'" . implode( "', '", $term_ids ) . "'";
    465 
    466         $object_ids = $wpdb->get_col("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 IN ($taxonomies) AND tt.term_id IN ($term_ids) ORDER BY tr.object_id $order");
    467 
    468         if ( ! $object_ids )
    469                 return array();
    470 
    471         return $object_ids;
     475
     476        switch ( $field ) {
     477                case 'term_id':
     478                        $terms = array_map( 'intval', $terms );
     479
     480                        if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) {
     481                                $children = $terms;
     482                                foreach ( $terms as $term )
     483                                        $children = array_merge( $children, get_term_children( $term, $taxonomy ) );
     484                                $terms = $children;
     485                        }
     486
     487                        $terms = implode( ',', $terms );
     488                        $sql = "
     489                                SELECT object_id
     490                                FROM $wpdb->term_relationships
     491                                INNER JOIN $wpdb->term_taxonomy USING (term_taxonomy_id)
     492                                WHERE taxonomy IN ($taxonomies)
     493                                AND term_id $operator ($terms)
     494                        ";
     495                break;
     496
     497                case 'slug':
     498                case 'name':
     499                        foreach ( $terms as $i => $term ) {
     500                                $terms[$i] = sanitize_term_field('slug', $term, 0, $taxonomy, 'db');
     501                        }
     502                        $terms = array_filter($terms);
     503
     504                        $terms = "'" . implode( "','", $terms ) . "'";
     505                        $sql = "
     506                                SELECT object_id
     507                                FROM $wpdb->term_relationships
     508                                INNER JOIN $wpdb->term_taxonomy USING (term_taxonomy_id)
     509                                INNER JOIN $wpdb->terms USING (term_id)
     510                                WHERE taxonomy IN ($taxonomies)
     511                                AND $field $operator ($terms)
     512                        ";
     513                break;
     514        }
     515
     516        if ( !$do_query )
     517                return $sql;
     518
     519        return $wpdb->get_col( $sql ); 
     520}
     521
     522/*
     523 * Retrieve object_ids matching one or more taxonomy queries
     524 *
     525 * @since 3.1.0
     526 *
     527 * @param array $queries A list of taxonomy queries. A query is an associative array:
     528 *   'taxonomy' string|array The taxonomy being queried
     529 *   'terms' string|array The list of terms
     530 *   'field' string Which term field is being used. Can be 'term_id', 'slug' or 'name'
     531 *   'operator' string Can be 'IN' and 'NOT IN'
     532 *
     533 * @return array|WP_Error List of matching object_ids; WP_Error on failure.
     534 */
     535function wp_tax_query( $queries ) {
     536        global $wpdb;
     537
     538        $sql = array();
     539        foreach ( $queries as $query ) {
     540                if ( !isset( $query['include_children'] ) )
     541                        $query['include_children'] = true;
     542                $query['do_query'] = false;
     543                $sql[] = get_objects_in_term( $query['terms'], $query['taxonomy'], $query );
     544        }
     545
     546        if ( 1 == count( $sql ) )
     547                return $wpdb->get_col( $sql[0] );
     548
     549        $r = "SELECT object_id FROM $wpdb->term_relationships WHERE 1=1";
     550        foreach ( $sql as $query )
     551                $r .= " AND object_id IN ($query)";
     552
     553        return $wpdb->get_col( $r );
    472554}
    473555
Note: See TracChangeset for help on using the changeset viewer.