Make WordPress Core

Changeset 41377


Ignore:
Timestamp:
09/13/2017 02:47:07 PM (9 years 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.