New User Form – Custom Menu Page

Important: The code posted below is not fully tested. There are lots of area where you can improve the code as this is only to show you the right way. If you need any pointer, check user-new.php as the reference.

I am going to use the class structure for the plugin and let’s say plugin name is create-user. So, the basic structure of this plugin will be:

<?php
/*
Plugin Name: Create User
Description: Create user
Plugin URI: ****
Author: sakibmoon
Author URI: ****
Version: 0.0.1
*/
class  create_user{

}

At first we have to create the Admin menu page. We are going to add that in the constructor.

public function __construct(){
    //Action hook to add menu option in the admin panel
    add_action('admin_menu', array( &$this, 'add_menu') );
}

The add_menu() function is as follow

public function add_menu(){
    //Creating top level menu as staff
    //Use add_submenu_page for adding additional submenu
    add_menu_page( 'Staff', 'staff', 'edit_users', __FILE__, array( &$this, 'show_staff_page' ) );
    }

show_staff_page() function will show the page content. We will show the form to create user as page content. I have taken almost all the portion from the user-new.php with the exception of role. By default, wordpress use wp_dropdown_roles() to populate the drop down field. But if you wanted to exclude Administrator you can’t call it directly. You have to remove Administrator from editable_roles. To save time, I have hard coded it. But in my opinion best choice would be to use the filter editable_roles. How to remove administrator role in settings -> general -> New User Default Role? will give you some idea about this.

public function show_staff_page(){
?>
    <?php //Input to create new User ?>
    <form action="" method="post" name="adduser" id="adduser" class="validate"<?php do_action('user_new_form_tag');?>>
        <input name="action" type="hidden" value="adduser" />
        <?php wp_nonce_field( 'add-user', '_wpnonce_add-user' ) ?>
        <?php
        // Load up the passed data, else set to a default.
        foreach ( array( 'user_login' => 'login', 'first_name' => 'firstname', 'last_name' => 'lastname',
                        'email' => 'email', 'url' => 'uri', 'role' => 'role', 'send_password' => 'send_password', 'noconfirmation' => 'ignore_pass' ) as $post_field => $var ) {
            $var = "new_user_$var";
            if( isset( $_POST['createuser'] ) ) {
                if ( ! isset($$var) )
                    $$var = isset( $_POST[$post_field] ) ? wp_unslash( $_POST[$post_field] ) : '';
            } else {
                $$var = false;
            }
        }

        ?>
        <table class="form-table">
            <tr class="form-field form-required">
                <th scope="row"><label for="user_login"><?php _e('Username'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th>
                <td><input name="user_login" type="text" id="user_login" value="<?php echo esc_attr($new_user_login); ?>" aria-required="true" /></td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row"><label for="email"><?php _e('E-mail'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th>
                <td><input name="email" type="text" id="email" value="<?php echo esc_attr($new_user_email); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="first_name"><?php _e('First Name') ?> </label></th>
                <td><input name="first_name" type="text" id="first_name" value="<?php echo esc_attr($new_user_firstname); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="last_name"><?php _e('Last Name') ?> </label></th>
                <td><input name="last_name" type="text" id="last_name" value="<?php echo esc_attr($new_user_lastname); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="url"><?php _e('Website') ?></label></th>
                <td><input name="url" type="text" id="url" class="code" value="<?php echo esc_attr($new_user_uri); ?>" /></td>
            </tr>
            <tr class="form-field form-required">
            <th scope="row"><label for="pass1"><?php _e('Password'); ?> <span class="description"><?php /* translators: password input field */_e('(required)'); ?></span></label></th>
            <td>
                <input class="hidden" value=" " /><!-- #24364 workaround -->
                <input name="pass1" type="password" id="pass1" autocomplete="off" />
            </td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row"><label for="pass2"><?php _e('Repeat Password'); ?> <span class="description"><?php /* translators: password input field */_e('(required)'); ?></span></label></th>
                <td>
                <input name="pass2" type="password" id="pass2" autocomplete="off" />
                <br />
                <div id="pass-strength-result"><?php _e('Strength indicator'); ?></div>
                <p class="description indicator-hint"><?php _e('Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ &amp; ).'); ?></p>
                </td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="role"><?php _e('Role'); ?></label></th>
                <td><select name="role" id="role">
                    <?php
                    $editable_roles = array_reverse( get_editable_roles() );
                    foreach ( $editable_roles as $role => $details ) {
                        if( 'administrator' == $role )
                            continue;
                        $name = translate_user_role($details['name'] );
                        if ( $selected == $role ) // preselect specified role
                            $p = "\n\t<option selected='selected' value="" . esc_attr($role) . "">$name</option>";
                        else
                            $r .= "\n\t<option value="" . esc_attr($role) . "">$name</option>";
                    }
                    echo $p . $r;
                    ?>
                    </select>
                </td>
            </tr>
        </table>
        <?php submit_button( __( 'Add New User '), 'primary', 'createuser', true, array( 'id' => 'createusersub' ) ); ?>
    </form>
    <?php
    }

The last thing to do is to handle the submit request, do error checking and then create user using wp_insert_user()

if($_POST['createuser']){
            //nonce verification for security
            check_admin_referer('add-user', '_wpnonce_add-user');

            $user_login     = $_POST['user_login'];
            $email          = $_POST['email'];
            $first_name     = $_POST['first_name'];
            $last_name      = $_POST['last_name'];
            $pass1          = $_POST['pass1'];
            $pass2          = $_POST['pass2'];
            $url            = $_POST['url'];
            $send_password  = $_POST['send_password'];
            $role           = $_POST['role'];

            //Handling errors
            if( empty($user_login) || empty($email) ){
                echo "Username or Email can't be empty";
            }elseif( !is_email($email) ){
                echo "Invalid email";
            }elseif( empty($pass1) ){
                echo "Password can't be empty";
            }elseif( $pass1 !== $pass2 ){
                echo "Password doesn't match";
            }else{
                //No errors. Create User.
                $userdata = array(
                    'user_login'    => $user_login,
                    'user_pass'     => $pass1,
                    'user_email'    => $email,
                    'user_url'      => $url,
                    'first_name'    => $first_name,
                    'last_name'     => $last_name,
                    'role'          => $role
                );
                $user_id = wp_insert_user( $userdata );
                if( !is_wp_error($user_id) ){
                    //User created.
                    echo "User created";
                }else{
                    //There was some error like duplicate email, username etc. Show the error
                    foreach( $user_id->errors as $name=>$errors ){
                        foreach( $errors as $error ){
                            echo $error;
                        }
                    }
                }
            }
        }

Then all you have to do is to initialize the class

$new_user = new create_user();

The whole code is posted below

<?php
/*
Plugin Name: Create User
Description: Create user
Plugin URI: ****
Author: sakibmoon
Author URI: ****
Version: 0.0.1
*/
class  create_user{
    public function __construct(){
        //Action hook to add menu option in the admin panel
        add_action('admin_menu', array( &$this, 'add_menu') );
    }

    public function add_menu(){
        //Creating top level menu as staff
        //Use add_submenu_page for adding additional submenu
        add_menu_page( 'Staff', 'staff', 'edit_users', __FILE__, array( &$this, 'show_staff_page' ) );
    }

    public function show_staff_page(){
        //Processing submitted data
        if($_POST['createuser']){
            //nonce verification for security
            check_admin_referer('add-user', '_wpnonce_add-user');

            $user_login     = $_POST['user_login'];
            $email          = $_POST['email'];
            $first_name     = $_POST['first_name'];
            $last_name      = $_POST['last_name'];
            $pass1          = $_POST['pass1'];
            $pass2          = $_POST['pass2'];
            $url            = $_POST['url'];
            $send_password  = $_POST['send_password'];
            $role           = $_POST['role'];

            //Handling errors
            if( empty($user_login) || empty($email) ){
                echo "Username or Email can't be empty";
            }elseif( !is_email($email) ){
                echo "Invalid email";
            }elseif( empty($pass1) ){
                echo "Password can't be empty";
            }elseif( $pass1 !== $pass2 ){
                echo "Password doesn't match";
            }else{
                //No errors. Create User.
                $userdata = array(
                    'user_login'    => $user_login,
                    'user_pass'     => $pass1,
                    'user_email'    => $email,
                    'user_url'      => $url,
                    'first_name'    => $first_name,
                    'last_name'     => $last_name,
                    'role'          => $role
                );
                $user_id = wp_insert_user( $userdata );
                if( !is_wp_error($user_id) ){
                    //User created.
                    echo "User created";
                }else{
                    //There was some error like duplicate email, username etc. Show the error
                    foreach( $user_id->errors as $name=>$errors ){
                        foreach( $errors as $error ){
                            echo $error;
                        }
                    }
                }
            }
        }

    ?>
    <?php //Input to create new User ?>
    <form action="" method="post" name="adduser" id="adduser" class="validate"<?php do_action('user_new_form_tag');?>>
        <input name="action" type="hidden" value="adduser" />
        <?php wp_nonce_field( 'add-user', '_wpnonce_add-user' ) ?>
        <?php
        // Load up the passed data, else set to a default.
        foreach ( array( 'user_login' => 'login', 'first_name' => 'firstname', 'last_name' => 'lastname',
                        'email' => 'email', 'url' => 'uri', 'role' => 'role', 'send_password' => 'send_password', 'noconfirmation' => 'ignore_pass' ) as $post_field => $var ) {
            $var = "new_user_$var";
            if( isset( $_POST['createuser'] ) ) {
                if ( ! isset($$var) )
                    $$var = isset( $_POST[$post_field] ) ? wp_unslash( $_POST[$post_field] ) : '';
            } else {
                $$var = false;
            }
        }

        ?>
        <table class="form-table">
            <tr class="form-field form-required">
                <th scope="row"><label for="user_login"><?php _e('Username'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th>
                <td><input name="user_login" type="text" id="user_login" value="<?php echo esc_attr($new_user_login); ?>" aria-required="true" /></td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row"><label for="email"><?php _e('E-mail'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th>
                <td><input name="email" type="text" id="email" value="<?php echo esc_attr($new_user_email); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="first_name"><?php _e('First Name') ?> </label></th>
                <td><input name="first_name" type="text" id="first_name" value="<?php echo esc_attr($new_user_firstname); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="last_name"><?php _e('Last Name') ?> </label></th>
                <td><input name="last_name" type="text" id="last_name" value="<?php echo esc_attr($new_user_lastname); ?>" /></td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="url"><?php _e('Website') ?></label></th>
                <td><input name="url" type="text" id="url" class="code" value="<?php echo esc_attr($new_user_uri); ?>" /></td>
            </tr>
            <tr class="form-field form-required">
            <th scope="row"><label for="pass1"><?php _e('Password'); ?> <span class="description"><?php /* translators: password input field */_e('(required)'); ?></span></label></th>
            <td>
                <input class="hidden" value=" " /><!-- #24364 workaround -->
                <input name="pass1" type="password" id="pass1" autocomplete="off" />
            </td>
            </tr>
            <tr class="form-field form-required">
                <th scope="row"><label for="pass2"><?php _e('Repeat Password'); ?> <span class="description"><?php /* translators: password input field */_e('(required)'); ?></span></label></th>
                <td>
                <input name="pass2" type="password" id="pass2" autocomplete="off" />
                <br />
                <div id="pass-strength-result"><?php _e('Strength indicator'); ?></div>
                <p class="description indicator-hint"><?php _e('Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ &amp; ).'); ?></p>
                </td>
            </tr>
            <tr class="form-field">
                <th scope="row"><label for="role"><?php _e('Role'); ?></label></th>
                <td><select name="role" id="role">
                    <?php
                    $editable_roles = array_reverse( get_editable_roles() );
                    foreach ( $editable_roles as $role => $details ) {
                        if( 'administrator' == $role )
                            continue;
                        $name = translate_user_role($details['name'] );
                        if ( $selected == $role ) // preselect specified role
                            $p = "\n\t<option selected='selected' value="" . esc_attr($role) . "">$name</option>";
                        else
                            $r .= "\n\t<option value="" . esc_attr($role) . "">$name</option>";
                    }
                    echo $p . $r;
                    ?>
                    </select>
                </td>
            </tr>
        </table>
        <?php submit_button( __( 'Add New User '), 'primary', 'createuser', true, array( 'id' => 'createusersub' ) ); ?>
    </form>
    <?php
    }
}

$new_user = new create_user();

EDIT: I don’t fully understand what you are trying to do. But it seems that you want to create user group. The staff that you are adding is list of users. They will be shown in all user list too. WordPress by default doesn’t have anything like user group. First you need to clear what you are trying to achieve with your code.