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.
Built from https://develop.svn.wordpress.org/trunk@36277


git-svn-id: http://core.svn.wordpress.org/trunk@36244 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Boone Gorges 2016-01-13 04:01:26 +00:00
parent 4ac35f5713
commit 98fb5f0bdb
2 changed files with 36 additions and 8 deletions

View File

@ -59,6 +59,17 @@ class WP_Comment_Query {
'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
*
@ -823,6 +834,8 @@ class WP_Comment_Query {
$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
$this->filtered_where_clause = $where;
if ( $where ) {
$where = 'WHERE ' . $where;
}
@ -874,12 +887,27 @@ class WP_Comment_Query {
0 => wp_list_pluck( $comments, 'comment_ID' ),
);
$where_clauses = $this->sql_clauses['where'];
unset(
$where_clauses['parent'],
$where_clauses['parent__in'],
$where_clauses['parent__not_in']
);
/*
* The WHERE clause for the descendant query is the same as for the top-level
* query, minus the `parent`, `parent__in`, and `parent__not_in` sub-clauses.
*/
$_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.
$level = 0;
@ -889,7 +917,7 @@ class WP_Comment_Query {
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" );
$level++;

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.5-alpha-36276';
$wp_version = '4.5-alpha-36277';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.