WordPress.org

Make WordPress Core

Changeset 41377


Ignore:
Timestamp:
09/13/17 14:47:07 (2 months ago)
Author:
boonebgorges
Message:

Taxonomy: Force a DISTINCT term query when result count matters.

Generally, duplicate terms returned by a term query are eliminated in PHP,
after the database query takes place. This technique doesn't work properly
when the query parameters specify the number of results, since the results
of a SELECT ... LIMIT x... query may be deduplicated to a count less than
x. In these cases, we force the original query to be DISTINCT.

Props elvishp2006.
Fixes #41796.

Location:
trunk
Files:
2 edited

Legend:

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

    r41162 r41377  
    552552        } 
    553553 
     554        $do_distinct = false; 
     555 
     556        /* 
     557         * Duplicate terms are generally removed when necessary after the database query. 
     558         * But when a LIMIT clause is included in the query, we let MySQL enforce 
     559         * distinctness so the count is correct. 
     560         */ 
     561        if ( ! empty( $limits ) && 'all_with_object_id' !== $args['fields'] ) { 
     562            $do_distinct = true; 
     563        } 
    554564 
    555565        if ( ! empty( $args['search'] ) ) { 
     
    569579            $join .= $mq_sql['join']; 
    570580            $this->sql_clauses['where']['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $mq_sql['where'] ); 
    571             $distinct .= "DISTINCT"; 
    572  
     581            $do_distinct = true; 
    573582        } 
    574583 
     
    632641        $where = implode( ' AND ', $this->sql_clauses['where'] ); 
    633642 
     643        $distinct = $do_distinct ? 'DISTINCT' : ''; 
     644 
    634645        /** 
    635646         * Filters the terms query SQL clauses. 
  • trunk/tests/phpunit/tests/term/query.php

    r40513 r41377  
    428428        $this->assertEquals( array( $term_ids[1], $term_ids[0], 1 ), wp_list_pluck( $terms, 'term_id' ) ); 
    429429    } 
     430 
     431    /** 
     432     * @ticket 41796 
     433     */ 
     434    public function test_number_should_work_with_object_ids() { 
     435        register_taxonomy( 'wptests_tax', 'post' ); 
     436 
     437        $term_1 = self::factory()->term->create( array( 
     438            'taxonomy' => 'wptests_tax', 
     439        ) ); 
     440        $term_2 = self::factory()->term->create( array( 
     441            'taxonomy' => 'wptests_tax', 
     442        ) ); 
     443 
     444        $post_1 = self::factory()->post->create(); 
     445        $post_2 = self::factory()->post->create(); 
     446 
     447        wp_set_object_terms( $post_1, array( $term_1, $term_2 ), 'wptests_tax' ); 
     448        wp_set_object_terms( $post_2, array( $term_1 ), 'wptests_tax' ); 
     449 
     450        $q = new WP_Term_Query( array( 
     451            'taxonomy' => 'wptests_tax', 
     452            'object_ids' => array( $post_1, $post_2 ), 
     453            'number' => 2, 
     454        ) ); 
     455 
     456        $this->assertEqualSets( array( $term_1, $term_2 ), wp_list_pluck( $q->terms, 'term_id' ) ); 
     457    } 
     458 
     459    /** 
     460     * @ticket 41796 
     461     */ 
     462    public function test_number_should_work_with_object_ids_and_all_with_object_id() { 
     463        register_taxonomy( 'wptests_tax', 'post' ); 
     464 
     465        $term_1 = self::factory()->term->create( array( 
     466            'taxonomy' => 'wptests_tax', 
     467        ) ); 
     468        $term_2 = self::factory()->term->create( array( 
     469            'taxonomy' => 'wptests_tax', 
     470        ) ); 
     471 
     472        $post_1 = self::factory()->post->create(); 
     473        $post_2 = self::factory()->post->create(); 
     474 
     475        wp_set_object_terms( $post_1, array( $term_1, $term_2 ), 'wptests_tax' ); 
     476        wp_set_object_terms( $post_2, array( $term_1 ), 'wptests_tax' ); 
     477 
     478        $q = new WP_Term_Query( array( 
     479            'taxonomy' => 'wptests_tax', 
     480            'object_ids' => array( $post_1, $post_2 ), 
     481            'fields' => 'all_with_object_id', 
     482            'number' => 2, 
     483        ) ); 
     484 
     485        $this->assertEqualSets( array( $term_1, $term_1 ), wp_list_pluck( $q->terms, 'term_id' ) ); 
     486    } 
    430487} 
Note: See TracChangeset for help on using the changeset viewer.