Toggle User Roles with button

As it happens, I have something very similar on one of my sites to to allow Administrators update some custom user meta.

Basically, you need to add an additional column and then populate it with a link to do what you want. When you click the link some jQuery fires of an AJAX request to update the user role and then you are redirected back the the /wp-admin/users.php page.

To main workhorse here is the wp_update_user() function, which I encourage you to take a look at.


PHP

First, add this to your functions.php file to add the additional column and it’s contents. This will also add the AJAX function that will actually do all the magic when it’s called upon –

/** Manage custom columns on instances of 'WP_List_Table' */
add_action('init', 'my_setup_custom_columns', 110, 0);
function my_setup_custom_columns(){
    
    /** Manage columns on the WP_Users_List_Table */
    add_filter('manage_users_columns', 'my_add_custom_columns');
    
    /** Populate additional columns on the WP_Users_List_Table */
    add_action('manage_users_custom_column', 'my_fill_custom_columns_return', 10, 3);
    
}

/**
 * Add additional custom columns to the list table views in the admin area
 *
 * @param required array $columns   The columns that currently exist
 */
function my_add_custom_columns($columns){

    /** Grab the page that is currently being viewed */
    global $pagenow;
    
    /** Users specific columns (http://www.blog.com/wp-admin/users.php) */
    if($pagenow === 'users.php') :
    
        $new_columns['my-change-user-role'] = __('Change Role');
        
    endif;
    
    $columns = $columns + $new_columns;
    
    return $columns;
    
}

/**
 * Fill the custom columns by returning data
 *
 * @param required string $column_value The current column value (in this case 'null' since the columns are new)
 * @param required string $column_name  The name of the column to return data for
 * @param required integer $object_id   The ID of the curent object to fill the column for
 * @return string $column_value         The value to fill the column with
 */
function my_fill_custom_columns_return($column_value, $column_name, $object_id){

    switch($column_name) :
    
        /**
         * ID (the ID of the current object)
         */
        case 'my-change-user-role' :
        
            $user = get_userdata($object_id);
            $role = $user->roles[0];
            
            if($role === 'legend') :
                $column_value="<span user-id="" . $object_id . '" new-role="subscriber" class="change-user-role">Downgrade to a Hero</span>';
            elseif($role === 'hero') :
                $column_value="<span user-id="" . $object_id . '" new-role="document_administrator" class="change-user-role">Upgrade to a Legend</span>';
            else:
                $column_value="&#8212;";
            endif;
            
            break;
    
    endswitch;
    
    return $column_value;
    
}

/**
 * Change the role of a given user
 */
add_action('wp_ajax_change_user_role', 'my_update_user_role');
function my_update_user_role(){

    /** Update the user role */
    $args = array(
        'ID'    => $_POST['user_id'],
        'role'  => $_POST['new_role']
    );
    $result = wp_update_user($args);
    
    /** Check whether or not the update was successful */
    if(is_wp_error($user_id)) :
        $message="An unexpected error occured, please try again.";
        $url = false;
    else :
        $message="success";
        $url = admin_url('users.php');
    endif;
    
    $return = array(
        'message'   => $message,
        'url'       => $url
    );
    echo json_encode((object)$return);
    
    wp_die(); // This is required to terminate immediately and return a proper response
    
}

CSS

Next, add this to a style sheet that is accessible when you are viewing the admin area –

.wp-list-table.users .manage-column.column-my-change-user-role{
    width:  150px;
}
.wp-list-table.users span.change-user-role{
    color:  #0074A2;
    cursor: pointer;
}
.wp-list-table.users span.change-user-role:hover{
    color:  #2EA2CC;
}

JS

Finally, add this to a JS file that is accessible when you are viewing the admin area –

jQuery(function($){
    
    $(document).ready(function(){
        updateUser.init();
    });
    
    var updateUser = {
    
        /**
         * Psuedo constructor
         */
        init : function(){
        
            this.userChangeRoleButtons = $('.wp-list-table.users span.change-user-role');   // Grab all instance of the buttons to change the user role
            this.createEvents();                                                            // Create the events to be handled by this object
            
        }, // init
        
        /**
         * Create the events that are to be handled by this object
         */
        createEvents : function(){
        
            var t = this;   // This object
            
            /**
             * Handle clicks of the change user role buttons
             */
            this.userChangeRoleButtons.on('click', function(e){
            
                t.changeRole($(this));
                
            });
            
        }, // createEvents
        
        /**
         * Updates the user role as required
         */
        changeRole : function(clicked){
        
            var t               = this, // This object
                user_id         = clicked.attr('user-id'),
                new_role        = clicked.attr('new-role');
            
            var data = {    // The data object to pass to the AJAX request
                action:     'change_user_role',
                user_id:    user_id,
                new_role:   new_role
            };
            
            /** Make the AJAX request to update the download count */
            var action_jqxhr = $.post(ajaxurl, data, function(response){
            
                /** Parse the JSON response */
                var obj = JSON.parse(response);
                
                /** Ensure that there were no errors and update the 'Change role' button text */
                if(obj.message.indexOf('error') === -1){    // There was no error, redirect the user back to this page
                
                    top.location.replace(obj.url);
                    
                } else {    // There was an error, tell the user about it
                
                    alert(obj.message); // Show the error to the user
                    
                }
                
            }).fail(function(){ // There was an AJAX error...
                alert('An unexpected error occured, please try again.');
            });
            
        } // changeRole
        
    };
    
});