How to get ID of Edit User page during wp_handle_upload_prefilter, whilst in Media picker?

Is this because, whilst the Edit User page is still at
user-edit.php?user_id=2, the Media modal has somehow denied us the
ability to get user_id?

Getting the user ID on that page is easy, e.g. you could simply use get_current_user_id() to get the ID of the currently logged-in user, or use $_GET['user_id'] to get the ID of the user for the profile that’s being edited.

But the thing is, the default WordPress media uploader will upload the file via AJAX to wp-admin/async-upload.php and despite on that page, you could still get the ID of the currently logged-in user, you wouldn’t be able to get the ID of the user being edited, i.e. the value of the above user_id parameter, because the media uploader doesn’t “forward” the user_id value to async-upload.php.

So by default, there’s no way to get that value from the wp_handle_upload_prefilter hook which runs on the async-upload.php page.

However, you could do one of these:

  1. Use wp_get_referer() to get the referring URL and then read the user_id from the URL’s query string.

  2. Manually “forward” the user ID to async-upload.php, which can be done via the plupload_default_params filter.

Working Examples

  1. For the first option above:

    // Note: This is a simplified example. In actual implementation, you'd want to
    // check if the referring page is wp-admin/user-edit.php or wp-admin/profile.php
    
    parse_str( parse_url( wp_get_referer(), PHP_URL_QUERY ), $args );
    $user_id = $args['user_id'] ?? get_current_user_id();
    
  2. For the second option above:

    add_filter( 'plupload_default_params', 'my_plupload_default_params' );
    function my_plupload_default_params( $params ) {
        // the admin page's file name, without .php
        $screens = array( 'user-edit', 'profile' );
    
        if ( is_admin() && in_array( get_current_screen()->id, $screens ) ) {
            $params['user_id'] = ( defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) ?
                get_current_user_id() : $_REQUEST['user_id'];
        }
    
        return $params;
    }
    

    And then in your function, just use $_POST['user_id'] to get the user ID.