WordPress.org

Make WordPress Core


Ignore:
Timestamp:
09/13/2010 04:44:14 PM (9 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.