Use the post-filter WHERE clause when querying for comment descendants.

The descendant query in `WP_Comment_Query::fill_descendants()` uses the clauses
of the main `get_comment_ids()` query as a basis, discarding the `parent`,
`parent__in`, and `parent__not_in` clauses. As implemented in WP 4.4 [34546],
the WHERE clause was assembled in such a way that any modifications applied
using the `comments_clauses` filter were not inherited by `fill_descendants()`.
This resulted in descendant queries that did not always properly filter
results, and sometimes contained syntax errors.

The current changeset fixes the problem by using the post-filter WHERE clause
as the basis for the `fill_descendants()` query. This change requires a new
approach for eliminating the unneeded parent-related clauses: instead of
eliminating values in an associative array, we must use regular expressions.

Props boonebgorges, firebird75.
Fixes #35192.

git-svn-id: https://develop.svn.wordpress.org/trunk@36277 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Boone Gorges
2016-01-13 04:00:36 +00:00
parent 1880b466c7
commit bf2f6f8104
2 changed files with 126 additions and 7 deletions

View File

@@ -2128,6 +2128,97 @@ class Tests_Comment_Query extends WP_UnitTestCase {
$this->assertEqualSets( array(), array_values( wp_list_pluck( $q->comments[ $c1 ]->get_child( $c2 )->get_children( $args ), 'comment_ID' ) ) );
}
/**
* @ticket 35192
*/
public function test_comment_clauses_prepend_callback_should_be_respected_when_filling_descendants() {
$top_level_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
) );
$child1_of_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
'comment_parent' => $top_level_0,
) );
$child2_of_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
'comment_parent' => $top_level_0,
) );
$top_level_comments = self::factory()->comment->create_many( 3, array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
) );
$this->to_exclude = array( $child2_of_0, $top_level_comments[1] );
add_filter( 'comments_clauses', array( $this, 'prepend_exclusions' ) );
$q = new WP_Comment_Query( array(
'post_id' => $this->post_id,
'hierarchical' => 'flat',
) );
remove_filter( 'comments_clauses', array( $this, 'prepend_exclusions' ) );
unset( $this->to_exclude );
$this->assertEqualSets( array( $top_level_0, $child1_of_0, $top_level_comments[0], $top_level_comments[2] ), wp_list_pluck( $q->comments, 'comment_ID' ) );
}
public function prepend_exclusions( $clauses ) {
global $wpdb;
$clauses['where'] = $wpdb->prepare( 'comment_ID != %d AND comment_ID != %d AND ', $this->to_exclude[0], $this->to_exclude[1] ) . $clauses['where'];
return $clauses;
}
/**
* @ticket 35192
*/
public function test_comment_clauses_append_callback_should_be_respected_when_filling_descendants() {
$top_level_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
) );
$child1_of_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
'comment_parent' => $top_level_0,
) );
$child2_of_0 = self::factory()->comment->create( array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
'comment_parent' => $top_level_0,
) );
$top_level_comments = self::factory()->comment->create_many( 3, array(
'comment_post_ID' => $this->post_id,
'comment_approved' => '1',
) );
$this->to_exclude = array( $child2_of_0, $top_level_comments[1] );
add_filter( 'comments_clauses', array( $this, 'append_exclusions' ) );
$q = new WP_Comment_Query( array(
'post_id' => $this->post_id,
'hierarchical' => 'flat',
) );
remove_filter( 'comments_clauses', array( $this, 'append_exclusions' ) );
unset( $this->to_exclude );
$this->assertEqualSets( array( $top_level_0, $child1_of_0, $top_level_comments[0], $top_level_comments[2] ), wp_list_pluck( $q->comments, 'comment_ID' ) );
}
public function append_exclusions( $clauses ) {
global $wpdb;
$clauses['where'] .= $wpdb->prepare( ' AND comment_ID != %d AND comment_ID != %d', $this->to_exclude[0], $this->to_exclude[1] );
return $clauses;
}
/**
* @ticket 27571
*/