Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add include, lower_limit_object_id and higher_limit_object_id for com… #4074

Merged
merged 6 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 111 additions & 24 deletions includes/classes/Indexable/Comment/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ class Comment extends Indexable {
*/
public $slug = 'comment';

/**
* Flag to indicate if the indexable has support for
* `id_range` pagination method during a sync.
*
* @var boolean
* @since 5.2.0
*/
public $support_indexing_advanced_pagination = true;

/**
* Instantiate the indexable SyncManager and QueryIntegration, the main responsibles for the WP integration.
*
Expand Down Expand Up @@ -777,22 +786,31 @@ public function get_indexable_comment_status() {
* @return array
*/
public function query_db( $args ) {

$defaults = [
'type' => $this->get_indexable_comment_types(),
'status' => $this->get_indexable_comment_status(),
'post_type' => Indexables::factory()->get( 'post' )->get_indexable_post_types(),
'post_status' => Indexables::factory()->get( 'post' )->get_indexable_post_status(),
'number' => $this->get_bulk_items_per_page(),
'offset' => 0,
'orderby' => 'comment_ID',
'order' => 'desc',
'type' => $this->get_indexable_comment_types(),
'status' => $this->get_indexable_comment_status(),
'post_type' => Indexables::factory()->get( 'post' )->get_indexable_post_types(),
'post_status' => Indexables::factory()->get( 'post' )->get_indexable_post_status(),
'number' => $this->get_bulk_items_per_page(),
'offset' => 0,
'orderby' => 'comment_ID',
'order' => 'desc',
'ep_indexing_advanced_pagination' => true,
'no_found_rows' => false,
];

if ( isset( $args['per_page'] ) ) {
$args['number'] = $args['per_page'];
}

if ( isset( $args['include'] ) ) {
$args['comment__in'] = $args['include'];
}

if ( isset( $args['exclude'] ) ) {
$args['comment__not_in'] = $args['exclude'];
}

/**
* Filter database arguments for comment query
*
Expand All @@ -809,23 +827,33 @@ public function query_db( $args ) {
unset( $all_query_args['offset'] );
$all_query_args['count'] = true;

/**
* Filter database arguments for comment count query
*
* @hook ep_comment_all_query_db_args
* @param {array} $args Query arguments based to WP_Comment_Query
* @since 3.6.0
* @return {array} New arguments
*/
$total_objects = get_comments( apply_filters( 'ep_comment_all_query_db_args', $all_query_args, $args ) );

if ( ! empty( $args['offset'] ) ) {
if ( (int) $args['offset'] >= $total_objects ) {
$total_objects = 0;
}
if ( isset( $args['comment__in'] ) || 0 < $args['offset'] ) {
// Disable advanced pagination. Not useful if only indexing specific IDs.
$args['ep_indexing_advanced_pagination'] = false;
}

$query = new WP_Comment_Query( $args );
// Enforce the following query args during advanced pagination to ensure things work correctly.
if ( $args['ep_indexing_advanced_pagination'] ) {
$args = array_merge(
$args,
[
'suppress_filters' => false,
'orderby' => 'ID',
'order' => 'DESC',
'paged' => 1,
'offset' => 0,
]
);
add_filter( 'comments_clauses', array( $this, 'bulk_indexing_filter_comments_where' ), 9999, 2 );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
add_filter( 'comments_clauses', array( $this, 'bulk_indexing_filter_comments_where' ), 9999, 2 );
add_filter( 'comments_clauses', [ $this, 'bulk_indexing_filter_comments_where' ], 9999, 2 );

(we should likely enforce the use of [] instead of array() in our CS)


$query = new WP_Comment_Query( $args );
$total_objects = $query->found_comments;

remove_filter( 'comments_clauses', array( $this, 'bulk_indexing_filter_comments_where' ), 9999, 2 );
} else {
$query = new WP_Comment_Query( $args );
$total_objects = $query->found_comments;
}

if ( is_array( $query->comments ) ) {
array_walk( $query->comments, [ $this, 'remap_comments' ] );
Expand All @@ -837,6 +865,52 @@ public function query_db( $args ) {
];
}

/**
* Filters the WHERE clause of the SQL query used for bulk indexing comments by modifying it to include a range
* of comment IDs based on advanced pagination parameters.
*
* @param array $clauses Associative array of the clauses for the query.
* @param \WP_Comment_Query $query The current WP_Comment_Query instance.
*
* @return array Modified SQL query clauses.
*/
public function bulk_indexing_filter_comments_where( $clauses, $query ) {
global $wpdb;

$using_advanced_pagination = $this->get_query_var( $query, 'ep_indexing_advanced_pagination', false );

if ( $using_advanced_pagination ) {
$requested_upper_limit_id = $this->get_query_var( $query, 'ep_indexing_upper_limit_object_id', PHP_INT_MAX );
$requested_lower_limit_object_id = $this->get_query_var( $query, 'ep_indexing_lower_limit_object_id', 0 );
$last_processed_id = $this->get_query_var( $query, 'ep_indexing_last_processed_object_id', null );

// On the first loopthrough we begin with the requested upper limit ID. Afterwards, use the last processed ID to paginate.
$upper_limit_range_object_id = $requested_upper_limit_id;
if ( is_numeric( $last_processed_id ) ) {
$upper_limit_range_object_id = $last_processed_id - 1;
}

// Sanitize. Abort if unexpected data at this point.
if ( ! is_numeric( $upper_limit_range_object_id ) || ! is_numeric( $requested_lower_limit_object_id ) ) {
return $clauses;
}

$range = [
'upper_limit' => "{$wpdb->comments}.comment_ID <= {$upper_limit_range_object_id}",
'lower_limit' => "{$wpdb->comments}.comment_ID >= {$requested_lower_limit_object_id}",
];

// Skip the end range if it's unnecessary.
$skip_ending_range = 0 === $requested_lower_limit_object_id;
$where = $clauses['where'];
$where = $skip_ending_range ? " {$range['upper_limit']} AND {$where}" : " {$range['upper_limit']} AND {$range['lower_limit']} AND {$where}";

$clauses['where'] = $where;
}

return $clauses;
}

/**
* Prepare a comment document for indexing
*
Expand Down Expand Up @@ -1073,4 +1147,17 @@ protected function parse_orderby( $orderby, $order, $args ) {

return $sort;
}

/**
* Retrieve a specific query variable from the query object.
*
* @param \WP_Comment_Query $query The query object.
* @param string $query_var The name of the query variable to retrieve.
* @param string $default_value The default value to return if the query variable is not set. Default is an empty string.
*
* @return mixed The value of the query variable if set, otherwise the default value.
*/
public function get_query_var( $query, $query_var, $default_value = '' ) {
return $query->query_vars[ $query_var ] ?? $default_value;
}
}
20 changes: 11 additions & 9 deletions includes/classes/Indexable/Post/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,16 @@ public function query_db( $args ) {
];
}

/**
* Manipulate the WHERE clause of the bulk indexing query to paginate by ID in order to avoid performance issues with SQL offset.
*
* @param string $where The current $where clause.
* @param WP_Query $query WP_Query object.
* @return string WHERE clause with our pagination added if needed.
*/
/**
* Manipulate the WHERE clause of the bulk indexing query to paginate by ID in order to avoid performance issues with SQL offset.
*
* @param string $where The current $where clause.
* @param WP_Query $query WP_Query object.
* @return string WHERE clause with our pagination added if needed.
*/
public function bulk_indexing_filter_posts_where( $where, $query ) {
global $wpdb;

$using_advanced_pagination = $query->get( 'ep_indexing_advanced_pagination', false );

if ( $using_advanced_pagination ) {
Expand All @@ -161,8 +163,8 @@ public function bulk_indexing_filter_posts_where( $where, $query ) {
}

$range = [
'upper_limit' => "{$GLOBALS['wpdb']->posts}.ID <= {$upper_limit_range_post_id}",
'lower_limit' => "{$GLOBALS['wpdb']->posts}.ID >= {$requested_lower_limit_post_id}",
'upper_limit' => "{$wpdb->posts}.ID <= {$upper_limit_range_post_id}",
'lower_limit' => "{$wpdb->posts}.ID >= {$requested_lower_limit_post_id}",
];

// Skip the end range if it's unnecessary.
Expand Down
Loading
Loading