0

I’m developing a WordPress plugin where the goal/ action is to manipulate data in the wp_usermeta table, by extending the WP_List_Table class, and using it in the WPPB.me boilerplate. I’ve been able to get my table to work outside of the boilerplate, for example, if I just put my action functions in the same “wp-list-table-example-page.php”, after the code for the extended class itself. But, I want to use the boilerplate where the _REQUEST’s would be sent to separate pages in the ./partials folder (assuming that’s the correct way). I have both row and bulk actions included by extending the WP_List_Table class. I’m stuck on getting the actions to function properly; to load the custom ./partials pages I created in the boilerplate to perform the requested actions when either a row is clicked, or the bulk action drop down is used with checkboxes in a table column.

Here’s what I’m working with in the file: (edit: fixed file path for clarity) http URL is: www/zapper/wp-admin/admin.php?page=zapper-table

<?php // ./wp-content/plugins/zapper/includes/class-zapper-list-table.php :



if(!defined('PLUGIN_TEXT_DOMAIN')){
    define('PLUGIN_TEXT_DOMAIN', 'zapper');
}

if(!class_exists('WP_List_Table')){
    require_once( ABSPATH . 'wp-admin/includes/screen.php' );
    require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}

class Zapper_List_Table extends WP_List_Table
{

   /* other extended WP_List_Table stuff withheld  */ 
    function get_bulk_actions()
    {
        $actions = array(
            'view_all'    => __('View Multi', 'PLUGIN_TEXT_DOMAIN'),
            'edit_all' => __('Edit Multi', 'PLUGIN_TEXT_DOMAIN')
        );
        return $actions;
    }

    public function handle_table_actions() {
        
        // check for row actions
        $the_table_action = $this->current_action();
        
        if ( 'view_meta' === $the_table_action ) {
            $nonce = wp_unslash( $_REQUEST['_wpnonce'] );
            // verify the nonce.
            if ( ! wp_verify_nonce( $nonce, 'view_meta_nonce' ) ) {
                $this->invalid_nonce_redirect();
            }
            else {                    
                $this->page_view_meta( absint( $_REQUEST['user_id']) );
                $this->graceful_exit();
            }
        }
        
        if ( 'add_meta' === $the_table_action ) {
            $nonce = wp_unslash( $_REQUEST['_wpnonce'] );
            // verify the nonce.
            if ( ! wp_verify_nonce( $nonce, 'add_meta_nonce' ) ) {
                $this->invalid_nonce_redirect();
            }
            else {                    
                $this->page_add_meta( absint( $_REQUEST['user_id']) );
                $this->graceful_exit();
            }
        }
        
        // check for bulk actions
        if ( ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'bulk-edit' ) || ( isset( $_REQUEST['action2'] ) && $_REQUEST['action2'] === 'bulk-edit' ) ) {
            
            $nonce = wp_unslash( $_REQUEST['_wpnonce'] );
            // verify the nonce.
            
            if ( ! wp_verify_nonce( $nonce, 'bulk-users' ) ) {
                $this->invalid_nonce_redirect();
            }
            else {
                $this->page_bulk_edit( $_REQUEST['users']);
                $this->graceful_exit();
            }
        }
        
    }


    public function page_view_meta( $user_id ) {
        
        $user = get_user_by( 'id', $user_id );        
        include_once( 'admin/partials/zapper-view-meta.php' );
    }
    
    public function page_edit_meta( $user_id ) {
        
        $user = get_user_by( 'id', $user_id );        
        include_once( 'admin/partials/zapper-edit-meta.php' );
    }
    

    public function page_bulk_edit( $bulk_user_ids ) {
                
        include_once( 'admin/partials/zapper-bulk-edit.php' );
    }      
}
?>

The result when clicking a row action is basically nothing, it just refreshes the page. Using the dropdown for a bulk action– while no error is thrown by WP– it directs to a blank page, with the following in the URL parameters:

?_wpnonce=183ef79f5e
&_wp_http_referer=/zapper/wp-admin/admin.php
?page=zapper-table
&action=edit_all
&paged=1
&element[]=9
&element[]=4
&element[]=11
&action2=edit_all

In my previous, successful tests, I don’t have the &_wp_http_referer or &paged=1 and I don’t understand why it’s there in this trial. And that is only on a bulk action request. Clearly I'm doing something wrong, as I've got two "?" in the URL params.

What have I've done wrong? Thank you!

EDIT: I changed the include_once './path' to include_once( WP_PLUGIN_DIR .'/... '), but i'm getting the same results:

    public function page_edit_meta( $user_id ) {
        
        $user = get_user_by( 'id', $user_id );        
        if(file_exists(WP_PLUGIN_DIR .'/zapper/partials/zapper-edit-meta.php')){
        return "<h1>FILE EXISTS!</h1>";
         die();
        }
        else {
                return "<h1>FILE NOT EXISTS!</h1>";
                die();
        }
        include_once( WP_PLUGIN_DIR .'/zapper/partials/zapper-edit-meta.php' );

    }

Changing that path, and adding die(); did not change the behavior at all. I expected it at least to exit. Now I'm really confused. It has to be going into the function if it's redirecting the page?..

EDIT2: The code in the page it's supposed to go to is as follows (but I don't see how that would be relevant here?).

<?php

/**
 * @file '/zapper/partials/zapper-edit-meta.php
 */

    if( current_user_can('edit_users' ) ) { ?>
        <h2> <?php echo __('Process bulk operations for the selected users: <br>', $this->plugin_text_domain ); ?> </h2>
        <h4>
            <ul>
            <?php
                foreach( $bulk_user_ids as $user_id ) {
                    $user = get_user_by( 'id', $user_id );
                    echo '<li>' . $user->display_name . ' (' . $user->user_login . ')' . '</li>';
                }
            ?>
            </ul>
        </h4>
        <div class="card">
            <h4> HTML Form to Edit Meta goes here </h4>
        </div>
        <br>
        <a href="<?php echo esc_url( add_query_arg( array( 'page' => wp_unslash( $_REQUEST['page'] ) ) , admin_url( 'admin.php' ) ) ); ?>"><?php _e( 'Back', $this->plugin_text_domain ) ?></a>
<?php
    }
    else {  
?>
        <p> <?php echo __( 'Not authorized', $this->plugin_text_domain ) ?> </p>
<?php   
    }
2
  • when i click the fucntion page_edit_meta( $user_id ) in the example, above, the resulting URL is ./admin.php?page=zapper-table&action=view_meta&user_id=9 (the actual ID numbers being irrelevant, but apparently i clicked on whoever is ID[9]) Commented Nov 9, 2022 at 1:43
  • i've tried this with both admin_url( 'admin.php' ) and admin_url( 'users.php' ) a WP_List_Table tutorial I'd used was going off of users.php. In my case, I haven't noticed any difference for which base file .php was used. I don't understand quite why, but i'm assuming because of the value in the url where "?page= ". Commented Nov 10, 2022 at 10:24

1 Answer 1

0

SOLVED:

I received guidance at WordPress.org which helped me solve this problem. The solution-- if i recall-- circumvented any need to further pursue what i was trying to do above (basically).

I don't recall precisely what was causing my issue as posted here, in the o/p, but I can check if anyone ever encounters issues w/ that, or WP_List_Table class in general. I think it was a Namespace issue which my code inherited (purposefully) from a tutorial i'd been following on the topic.

The "working" product is here if anyone would like to look at the code, please be my guest. I believe it was quite reworked from my approach in the o/p:

https://github.com/ajaxStardust/wp_zapper

feedback welcome! Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.