Question

I want to update the confirmation form for delete user.

If user has posts, it shows Attribute all content to - option to reassign other author for his posts. It takes lots-of time to load the page, if there are thousands of users in the system. (we have 55k+ users)

So, I want to change the User option (Attribute all content to) from Drop-down to Type and Search.

I've tried to found the hooks/action but could not found that I want. I don't want to update wordpress core files to change this.

Please suggest me hooks/action for my question.

Thanks.

enter image description here

Was it helpful?

Solution

On the Users (wp-admin/users.php) page, WordPress uses wp_dropdown_users() to generate the users drop-down menu you're referring to, so I'd suggest using the wp_dropdown_users_args hook to filter the users query, e.g. to show only 1 result (or 10, but surely not 55k!) and then use JavaScript to add/load the other results.

So in this answer, I'm going to show you how you can do that, where we use Select2 to add the "type and search" functionality. Note that I'm using a custom REST API endpoint which returns the results in the format expected by Select2 and that way, the JavaScript part/code would also be simpler for us (i.e. the code is shorter).

Step #1: Filter the users query for the reassign_user drop-down menu.

function my_filter_reassign_user_query( $query_args, $parsed_args ) {
    // Make sure we're on the users.php page on the admin side.
    if ( is_admin() && 'users' === get_current_screen()->id          &&
        // .. and the action is deleting a user
        ( isset( $_GET['action'] ) && 'delete' === $_GET['action'] ) &&
        // .. and the <select>'s name is set to reassign_user.
        'reassign_user' === $parsed_args['name']
    ) {
        // You can also use 10, etc., but the point is, we don't want 55k (or
        // LOTS OF) <option> tags!
        $query_args['number'] = 1;
    }

    return $query_args;
}
add_filter( 'wp_dropdown_users_args', 'my_filter_reassign_user_query', 10, 2 );

Step #2: Enqueue the Select2 scripts and styles, and our AJAX script.

function my_enqueue_select2_scripts() {
    // Make sure we're on the users.php page on the admin side.
    if ( is_admin() && 'users' === get_current_screen()->id ) {
        wp_enqueue_style( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/css/select2.min.css', [], null );
        wp_enqueue_script( 'select2', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.12/js/select2.full.min.js', [], null );

        wp_enqueue_script( 'users-ajax', '/path/to/users-ajax.js', [ 'select2', 'jquery' ], '1.0' );
        wp_localize_script( 'users-ajax', 'users_ajax', [
            'root'  => esc_url_raw( get_rest_url() ),
            'nonce' => wp_create_nonce( 'wp_rest' ),
        ] );
    }
}
add_action( 'admin_enqueue_scripts', 'my_enqueue_select2_scripts' );

Step #3: Register the custom REST API endpoint.

I'm just giving you the code, so check out the official handbook if you haven't. You'd also want to check WP_User_Query::prepare_query() for the parameters you can use.

function my_select2_users( $request ) {
    $search   = $request->get_param( 'term' );     // the search keyword
    $per_page = $request->get_param( 'per_page' ); // results per page
    $page     = $request->get_param( 'page' );     // current page number

    $per_page = $per_page ? $per_page : 10;
    $page     = $page     ? $page     : 1;
    $args     = [
        'number'         => $per_page,
        'paged'          => $page,
        'search_columns' => [ 'user_login', 'display_name' ],
        'fields'         => [ 'ID', 'display_name', 'user_login' ],
        'who'            => 'authors',
    ];

    if ( $search ) {
        $args['search'] = '*' . sanitize_text_field( $search ) . '*';
    }

    $query = new WP_User_Query( $args );

    $items = [];
    foreach ( $query->get_results() as $user ) {
        $items[] = [
            'id'   => $user->ID,
            'text' => $user->display_name . ' (' . $user->user_login . ')',
        ];
    }

    return [
        'results'    => $items,
        'pagination' => [ 'more' => $page * $per_page < $query->get_total() ],
        'total'      => $query->get_total(),
    ];
}

add_action( 'rest_api_init', function () {
    // You should rename the my-plugin to a meaningful one..
    register_rest_route( 'my-plugin/v1', '/select2_users', [
        'methods'             => 'GET',
        'callback'            => 'my_select2_users',
        'permission_callback' => function () {
            return current_user_can( 'delete_users' );
        }
    ] );
} );

Step #4: The JavaScript/AJAX script (placed in users-ajax.js).

Check here for the Select2's parameters (like the ajax) you can use.

jQuery( function ( $ ) {
    $( 'select[name="reassign_user"]' ).on( 'select2:open', function () {
        $( '#delete_option1' ).prop( 'checked', true );
    } ).on( 'select2:select', function( e ) {
        $( '#submit' ).removeProp( 'disabled' );
    } ).on( 'select2:unselect', function( e ) {
        $( '#submit' ).prop( 'disabled', true );
    } ).select2( {
        ajax: {
            url: users_ajax.root + 'my-plugin/v1/select2_users',
            dataType: 'json',
            headers: { 'X-WP-NONCE': users_ajax.nonce }
        },
        minimumInputLength: 2
    } );
} );

When all code put together, you'd get something like so:

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top