Logging: Fix pagination and filtering on DB log list table (#41870)

Fixes some issues where pagination and filters were not persisting in the DB log list table view after running a bulk action. Also adds a way to customize the number of log entries shown per page.

Fixes #39359
This commit is contained in:
Corey McKrill 2023-12-11 12:27:26 -08:00 committed by GitHub
parent a4bbdffd31
commit 44ab680fe1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 120 additions and 35 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Fix problems with pagination and filtering for the database logger list table view

View File

@ -17,6 +17,12 @@ if ( ! class_exists( 'WP_List_Table' ) ) {
}
class WC_Admin_Log_Table_List extends WP_List_Table {
/**
* The key for the user option of how many list table items to display per page.
*
* @const string
*/
public const PER_PAGE_USER_OPTION_KEY = 'woocommerce_status_log_items_per_page';
/**
* Initialize the log table list.
@ -330,7 +336,10 @@ class WC_Admin_Log_Table_List extends WP_List_Table {
$this->prepare_column_headers();
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
$per_page = $this->get_items_per_page(
self::PER_PAGE_USER_OPTION_KEY,
$this->get_per_page_default()
);
$where = $this->get_items_query_where();
$order = $this->get_items_query_order();
@ -367,7 +376,11 @@ class WC_Admin_Log_Table_List extends WP_List_Table {
protected function get_items_query_limit() {
global $wpdb;
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
$per_page = $this->get_items_per_page(
self::PER_PAGE_USER_OPTION_KEY,
$this->get_per_page_default()
);
return $wpdb->prepare( 'LIMIT %d', $per_page );
}
@ -381,7 +394,10 @@ class WC_Admin_Log_Table_List extends WP_List_Table {
protected function get_items_query_offset() {
global $wpdb;
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
$per_page = $this->get_items_per_page(
self::PER_PAGE_USER_OPTION_KEY,
$this->get_per_page_default()
);
$current_page = $this->get_pagenum();
if ( 1 < $current_page ) {
$offset = $per_page * ( $current_page - 1 );
@ -457,4 +473,13 @@ class WC_Admin_Log_Table_List extends WP_List_Table {
$this->get_sortable_columns(),
);
}
/**
* Helper to get the default value for the per_page arg.
*
* @return int
*/
public function get_per_page_default(): int {
return 20;
}
}

View File

@ -326,6 +326,7 @@ class WC_Admin_Menus {
'woocommerce_webhooks_per_page',
FileListTable::PER_PAGE_USER_OPTION_KEY,
SearchListTable::PER_PAGE_USER_OPTION_KEY,
WC_Admin_Log_Table_List::PER_PAGE_USER_OPTION_KEY,
);
if ( in_array( $option, $screen_options, true ) ) {

View File

@ -15,6 +15,12 @@ defined( 'ABSPATH' ) || exit;
* WC_Admin_Status Class.
*/
class WC_Admin_Status {
/**
* An instance of the DB log handler list table.
*
* @var WC_Admin_Log_Table_List
*/
private static $db_log_list_table;
/**
* Handles output of the reports page in admin.
@ -133,15 +139,17 @@ class WC_Admin_Status {
* Show the log page contents for db log handler.
*/
public static function status_logs_db() {
if ( ! empty( $_REQUEST['flush-logs'] ) ) { // WPCS: input var ok, CSRF ok.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce handled in flush_db_logs().
if ( isset( $_REQUEST['flush-logs'] ) ) {
self::flush_db_logs();
}
if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['log'] ) ) { // WPCS: input var ok, CSRF ok.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce handled in log_table_bulk_actions().
if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['log'] ) ) {
self::log_table_bulk_actions();
}
$log_table_list = new WC_Admin_Log_Table_List();
$log_table_list = self::get_db_log_list_table();
$log_table_list->prepare_items();
include_once __DIR__ . '/views/html-admin-page-status-logs-db.php';
@ -306,20 +314,38 @@ class WC_Admin_Status {
exit();
}
/**
* Return a stored instance of the DB log list table class.
*
* @return WC_Admin_Log_Table_List
*/
public static function get_db_log_list_table() {
if ( is_null( self::$db_log_list_table ) ) {
self::$db_log_list_table = new WC_Admin_Log_Table_List();
}
return self::$db_log_list_table;
}
/**
* Clear DB log table.
*
* @since 3.0.0
*/
private static function flush_db_logs() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-status-logs' ) ) { // WPCS: input var ok, sanitization ok.
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
check_admin_referer( 'bulk-logs' );
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to manage log entries.', 'woocommerce' ) );
}
WC_Log_Handler_DB::flush();
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
exit();
$sendback = wp_sanitize_redirect( admin_url( 'admin.php?page=wc-status&tab=logs' ) );
wp_safe_redirect( $sendback );
exit;
}
/**
@ -328,15 +354,22 @@ class WC_Admin_Status {
* @since 3.0.0
*/
private static function log_table_bulk_actions() {
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-status-logs' ) ) { // WPCS: input var ok, sanitization ok.
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
check_admin_referer( 'bulk-logs' );
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'You do not have permission to manage log entries.', 'woocommerce' ) );
}
$log_ids = array_map( 'absint', (array) isset( $_REQUEST['log'] ) ? wp_unslash( $_REQUEST['log'] ) : array() ); // WPCS: input var ok, sanitization ok.
$log_ids = (array) filter_input( INPUT_GET, 'log', FILTER_CALLBACK, array( 'options' => 'absint' ) );
if ( ( isset( $_REQUEST['action'] ) && 'delete' === $_REQUEST['action'] ) || ( isset( $_REQUEST['action2'] ) && 'delete' === $_REQUEST['action2'] ) ) { // WPCS: input var ok, sanitization ok.
$action = self::get_db_log_list_table()->current_action();
if ( 'delete' === $action ) {
WC_Log_Handler_DB::delete( $log_ids );
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
$sendback = remove_query_arg( array( 'action', 'action2', 'log', '_wpnonce', '_wp_http_referer' ), wp_get_referer() );
wp_safe_redirect( $sendback );
exit();
}
}

View File

@ -9,16 +9,29 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$delete_confirmation_js = sprintf(
"return window.confirm( '%s' )",
esc_js( __( 'Are you sure you want to clear all logs from the database?', 'woocommerce' ) )
);
?>
<form method="post" id="mainform" action="">
<?php $log_table_list->search_box( __( 'Search logs', 'woocommerce' ), 'log' ); ?>
<?php $log_table_list->display(); ?>
<form method="get" id="mainform">
<input type="hidden" name="page" value="wc-status" />
<input type="hidden" name="tab" value="logs" />
<?php submit_button( __( 'Flush all logs', 'woocommerce' ), 'delete', 'flush-logs' ); ?>
<?php wp_nonce_field( 'woocommerce-status-logs' ); ?>
<?php $log_table_list->search_box( __( 'Search logs', 'woocommerce' ), 'log' ); ?>
<?php $log_table_list->display(); ?>
<?php
submit_button(
__( 'Flush all logs', 'woocommerce' ),
'delete',
'flush-logs',
true,
array(
'onclick' => esc_attr( $delete_confirmation_js ),
)
);
?>
</form>
<script>
document.addEventListener( 'DOMContentLoaded', function() {
@ -49,12 +62,3 @@ if ( ! defined( 'ABSPATH' ) ) {
} );
} );
</script>
<?php
wc_enqueue_js(
"jQuery( '#flush-logs' ).on( 'click', function() {
if ( window.confirm('" . esc_js( __( 'Are you sure you want to clear all logs from the database?', 'woocommerce' ) ) . "') ) {
return true;
}
return false;
});"
);

View File

@ -4,11 +4,13 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Internal\Admin\Logging;
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Admin\Logging\LogHandlerFileV2;
use Automattic\WooCommerce\Internal\Admin\Logging\FileV2\{ FileController, FileListTable, SearchListTable };
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
use WC_Admin_Status;
use WP_List_Table;
use WC_Log_Handler_File, WC_Log_Handler_DB;
use WC_Log_Levels;
use WP_List_Table;
/**
* PageController class.
@ -82,7 +84,7 @@ class PageController {
$handler = Constants::get_constant( 'WC_LOG_HANDLER' );
if ( is_null( $handler ) || ! class_exists( $handler ) ) {
$handler = \WC_Log_Handler_File::class;
$handler = WC_Log_Handler_File::class;
}
return $handler;
@ -424,11 +426,22 @@ class PageController {
* @return void
*/
private function setup_screen_options(): void {
$params = $this->get_query_params( array( 'view' ) );
$params = $this->get_query_params( array( 'view' ) );
$handler = $this->get_default_handler();
$list_table = null;
if ( in_array( $params['view'], array( 'list_files', 'search_results' ), true ) ) {
$list_table = $this->get_list_table( $params['view'] );
switch ( $handler ) {
case LogHandlerFileV2::class:
if ( in_array( $params['view'], array( 'list_files', 'search_results' ), true ) ) {
$list_table = $this->get_list_table( $params['view'] );
}
break;
case 'WC_Log_Handler_DB':
$list_table = WC_Admin_Status::get_db_log_list_table();
break;
}
if ( $list_table instanceof WP_List_Table ) {
// Ensure list table columns are initialized early enough to enable column hiding, if available.
$list_table->prepare_column_headers();
@ -448,6 +461,11 @@ class PageController {
* @return void
*/
private function handle_list_table_bulk_actions(): void {
// Bail if we're not using the file handler.
if ( LogHandlerFileV2::class !== $this->get_default_handler() ) {
return;
}
$params = $this->get_query_params( array( 'file_id', 'view' ) );
// Bail if this is not the list table view.