Performance: Support pagination to avoid double queries to search webhooks

This commit is contained in:
Mike Jolley 2019-02-18 14:58:32 +00:00
parent 4b3c1660f1
commit 71d3121872
5 changed files with 82 additions and 87 deletions

View File

@ -297,22 +297,19 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
$args['search'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // WPCS: input var okay, CSRF ok.
}
$args['paginate'] = true;
// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks( $args );
$this->items = array_map( 'wc_get_webhook', $webhooks );
// Get total items.
$args['limit'] = -1;
$args['offset'] = 0;
$total_items = count( $data_store->search_webhooks( $args ) );
$this->items = array_map( 'wc_get_webhook', $webhooks->webhooks );
// Set the pagination.
$this->set_pagination_args(
array(
'total_items' => $total_items,
'total_items' => $webhooks->total,
'per_page' => $per_page,
'total_pages' => ceil( $total_items / $per_page ),
'total_pages' => $webhooks->max_num_pages,
)
);
}

View File

@ -326,21 +326,6 @@ class WC_API_Webhooks extends WC_API_Resource {
return $webhook->delete( true );
}
/**
* Get webhooks total results
*
* @since 3.3.0
* @param array $args Request arguments for filtering query.
* @return array
*/
private function get_webhooks_total_results( $args = array() ) {
$data_store = WC_Data_Store::load( 'webhook' );
$args['limit'] = -1;
$args['offset'] = 0;
return count( $data_store->search_webhooks( $args ) );
}
/**
* Helper method to get webhook post objects
*
@ -390,6 +375,8 @@ class WC_API_Webhooks extends WC_API_Resource {
unset( $args['date_query'] );
}
$args['paginate'] = true;
// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$results = $data_store->search_webhooks( $args );
@ -397,12 +384,12 @@ class WC_API_Webhooks extends WC_API_Resource {
// Get total items.
$headers = new stdClass;
$headers->page = $page;
$headers->total = $this->get_webhooks_total_results( $args );
$headers->total = $results->total;
$headers->is_single = $args['limit'] > $headers->total;
$headers->total_pages = ceil( $headers->total / $args['limit'] );
$headers->total_pages = $results->max_num_pages;
return array(
'results' => $results,
'results' => $results->webhooks,
'headers' => $headers,
);
}

View File

@ -326,21 +326,6 @@ class WC_API_Webhooks extends WC_API_Resource {
return $webhook->delete( true );
}
/**
* Get webhooks total results
*
* @since 3.3.0
* @param array $args Request arguments for filtering query.
* @return array
*/
private function get_webhooks_total_results( $args = array() ) {
$data_store = WC_Data_Store::load( 'webhook' );
$args['limit'] = -1;
$args['offset'] = 0;
return count( $data_store->search_webhooks( $args ) );
}
/**
* Helper method to get webhook post objects
*
@ -390,6 +375,8 @@ class WC_API_Webhooks extends WC_API_Resource {
unset( $args['date_query'] );
}
$args['paginate'] = true;
// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$results = $data_store->search_webhooks( $args );
@ -397,12 +384,12 @@ class WC_API_Webhooks extends WC_API_Resource {
// Get total items.
$headers = new stdClass;
$headers->page = $page;
$headers->total = $this->get_webhooks_total_results( $args );
$headers->total = $results->total;
$headers->is_single = $args['limit'] > $headers->total;
$headers->total_pages = ceil( $headers->total / $args['limit'] );
$headers->total_pages = $results->max_num_pages;
return array(
'results' => $results,
'results' => $results->webhooks,
'headers' => $headers,
);
}

View File

@ -247,32 +247,29 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller {
*/
$prepared_args = apply_filters( 'woocommerce_rest_webhook_query', $args, $request );
unset( $prepared_args['page'] );
$prepared_args['paginate'] = true;
// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$results = $data_store->search_webhooks( $prepared_args );
$webhooks = array();
$data_store = WC_Data_Store::load( 'webhook' );
$results = $data_store->search_webhooks( $prepared_args );
$webhook_ids = $results->webhooks;
$webhooks = array();
foreach ( $results as $webhook_id ) {
foreach ( $webhook_ids as $webhook_id ) {
$data = $this->prepare_item_for_response( $webhook_id, $request );
$webhooks[] = $this->prepare_response_for_collection( $data );
}
$response = rest_ensure_response( $webhooks );
$response = rest_ensure_response( $webhooks );
$per_page = (int) $prepared_args['limit'];
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
$total_webhooks = $results->total;
$max_pages = $results->max_num_pages;
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
// Store pagination values for headers then unset for count query.
$per_page = (int) $prepared_args['limit'];
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
$response->header( 'X-WP-Total', $total_webhooks );
$response->header( 'X-WP-TotalPages', $max_pages );
// Calculate totals.
$prepared_args['limit'] = -1;
$prepared_args['offset'] = 0;
$total_webhooks = count( $data_store->search_webhooks( $prepared_args ) );
$response->header( 'X-WP-Total', (int) $total_webhooks );
$max_pages = ceil( $total_webhooks / $per_page );
$response->header( 'X-WP-TotalPages', (int) $max_pages );
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
if ( $page > 1 ) {
$prev_page = $page - 1;
if ( $prev_page > $max_pages ) {

View File

@ -233,7 +233,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
* Search webhooks.
*
* @param array $args Search arguments.
* @return array
* @return array|object
*/
public function search_webhooks( $args ) {
global $wpdb;
@ -241,10 +241,11 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
$args = wp_parse_args(
$args,
array(
'limit' => 10,
'offset' => 0,
'order' => 'DESC',
'orderby' => 'id',
'limit' => 10,
'offset' => 0,
'order' => 'DESC',
'orderby' => 'id',
'paginate' => false,
)
);
@ -306,33 +307,59 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
}
// Check for cache.
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
$ids = wp_cache_get( $cache_key, 'webhook_search_results' );
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
$cache_value = wp_cache_get( $cache_key, 'webhook_search_results' );
if ( false !== $ids ) {
return $ids;
if ( $cache_value ) {
return $cache_value;
}
$query = trim(
"SELECT webhook_id
FROM {$wpdb->prefix}wc_webhooks
WHERE 1=1
{$status}
{$search}
{$include}
{$exclude}
{$date_created}
{$date_modified}
{$order}
{$limit}
{$offset}"
);
if ( $args['paginate'] ) {
$query = trim(
"SELECT SQL_CALC_FOUND_ROWS webhook_id
FROM {$wpdb->prefix}wc_webhooks
WHERE 1=1
{$status}
{$search}
{$include}
{$exclude}
{$date_created}
{$date_modified}
{$order}
{$limit}
{$offset}"
);
$ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$total = (int) $wpdb->get_var( 'SELECT FOUND_ROWS();' );
$return_value = (object) array(
'webhooks' => $webhook_ids,
'total' => $total,
'max_num_pages' => $args['limit'] > 1 ? ceil( $total / $args['limit'] ) : 1,
);
} else {
$query = trim(
"SELECT webhook_id
FROM {$wpdb->prefix}wc_webhooks
WHERE 1=1
{$status}
{$search}
{$include}
{$exclude}
{$date_created}
{$date_modified}
{$order}
{$limit}
{$offset}"
);
wp_cache_set( $cache_key, $ids, 'webhook_search_results' );
$webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$return_value = $webhook_ids;
}
return $ids;
wp_cache_set( $cache_key, $return_value, 'webhook_search_results' );
return $return_value;
}
/**