Add bulk delete action to list table

This commit is contained in:
Corey McKrill 2023-10-18 16:03:55 -07:00
parent 8d21f645e7
commit 4fff634b6b
No known key found for this signature in database
GPG Key ID: 84BBFE669C4D97B8
4 changed files with 166 additions and 40 deletions

View File

@ -118,4 +118,13 @@ class File {
return filesize( $this->path );
}
/**
* Delete the file from the filesystem.
*
* @return bool
*/
public function delete() {
return @unlink( $this->path );
}
}

View File

@ -9,6 +9,17 @@ use WP_Error;
* FileController class.
*/
class FileController {
/**
* @const array Default values for arguments for the get_files method.
*/
public const DEFAULTS_GET_FILES = array(
'offset' => 0,
'order' => 'desc',
'orderby' => 'modified',
'per_page' => 20,
'source' => '',
);
/**
* @var string The absolute path to the log directory.
*/
@ -38,14 +49,7 @@ class FileController {
* @return File[]|int|WP_Error
*/
public function get_files( array $args = array(), bool $count_only = false ) {
$defaults = array(
'offset' => 0,
'order' => 'desc',
'orderby' => 'modified',
'per_page' => 10,
'source' => '',
);
$args = wp_parse_args( $args, $defaults );
$args = wp_parse_args( $args, self::DEFAULTS_GET_FILES );
$pattern = $args['source'] . '*' . '.log';
$files = glob( $this->log_directory . $pattern );
@ -159,4 +163,26 @@ class FileController {
return array_unique( $all_sources );
}
/**
* Delete one or more files from the filesystem.
*
* @param array $files An array of file basenames (filename without the path).
*
* @return int
*/
public function delete_files( $files ) {
$deleted = 0;
foreach ( $files as $basename ) {
$file = new File( $this->log_directory . $basename );
$result = $file->delete();
if ( true === $result ) {
$deleted ++;
}
}
return $deleted;
}
}

View File

@ -25,11 +25,6 @@ class ListTable extends WP_List_Table {
*/
private $page_controller;
/**
* @var array
*/
private $file_args = array();
/**
* ListTable class.
*/
@ -46,19 +41,6 @@ class ListTable extends WP_List_Table {
);
}
/**
* Set file args for later use, since `prepare_items` can't take any parameters.
*
* @param array $args
*
* @return void
*/
public function set_file_args( $args ) {
if ( is_array( $args ) ) {
$this->file_args = $args;
}
}
/**
* Render message when there are no items.
*
@ -68,6 +50,17 @@ class ListTable extends WP_List_Table {
esc_html_e( 'No log files found.', 'woocommerce' );
}
/**
* Retrieves the list of bulk actions available for this table.
*
* @return array
*/
protected function get_bulk_actions() {
return array(
'delete' => __( 'Delete permanently', 'woocommerce' ),
);
}
/**
* Get the existing log sources for the filter dropdown.
*
@ -103,7 +96,17 @@ class ListTable extends WP_List_Table {
</option>
<?php endforeach; ?>
</select>
<?php submit_button( __( 'Filter', 'woocommerce' ), '', 'filter_action', false, array( 'id' => 'logs-filter-submit' ) ); ?>
<?php
submit_button(
__( 'Filter', 'woocommerce' ),
'',
'filter_action',
false,
array(
'id' => 'logs-filter-submit',
)
);
?>
<?php endif; ?>
</div>
<?php
@ -129,15 +132,27 @@ class ListTable extends WP_List_Table {
* @return void
*/
public function prepare_items() {
$per_page = $this->get_items_per_page( self::PER_PAGE_USER_OPTION_KEY );
$per_page = $this->get_items_per_page(
self::PER_PAGE_USER_OPTION_KEY,
$this->file_controller::DEFAULTS_GET_FILES['per_page']
);
$defaults = array(
'per_page' => $per_page,
'offset' => ( $this->get_pagenum() - 1 ) * $per_page,
);
$file_args = wp_parse_args( $this->file_args, $defaults );
$file_args = wp_parse_args( $this->page_controller->get_query_params(), $defaults );
$total_items = $this->file_controller->get_files( $file_args, true );
if ( is_wp_error( $total_items ) ) {
printf(
'<div class="notice notice-warning"><p>%s</p></div>',
esc_html( $total_items->get_error_message() )
);
return;
}
$total_pages = ceil( $total_items / $per_page );
$items = $this->file_controller->get_files( $file_args );
@ -198,9 +213,20 @@ class ListTable extends WP_List_Table {
<input
id="cb-select-<?php echo esc_attr( $item->get_key() ); ?>"
type="checkbox"
name="id[]"
value="<?php echo esc_attr( $item->get_key() ); ?>"
name="file[]"
value="<?php echo esc_attr( $item->get_basename() ); ?>"
/>
<label for="cb-select-<?php echo esc_attr( $item->get_key() ); ?>">
<span class="screen-reader-text">
<?php
printf(
esc_html__( 'Select the %1$s log file for %2$s', 'woocommerce' ),
esc_html( date( get_option( 'date_format' ), $item->get_created_timestamp() ) ),
esc_html( $item->get_source() )
);
?>
</span>
</label>
<?php
return ob_get_clean();
}

View File

@ -46,6 +46,7 @@ class PageController {
*/
private function init_hooks() {
self::add_action( 'load-woocommerce_page_wc-status', array( $this, 'setup_screen_options' ) );
self::add_action( 'load-woocommerce_page_wc-status', array( $this, 'handle_list_table_bulk_actions' ) );
}
/**
@ -130,17 +131,20 @@ class PageController {
$defaults = $this->get_query_param_defaults();
$params = $this->get_query_params();
$this->get_list_table()->set_file_args( $params );
$this->get_list_table()->prepare_items();
?>
<form id="logs-filter" method="get">
<form id="logs-list-table-form" method="get">
<input type="hidden" name="page" value="wc-status" />
<input type="hidden" name="tab" value="logs" />
<?php foreach ( $params as $key => $value ) : ?>
<?php if ( $value !== $defaults[ $key ] ) : ?>
<input type="hidden" name="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $value ); ?>" />
<input
type="hidden"
name="<?php echo esc_attr( $key ); ?>"
value="<?php echo esc_attr( $value ); ?>"
/>
<?php endif; ?>
<?php endforeach; ?>
<?php $this->get_list_table()->prepare_items(); ?>
<?php $this->get_list_table()->display(); ?>
</form>
<?php
@ -151,12 +155,12 @@ class PageController {
*
* @return string[]
*/
private function get_query_param_defaults() {
public function get_query_param_defaults() {
return array(
'order' => $this->file_controller::DEFAULTS_GET_FILES['order'],
'orderby' => $this->file_controller::DEFAULTS_GET_FILES['orderby'],
'source' => $this->file_controller::DEFAULTS_GET_FILES['source'],
'view' => 'list_files',
'orderby' => 'modified',
'order' => 'desc',
'source' => '',
);
}
@ -165,7 +169,7 @@ class PageController {
*
* @return array
*/
private function get_query_params() {
public function get_query_params() {
$defaults = $this->get_query_param_defaults();
$params = filter_input_array(
INPUT_GET,
@ -236,4 +240,65 @@ class PageController {
);
}
}
/**
* Process bulk actions initiated from the log file list table.
*
* @return void
*/
private function handle_list_table_bulk_actions() {
$action = $this->get_list_table()->current_action();
if ( $action ) {
check_admin_referer( 'bulk-log-files' );
$sendback = remove_query_arg( array( 'deleted' ), wp_get_referer() );
$files = filter_input( INPUT_GET, 'file', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
if ( ! is_array( $files ) || count( $files ) < 1 ) {
wp_safe_redirect( $sendback );
}
switch ( $action ) {
case 'delete':
$deleted = $this->file_controller->delete_files( $files );
$sendback = add_query_arg( 'deleted', $deleted, $sendback );
break;
}
$sendback = remove_query_arg( array( 'action', 'action2' ), $sendback );
wp_safe_redirect( $sendback );
exit;
} elseif ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
$removable_args = array( '_wp_http_referer', '_wpnonce', 'action', 'action2', 'filter_action' );
wp_safe_redirect( remove_query_arg( $removable_args, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
exit;
}
$deleted = filter_input( INPUT_GET, 'deleted', FILTER_VALIDATE_INT );
if ( is_numeric( $deleted ) ) {
add_action(
'admin_notices',
function() use ( $deleted ) {
?>
<div class="notice notice-info is-dismissible">
<p>
<?php
printf(
// translators: %s is a number of files.
esc_html( _n( '%s log file deleted.', '%s log files deleted.', $deleted, 'woocommerce' ) ),
number_format_i18n( $deleted )
);
?>
</p>
</div>
<?php
}
);
}
$_SERVER['REQUEST_URI'] = remove_query_arg( array( 'deleted' ), wp_unslash( $_SERVER['REQUEST_URI'] ) );
}
}