wp_list_table bulk actions not working properly

I’ve been working with the wp_list_table class and creating my custom theme pages with add/edit/delete features on the row options. The problem i am having is with the bulk actions. The row actions are working just fine. Now here is where it gets weird.

If I am looking at my table in admin and I select the checkbox on a few rows, switch to bulk-delete action, then hit apply, I will not get any post data for those checkboxes. What I mean by that is the checkboxes are named as an array bulk-delete[] in html. and if I do a print_r($_request); the bulk-delete key is no present.

Read More

Now when I select a few checkboxes, and this time NOT switch to bulk-delete I just leave it saying “Bulk Actions”, then hit apply, I will get the bulk-delete array but all the keys are empty.

For me totally freaking bazaar. But I am sure there is something really stupid that I missed. So here is the class in it’s entirety. Please let me know what I missed.

[a secondary issue – I’d like to also show an “Country has been added” success message. Could you guys point me in the right direction for knowledge to read up on that]

Thanks in advance.

<?php

class country_class {

var $page_name = "lp-manage-countries";


public function __construct(){
    //make sure the wp_list_table class has been loaded
    if (!class_exists('WP_List_Table')) {
        require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
    }
    add_action( 'admin_post_add_country', array( $this, 'lp_admin_add_country') );
    add_filter('set-screen-option', array( $this, 'lp_save_screen_options') , 10, 3);
    //add_action( 'admin_post_bulk_action', array( $this, 'process_bulk_action') );
}

/**
 * Sets the screen options up for table paging
 */
public function lp_screen_options() {
    $lp_manage_countries_page = "toplevel_page_" . $this->page_name;
    $screen = get_current_screen();
    // get out of here if we are not on our settings page
    if(!is_object($screen) || $screen->id != $lp_manage_countries_page)
        return;
    $args = array(
        'label' => __('Countries per page'),
        'default' => 25,
        'option' => 'countries_per_page'
    );
    add_screen_option( 'per_page', $args );
}

/**
 * Saves the screen option to the object class
 */
function lp_save_screen_options($status, $option, $value) {
    if ( 'countries_per_page' == $option ) return $value;
    return $status;
}

/**
 * Installs the page and screen options
 */
public function install_countries_page(){
    //Add the screen options first
    add_action("load-toplevel_page_" . $this->page_name, array( $this, "lp_screen_options") );
    add_menu_page('LP Countries', 'LP Countries', 'manage_options', 'lp-manage-countries', array($this, 'show_country_page'));
}

public function  lp_admin_add_country(){
    global $wpdb;
    if( isset( $_REQUEST['country_name'] ) and !empty( $_REQUEST['country_name'] )){
        $result = $wpdb->insert(
            'countries',
            array(
                'name' => $_REQUEST['country_name']
            )
        );
        if( $result !== false ){
            wp_redirect(admin_url("admin.php?page=" . $this->page_name) );
            exit;
        }
    }
}

/**
 * Displays the page data
 */
public function show_country_page(){
    if( isset( $_GET['action']) && ( $_REQUEST['action'] == "add" || $_REQUEST['action'] == "edit" )){
        echo "<div class='wrap'>
            <h1>Add Country</h1>
            <form action='" . admin_url("admin-post.php", "http") . "' method='post'>
            <input type="hidden" name="action" value="add_country">
            <table class="form-table">
            <tbody>
            <tr>
            <th scope="row"><label for='country_name' xmlns="http://www.w3.org/1999/html">Country Name:</label></th>
            <td><input id='country_name' required class='regular-text type='text' value='' name='country_name'></input></td>
            </tr>
            </tbody>
            </table>
            <p class='submit'>
            <input id='submit' class='button button-primary' type='submit' value='Save Country' name='submit'></input>
            </p>
            </form>";
    } else {
        echo "<div class="wrap">
            <h1>Manage Countries<a class="page-title-action" href="".admin_url("admin.php?page=".$this->page_name."&action=add")."">Add New</a></h1>
            <form method='post'>";
            //echo "<input type="hidden" name="action" value="bulk_action">";
        //Prepare Table of elements
        $categories_list_table = new category_list_table();
        $categories_list_table->prepare_items();
        //Table of elements
        $categories_list_table->display();
        echo "</form>";
    }
}

/**
 * Creates the database for this page
 */
public function create_countries_table(){
    global $wpdb;
    $charset = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE IF NOT EXISTS `countries` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `name` varchar(45) NOT NULL,
            `parent_id` int(11) DEFAULT NULL,
            `image` varchar(45) DEFAULT NULL,
            PRIMARY KEY (`id`)
            ) $charset; ";

    $wpdb->query( $sql );

}

/**
 * removes the page database when uninstalled
 */
public function drop_countries_table(){
    global $wpdb;
    $sql = "DROP TABLE `countries`;";
    $wpdb->query($sql);
}

}


class category_list_table extends WP_List_Table {

public function __construct(){
    parent::__construct( array(
        'singular' => 'Country',
        'plural' => 'Countries',
            'ajax' => false)
    );
}

public function get_columns(){
    return $columns = array(
        'cb'   => '<input name="bulk-delete[]" type="checkbox" />',
        'name' => __('Name'),
        'parent_id' => __('Parent ID'),
        'image' => __('Image')
    );
}

function column_name($item) {
    // create a nonce
    $delete_nonce = wp_create_nonce( 'lp_delete_country' );
    $edit_nonce = wp_create_nonce( 'lp_delete_country' );
    $actions = array(
        'edit' => sprintf('<a href="?page=%s&action=%s&country=%s&_wpnonce=%s">Edit</a>', $_REQUEST['page'], 'edit', $item['id'], $edit_nonce),
        'delete' => sprintf('<a href="?page=%s&action=%s&country=%s&_wpnonce=%s">Delete</a>', $_REQUEST['page'], 'delete', $item['id'], $delete_nonce),
    );
    return sprintf('%1$s %2$s', $item['name'], $this->row_actions($actions) );
}

public function get_sortable_columns(){
    return $sortable = array(
        'id' => array('id',false),
        'name' => array('name',false),
        'parent_id' => array('parent_id', false),
        'image' => array('image', false)
    );
}

public function get_hidden_columns( ){
    $screen = get_current_screen();

    if ( is_string( $screen ) )
        $screen = convert_to_screen( $screen );

    return (array) get_user_option( 'manage' . $screen->id . 'columnshidden' );
}

public function prepare_items(){
    global $wpdb, $_wp_column_headers;

    $screen = get_current_screen();

    /** Process bulk action */
    $this->process_bulk_action();

    /* Prepare the query */
    $query = "SELECT * FROM `countries`";

    /* Order Parameters */
    $orderby = !empty($_GET["orderby"]) ? mysql_real_escape_string($_GET["orderby"]) : 'ASC';
    $order = !empty($_GET["order"]) ? mysql_real_escape_string($_GET["order"]) : '';
    if(!empty($orderby) & !empty($order)){ $query.=' ORDER BY '.$orderby.' '.$order; }

    /* Pagination Params */
    //Number of elements in your table?
    $totalitems = $wpdb->query($query); //return the total number of affected rows

    //How many to display per page?
    $perpage = get_user_meta( get_current_user_id() , 'countries_per_page', true);

    if( empty($perpage)){
        $perpage = 25;
    }

    //Which page is this?
    $paged = !empty($_GET["paged"]) ? mysql_real_escape_string($_GET["paged"]) : '';

    //Page Number
    if(empty($paged) || !is_numeric($paged) || $paged<=0 ){ $paged=1; }

    //How many pages do we have in total?
    $totalpages = ceil($totalitems/$perpage);

    //adjust the query to take pagination into account
    if(!empty($paged) && !empty($perpage)){
        $offset=($paged-1)*$perpage;
        $query.=' LIMIT '.(int)$offset.','.(int)$perpage;
    }

    /* Register pagination */
    $this->set_pagination_args( array(
        "total_items" => $totalitems,
        "total_pages" => $totalpages,
        "per_page" => $perpage
    )
    );

    /* register the columns */
    $columns = $this->get_columns();
    $_wp_column_headers[$screen->id]=$columns;

    /* Get the items */
    $this->items = $wpdb->get_results($query, 'ARRAY_A');

    $hidden_columns = $this->get_hidden_columns();
    $sortable_columns = $this->get_sortable_columns();
    parent::get_column_info();
    $this->_column_headers = array( $columns, $hidden_columns, $sortable_columns);
}

public function column_default($item, $column_name) {
    //return $item[$column_name];
    switch ( $column_name ) {
        case 'cb':
        case 'name':
        case 'parent_id':
        case 'image':
            return $item[ $column_name ];
        default:
            return $item[ $column_name ];
    }
}

function no_items() {
    _e( 'No Countries Found.' );
}

function column_cb( $item ) {
    return sprintf(
        '<input type="checkbox" name="bulk-delete[]" value="%s" />', $item['ID']
    );
}

public function get_bulk_actions() {
    $actions = [
        'bulk-delete' => 'Delete'
    ];
    return $actions;
}

public function process_bulk_action() {

    $action = $this->current_action();
    echo "action is [" . $action . "]";
    if( !empty( $action ) ){

        switch ($action){
            case 'delete':
                // In our file that handles the request, verify the nonce.
                $nonce = esc_attr( $_REQUEST['_wpnonce'] );

                if ( ! wp_verify_nonce( $nonce, 'lp_delete_country' ) ) {
                    die( 'Go get a life script kiddies' );
                } else {
                    echo " running delete";
                    self::delete_country( absint( $_GET['country'] ) );
                    wp_redirect( esc_url( add_query_arg() ) );
                    exit;
                }
            case 'edit':
                echo "we should be editing";
            case 'bulk-delete':
                // If the delete bulk action is triggered
                echo "we triggered a bulk delete";
                echo "<pre>";
                print_r( $_REQUEST );
                echo "</pre>";
                if ( !empty( $_POST['bulk-delete'] ) ) {

                    $delete_ids = esc_sql( $_POST['bulk-delete'] );

                    // loop over the array of record IDs and delete them
                    foreach ( $delete_ids as $id ) {
                        $this->delete_country( $id );

                    }

                    wp_redirect( esc_url( add_query_arg() ) );
                    exit;
                } else {
                    echo "Fucking empty";
                }

            default:
                echo "<pre>";
                print_r( $_REQUEST );
                echo "</pre>";
                //quietly exit;
        }
    } else {
        echo "<pre>";
        print_r( $_REQUEST );
        echo "</pre>";
    }
}

function delete_country( $id ) {
    global $wpdb;
    $wpdb->delete(
        "countries",
        [ 'id' => $id ]
    );
}

}

Related posts