Extending WP_List_Table / handling checkbox options in plugin administration

I’m working on a WordPress plugin, and part of that plugin requires extending WP_List_Table and storing any of the items which are checked in that table to an option. I’ve managed to figure out how to properly setup and display the required table, but how do I handle storing the checked options?

Here’s what I’ve got so far…

Read More
class TDBar_List_Table extends WP_List_Table {

    // Reference parent constructor
    function __construct() {
        global $status, $page;

        // Set defaults
        parent::__construct( array(
            'singular' => 'theme',
            'plural' => 'themes',
            'ajax' => false
        ));
    }

    // Set table classes
    function get_table_classes() {
        return array('widefat', 'wp-list-table', 'themes');
    }

    // Setup default column
    function column_default($item, $column_name) {
        switch($column_name) {
            case 'Title':
            case 'URI':
            case'Description':
                return $item[$column_name];
            default:
                return print_r($item, true);
        }
    }

    // Displaying checkboxes!
    function column_cb($item) {
        return sprintf(
            '<input type="checkbox" name="%1$s" id="%2$s" value="checked" />',
            //$this->_args['singular'],
            $item['Stylesheet'] . '_status',
            $item['Stylesheet'] . '_status'
        );
    }

    // Display theme title
    function column_title($item) {
        return sprintf(
            '<strong>%1$s</strong>',
            $item['Title']
        );
    }

    // Display theme preview
    function column_preview($item) {
        if (file_exists(get_theme_root() . '/' . $item['Stylesheet'] . '/screenshot.png')) {
            $preview = get_theme_root_uri() . '/' . $item['Stylesheet'] . '/screenshot.png';
        } else {
            $preview = '';
        }
            return sprintf(
                '<a href="%1$s" class="thickbox" title="%2$s"><img src="%3$s" style="width: 150px;" /></a>',
                $preview,
                $item['Title'],
                $preview
            );
    }

    // Display theme description
    function column_description($item) {
        if (isset($item['Version'])) {
            $version = 'Version ' . $item['Version'];
            if (isset($item['Author']) || isset($item['URI']))
                $version .= '&nbsp;|&nbsp;';
        } else {
            $version = '';
        }
        if (isset($item['Author'])) {
            $author = 'By ' . $item['Author'];
            if (isset($item['URI']))
                $author .= '&nbsp;|&nbsp;';
        } else {
            $author = '';
        }
        if (isset($item['URI'])) {
            $uri = $item['URI'];
        } else {
            $uri = '';
        }

        return sprintf(
            '<div class="theme-description"><p>%1$s</p></div><div class="second theme-version-author-uri">%2$s%3$s%4$s',
            $item['Description'],
            $version,
            $author,
            $uri
        );
    }

    // Setup columns
    function get_columns() {
        $columns = array(
            'cb' => '<input type="checkbox" />',
            'title' => 'Theme',
            'preview' => 'Preview',
            'description' => 'Description'
        );
        return $columns;
    }

    // Make title column sortable
    function get_sortable_columns() {
        $sortable_columns = array(
            'title' => array('Title', true)
        );
        return $sortable_columns;
    }

    // Setup bulk actions
    function get_bulk_actions() {
        $actions = array(
            'update' => 'Update'
        );
        return $actions;
    }

    // Handle bulk actions
    function process_bulk_action() {
        // Define our data source
        if (defined('WP_ALLOW_MULTISITE') && WP_ALLOW_MULTISITE == true) {
            $themes = get_allowed_themes();
        } else {
            $themes = get_themes();
        }

        if ('update' === $this->current_action()) {
            foreach ($themes as $theme) {
                if ($theme['Stylesheet'] . '_status' == 'checked') {
                    // Do stuff - here's the problem
                }
            }
        }
    }

    // Handle data preparation
    function prepare_items() {

        // How many records per page?
        $per_page = 10;

        // Define column headers
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();

        // Build the array
        $this->_column_headers = array($columns, $hidden, $sortable);

        // Pass off bulk action
        $this->process_bulk_action();

        // Define our data source
        if (defined('WP_ALLOW_MULTISITE') && WP_ALLOW_MULTISITE == true) {
            $themes = get_allowed_themes();
        } else {
            $themes = get_themes();
        }

        // Handle sorting
        function usort_reorder($a,$b) {
            $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'Title';
            $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
            $result = strcmp($a[$orderby], $b[$orderby]);
            return ($order === 'asc') ? $result : -$result;
        }
        usort($themes, 'usort_reorder');

        //MAIN STUFF HERE
        //for ($i = 0; i < count($themes); $i++) {

        //}

        // Figure out the current page and how many items there are
        $current_page = $this->get_pagenum();
        $total_items = count($themes);

        // Only show the current page
        $themes = array_slice($themes,(($current_page-1)*$per_page),$per_page);

        // Display sorted data
        $this->items = $themes;

        // Register pagination options
        $this->set_pagination_args( array(
            'total_items' => $total_items,
            'per_page' => $per_page,
            'total_pages' => ceil($total_items/$per_page)
        ));
    }
}

Problem is, I can’t get it to save properly. I select the rows I want, hit save and it just resets.

Related posts

Leave a Reply

1 comment

  1. I assume you are talking about the checkboxes in your table listing, so this will be how to process bulk actions.

    All you need to do is add two new methods to your class and initialize it in the prepare_items method. I use the code below in one of my plugins to delete or export, but you can just as easily run an update.

    /**
     * Define our bulk actions
     * 
     * @since 1.2
     * @returns array() $actions Bulk actions
     */
    function get_bulk_actions() {
        $actions = array(
            'delete' => __( 'Delete' , 'visual-form-builder'),
            'export-all' => __( 'Export All' , 'visual-form-builder'),
            'export-selected' => __( 'Export Selected' , 'visual-form-builder')
        );
    
        return $actions;
    }
    
    /**
     * Process our bulk actions
     * 
     * @since 1.2
     */
    function process_bulk_action() {        
        $entry_id = ( is_array( $_REQUEST['entry'] ) ) ? $_REQUEST['entry'] : array( $_REQUEST['entry'] );
    
        if ( 'delete' === $this->current_action() ) {
            global $wpdb;
    
            foreach ( $entry_id as $id ) {
                $id = absint( $id );
                $wpdb->query( "DELETE FROM $this->entries_table_name WHERE entries_id = $id" );
            }
        }
    }
    

    Now, call this method inside prepare_items() like so:

    function prepare_items() {
           //Do other stuff in here
    
           /* Handle our bulk actions */
           $this->process_bulk_action();
    }
    

    There’s a fantastic helper plugin called Custom List Table Example that makes figuring out the WP_List_Table class much easier.