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:
parent
1880b466c7
commit
bf2f6f8104
@ -59,6 +59,17 @@ class WP_Comment_Query {
|
|||||||
'limits' => '',
|
'limits' => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQL WHERE clause.
|
||||||
|
*
|
||||||
|
* Stored after the 'comments_clauses' filter is run on the compiled WHERE sub-clauses.
|
||||||
|
*
|
||||||
|
* @since 4.4.2
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $filtered_where_clause;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date query container
|
* Date query container
|
||||||
*
|
*
|
||||||
@ -823,6 +834,8 @@ class WP_Comment_Query {
|
|||||||
$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
|
$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
|
||||||
$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
|
$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
|
||||||
|
|
||||||
|
$this->filtered_where_clause = $where;
|
||||||
|
|
||||||
if ( $where ) {
|
if ( $where ) {
|
||||||
$where = 'WHERE ' . $where;
|
$where = 'WHERE ' . $where;
|
||||||
}
|
}
|
||||||
@ -874,12 +887,27 @@ class WP_Comment_Query {
|
|||||||
0 => wp_list_pluck( $comments, 'comment_ID' ),
|
0 => wp_list_pluck( $comments, 'comment_ID' ),
|
||||||
);
|
);
|
||||||
|
|
||||||
$where_clauses = $this->sql_clauses['where'];
|
/*
|
||||||
unset(
|
* The WHERE clause for the descendant query is the same as for the top-level
|
||||||
$where_clauses['parent'],
|
* query, minus the `parent`, `parent__in`, and `parent__not_in` sub-clauses.
|
||||||
$where_clauses['parent__in'],
|
*/
|
||||||
$where_clauses['parent__not_in']
|
$_where = $this->filtered_where_clause;
|
||||||
);
|
$exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' );
|
||||||
|
foreach ( $exclude_keys as $exclude_key ) {
|
||||||
|
if ( isset( $this->sql_clauses['where'][ $exclude_key ] ) ) {
|
||||||
|
$clause = $this->sql_clauses['where'][ $exclude_key ];
|
||||||
|
|
||||||
|
// Strip the clause as well as any adjacent ANDs.
|
||||||
|
$pattern = '|(?:AND)?\s*' . $clause . '\s*(?:AND)?|';
|
||||||
|
$_where_parts = preg_split( $pattern, $_where );
|
||||||
|
|
||||||
|
// Remove empties.
|
||||||
|
$_where_parts = array_filter( array_map( 'trim', $_where_parts ) );
|
||||||
|
|
||||||
|
// Reassemble with an AND.
|
||||||
|
$_where = implode( ' AND ', $_where_parts );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch an entire level of the descendant tree at a time.
|
// Fetch an entire level of the descendant tree at a time.
|
||||||
$level = 0;
|
$level = 0;
|
||||||
@ -889,7 +917,7 @@ class WP_Comment_Query {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$where = 'WHERE ' . implode( ' AND ', $where_clauses ) . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $parent_ids ) ) . ')';
|
$where = 'WHERE ' . $_where . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $parent_ids ) ) . ')';
|
||||||
$comment_ids = $wpdb->get_col( "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} ORDER BY comment_date_gmt ASC, comment_ID ASC" );
|
$comment_ids = $wpdb->get_col( "{$this->sql_clauses['select']} {$this->sql_clauses['from']} {$where} {$this->sql_clauses['groupby']} ORDER BY comment_date_gmt ASC, comment_ID ASC" );
|
||||||
|
|
||||||
$level++;
|
$level++;
|
||||||
|
@ -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' ) ) );
|
$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
|
* @ticket 27571
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user