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 ); 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. * FileController class.
*/ */
class FileController { 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. * @var string The absolute path to the log directory.
*/ */
@ -38,14 +49,7 @@ class FileController {
* @return File[]|int|WP_Error * @return File[]|int|WP_Error
*/ */
public function get_files( array $args = array(), bool $count_only = false ) { public function get_files( array $args = array(), bool $count_only = false ) {
$defaults = array( $args = wp_parse_args( $args, self::DEFAULTS_GET_FILES );
'offset' => 0,
'order' => 'desc',
'orderby' => 'modified',
'per_page' => 10,
'source' => '',
);
$args = wp_parse_args( $args, $defaults );
$pattern = $args['source'] . '*' . '.log'; $pattern = $args['source'] . '*' . '.log';
$files = glob( $this->log_directory . $pattern ); $files = glob( $this->log_directory . $pattern );
@ -159,4 +163,26 @@ class FileController {
return array_unique( $all_sources ); 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; private $page_controller;
/**
* @var array
*/
private $file_args = array();
/** /**
* ListTable class. * 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. * 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' ); 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. * Get the existing log sources for the filter dropdown.
* *
@ -103,7 +96,17 @@ class ListTable extends WP_List_Table {
</option> </option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </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; ?> <?php endif; ?>
</div> </div>
<?php <?php
@ -129,15 +132,27 @@ class ListTable extends WP_List_Table {
* @return void * @return void
*/ */
public function prepare_items() { 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( $defaults = array(
'per_page' => $per_page, 'per_page' => $per_page,
'offset' => ( $this->get_pagenum() - 1 ) * $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 ); $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 ); $total_pages = ceil( $total_items / $per_page );
$items = $this->file_controller->get_files( $file_args ); $items = $this->file_controller->get_files( $file_args );
@ -198,9 +213,20 @@ class ListTable extends WP_List_Table {
<input <input
id="cb-select-<?php echo esc_attr( $item->get_key() ); ?>" id="cb-select-<?php echo esc_attr( $item->get_key() ); ?>"
type="checkbox" type="checkbox"
name="id[]" name="file[]"
value="<?php echo esc_attr( $item->get_key() ); ?>" 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 <?php
return ob_get_clean(); return ob_get_clean();
} }

View File

@ -46,6 +46,7 @@ class PageController {
*/ */
private function init_hooks() { 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, '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(); $defaults = $this->get_query_param_defaults();
$params = $this->get_query_params(); $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="page" value="wc-status" />
<input type="hidden" name="tab" value="logs" /> <input type="hidden" name="tab" value="logs" />
<?php foreach ( $params as $key => $value ) : ?> <?php foreach ( $params as $key => $value ) : ?>
<?php if ( $value !== $defaults[ $key ] ) : ?> <?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 endif; ?>
<?php endforeach; ?> <?php endforeach; ?>
<?php $this->get_list_table()->prepare_items(); ?>
<?php $this->get_list_table()->display(); ?> <?php $this->get_list_table()->display(); ?>
</form> </form>
<?php <?php
@ -151,12 +155,12 @@ class PageController {
* *
* @return string[] * @return string[]
*/ */
private function get_query_param_defaults() { public function get_query_param_defaults() {
return array( 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', 'view' => 'list_files',
'orderby' => 'modified',
'order' => 'desc',
'source' => '',
); );
} }
@ -165,7 +169,7 @@ class PageController {
* *
* @return array * @return array
*/ */
private function get_query_params() { public function get_query_params() {
$defaults = $this->get_query_param_defaults(); $defaults = $this->get_query_param_defaults();
$params = filter_input_array( $params = filter_input_array(
INPUT_GET, 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'] ) );
}
} }