Make WordPress Core


Ignore:
Timestamp:
01/13/2016 04:00:36 AM (8 years ago)
Author:
boonebgorges
Message:

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.

File:
1 edited

Legend:

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

    r36224 r36277  
    5959        'limits'  => '',
    6060    );
     61
     62    /**
     63     * SQL WHERE clause.
     64     *
     65     * Stored after the 'comments_clauses' filter is run on the compiled WHERE sub-clauses.
     66     *
     67     * @since 4.4.2
     68     * @access protected
     69     * @var string
     70     */
     71    protected $filtered_where_clause;
    6172
    6273    /**
     
    824835        $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
    825836
     837        $this->filtered_where_clause = $where;
     838
    826839        if ( $where ) {
    827840            $where = 'WHERE ' . $where;
     
    875888        );
    876889
    877         $where_clauses = $this->sql_clauses['where'];
    878         unset(
    879             $where_clauses['parent'],
    880             $where_clauses['parent__in'],
    881             $where_clauses['parent__not_in']
    882         );
     890        /*
     891         * The WHERE clause for the descendant query is the same as for the top-level
     892         * query, minus the `parent`, `parent__in`, and `parent__not_in` sub-clauses.
     893         */
     894        $_where = $this->filtered_where_clause;
     895        $exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' );
     896        foreach ( $exclude_keys as $exclude_key ) {
     897            if ( isset( $this->sql_clauses['where'][ $exclude_key ] ) ) {
     898                $clause = $this->sql_clauses['where'][ $exclude_key ];
     899
     900                // Strip the clause as well as any adjacent ANDs.
     901                $pattern = '|(?:AND)?\s*' . $clause . '\s*(?:AND)?|';
     902                $_where_parts = preg_split( $pattern, $_where );
     903
     904                // Remove empties.
     905                $_where_parts = array_filter( array_map( 'trim', $_where_parts ) );
     906
     907                // Reassemble with an AND.
     908                $_where = implode( ' AND ', $_where_parts );
     909            }
     910        }
    883911
    884912        // Fetch an entire level of the descendant tree at a time.
     
    890918            }
    891919
    892             $where = 'WHERE ' . implode( ' AND ', $where_clauses ) . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $parent_ids ) ) . ')';
     920            $where = 'WHERE ' . $_where . ' AND comment_parent IN (' . implode( ',', array_map( 'intval', $parent_ids ) ) . ')';
    893921            $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" );
    894922
Note: See TracChangeset for help on using the changeset viewer.