* @return bool Whether the update was successful.
function wp_update_user_counts( $network_id = null ) {
if ( ! is_multisite() && null !== $network_id ) {
/* translators: %s: $network_id */
__( 'Unable to pass %s if not using multisite.' ),
'<code>$network_id</code>'
$query = "SELECT COUNT(ID) as c FROM $wpdb->users";
$query .= " WHERE spam = '0' AND deleted = '0'";
$count = $wpdb->get_var( $query );
return update_network_option( $network_id, 'user_count', $count );
* Schedules a recurring recalculation of the total count of users.
function wp_schedule_update_user_counts() {
if ( ! is_main_site() ) {
if ( ! wp_next_scheduled( 'wp_update_user_counts' ) && ! wp_installing() ) {
wp_schedule_event( time(), 'twicedaily', 'wp_update_user_counts' );
* Determines whether the site has a large number of users.
* The default criteria for a large site is more than 10,000 users.
* @param int|null $network_id ID of the network. Defaults to the current network.
* @return bool Whether the site has a large number of users.
function wp_is_large_user_count( $network_id = null ) {
if ( ! is_multisite() && null !== $network_id ) {
/* translators: %s: $network_id */
__( 'Unable to pass %s if not using multisite.' ),
'<code>$network_id</code>'
$count = get_user_count( $network_id );
* Filters whether the site is considered large, based on its number of users.
* @param bool $is_large_user_count Whether the site has a large number of users.
* @param int $count The total number of users.
* @param int|null $network_id ID of the network. `null` represents the current network.
return apply_filters( 'wp_is_large_user_count', $count > 10000, $count, $network_id );
// Private helper functions.
* Sets up global user vars.
* Used by wp_set_current_user() for back compat. Might be deprecated in the future.
* @global string $user_login The user username for logging in
* @global WP_User $userdata User data.
* @global int $user_level The level of the user
* @global int $user_ID The ID of the user
* @global string $user_email The email address of the user
* @global string $user_url The url in the user's profile
* @global string $user_identity The display name of the user
* @param int $for_user_id Optional. User ID to set up global data. Default 0.
function setup_userdata( $for_user_id = 0 ) {
global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_identity;
$for_user_id = get_current_user_id();
$user = get_userdata( $for_user_id );
$user_ID = (int) $user->ID;
$user_level = (int) $user->user_level;
$user_login = $user->user_login;
$user_email = $user->user_email;
$user_url = $user->user_url;
$user_identity = $user->display_name;
* Creates dropdown HTML content of users.
* The content can either be displayed, which it is by default, or retrieved by
* setting the 'echo' argument to false. The 'include' and 'exclude' arguments
* are optional; if they are not specified, all users will be displayed. Only one
* can be used in a single call, either 'include' or 'exclude', but not both.
* @since 4.5.0 Added the 'display_name_with_login' value for 'show'.
* @since 4.7.0 Added the 'role', 'role__in', and 'role__not_in' parameters.
* @since 5.9.0 Added the 'capability', 'capability__in', and 'capability__not_in' parameters.
* Deprecated the 'who' parameter.
* @param array|string $args {
* Optional. Array or string of arguments to generate a drop-down of users.
* See WP_User_Query::prepare_query() for additional available arguments.
* @type string $show_option_all Text to show as the drop-down default (all).
* @type string $show_option_none Text to show as the drop-down default when no
* users were found. Default empty.
* @type int|string $option_none_value Value to use for `$show_option_none` when no users
* were found. Default -1.
* @type string $hide_if_only_one_author Whether to skip generating the drop-down
* if only one user was found. Default empty.
* @type string $orderby Field to order found users by. Accepts user fields.
* Default 'display_name'.
* @type string $order Whether to order users in ascending or descending
* order. Accepts 'ASC' (ascending) or 'DESC' (descending).
* @type int[]|string $include Array or comma-separated list of user IDs to include.
* @type int[]|string $exclude Array or comma-separated list of user IDs to exclude.
* @type bool|int $multi Whether to skip the ID attribute on the 'select' element.
* Accepts 1|true or 0|false. Default 0|false.
* @type string $show User data to display. If the selected item is empty
* then the 'user_login' will be displayed in parentheses.
* Accepts any user field, or 'display_name_with_login' to show
* the display name with user_login in parentheses.
* Default 'display_name'.
* @type int|bool $echo Whether to echo or return the drop-down. Accepts 1|true (echo)
* or 0|false (return). Default 1|true.
* @type int $selected Which user ID should be selected. Default 0.
* @type bool $include_selected Whether to always include the selected user ID in the drop-
* @type string $name Name attribute of select element. Default 'user'.
* @type string $id ID attribute of the select element. Default is the value of `$name`.
* @type string $class Class attribute of the select element. Default empty.
* @type int $blog_id ID of blog (Multisite only). Default is ID of the current blog.
* @type string $who Deprecated, use `$capability` instead.
* Which type of users to query. Accepts only an empty string or
* 'authors'. Default empty (all users).
* @type string|string[] $role An array or a comma-separated list of role names that users
* must match to be included in results. Note that this is
* an inclusive list: users must match *each* role. Default empty.
* @type string[] $role__in An array of role names. Matched users must have at least one
* of these roles. Default empty array.
* @type string[] $role__not_in An array of role names to exclude. Users matching one or more
* of these roles will not be included in results. Default empty array.
* @type string|string[] $capability An array or a comma-separated list of capability names that users
* must match to be included in results. Note that this is
* an inclusive list: users must match *each* capability.
* Does NOT work for capabilities not in the database or filtered
* via {@see 'map_meta_cap'}. Default empty.
* @type string[] $capability__in An array of capability names. Matched users must have at least one
* Does NOT work for capabilities not in the database or filtered
* via {@see 'map_meta_cap'}. Default empty array.
* @type string[] $capability__not_in An array of capability names to exclude. Users matching one or more
* of these capabilities will not be included in results.
* Does NOT work for capabilities not in the database or filtered
* via {@see 'map_meta_cap'}. Default empty array.
* @return string HTML dropdown list of users.
function wp_dropdown_users( $args = '' ) {
'show_option_none' => '',
'hide_if_only_one_author' => '',
'orderby' => 'display_name',
'show' => 'display_name',
'blog_id' => get_current_blog_id(),
'include_selected' => false,
'option_none_value' => -1,
'role__not_in' => array(),
'capability__in' => array(),
'capability__not_in' => array(),
$defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;
$parsed_args = wp_parse_args( $args, $defaults );
$query_args = wp_array_slice_assoc(
$fields = array( 'ID', 'user_login' );
$show = ! empty( $parsed_args['show'] ) ? $parsed_args['show'] : 'display_name';
if ( 'display_name_with_login' === $show ) {
$fields[] = 'display_name';
$query_args['fields'] = $fields;
$show_option_all = $parsed_args['show_option_all'];
$show_option_none = $parsed_args['show_option_none'];
$option_none_value = $parsed_args['option_none_value'];
* Filters the query arguments for the list of users in the dropdown.
* @param array $query_args The query arguments for get_users().
* @param array $parsed_args The arguments passed to wp_dropdown_users() combined with the defaults.
$query_args = apply_filters( 'wp_dropdown_users_args', $query_args, $parsed_args );
$users = get_users( $query_args );
if ( ! empty( $users ) && ( empty( $parsed_args['hide_if_only_one_author'] ) || count( $users ) > 1 ) ) {
$name = esc_attr( $parsed_args['name'] );
if ( $parsed_args['multi'] && ! $parsed_args['id'] ) {
$id = $parsed_args['id'] ? " id='" . esc_attr( $parsed_args['id'] ) . "'" : " id='$name'";
$output = "<select name='{$name}'{$id} class='" . $parsed_args['class'] . "'>\n";
if ( $show_option_all ) {
$output .= "\t<option value='0'>$show_option_all</option>\n";
if ( $show_option_none ) {
$_selected = selected( $option_none_value, $parsed_args['selected'], false );
$output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$_selected>$show_option_none</option>\n";
if ( $parsed_args['include_selected'] && ( $parsed_args['selected'] > 0 ) ) {
$parsed_args['selected'] = (int) $parsed_args['selected'];
foreach ( (array) $users as $user ) {
$user->ID = (int) $user->ID;
if ( $user->ID === $parsed_args['selected'] ) {
if ( ! $found_selected ) {
$selected_user = get_userdata( $parsed_args['selected'] );
$users[] = $selected_user;
foreach ( (array) $users as $user ) {
if ( 'display_name_with_login' === $show ) {
/* translators: 1: User's display name, 2: User login. */
$display = sprintf( _x( '%1$s (%2$s)', 'user dropdown' ), $user->display_name, $user->user_login );
} elseif ( ! empty( $user->$show ) ) {
$display = '(' . $user->user_login . ')';
$_selected = selected( $user->ID, $parsed_args['selected'], false );
$output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n";
* Filters the wp_dropdown_users() HTML output.
* @param string $output HTML output generated by wp_dropdown_users().
$html = apply_filters( 'wp_dropdown_users', $output );
if ( $parsed_args['echo'] ) {
* Sanitizes user field based on context.
* Possible context values are: 'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
* 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
* @param string $field The user Object field name.
* @param mixed $value The user Object value.
* @param int $user_id User ID.
* @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
* @return mixed Sanitized value.
function sanitize_user_field( $field, $value, $user_id, $context ) {
$int_fields = array( 'ID' );
if ( in_array( $field, $int_fields, true ) ) {
if ( 'raw' === $context ) {
if ( ! is_string( $value ) && ! is_numeric( $value ) ) {
$prefixed = str_contains( $field, 'user_' );
if ( 'edit' === $context ) {
/** This filter is documented in wp-includes/post.php */
$value = apply_filters( "edit_{$field}", $value, $user_id );
* Filters a user field value in the 'edit' context.
* The dynamic portion of the hook name, `$field`, refers to the prefixed user
* field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
* @param mixed $value Value of the prefixed user field.
* @param int $user_id User ID.
$value = apply_filters( "edit_user_{$field}", $value, $user_id );
if ( 'description' === $field ) {
$value = esc_html( $value ); // textarea_escaped?
$value = esc_attr( $value );
} elseif ( 'db' === $context ) {
/** This filter is documented in wp-includes/post.php */
$value = apply_filters( "pre_{$field}", $value );
* Filters the value of a user field in the 'db' context.
* The dynamic portion of the hook name, `$field`, refers to the prefixed user
* field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
* @param mixed $value Value of the prefixed user field.
$value = apply_filters( "pre_user_{$field}", $value );
// Use display filters by default.
/** This filter is documented in wp-includes/post.php */
$value = apply_filters( "{$field}", $value, $user_id, $context );
* Filters the value of a user field in a standard context.
* The dynamic portion of the hook name, `$field`, refers to the prefixed user
* field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
* @param mixed $value The user object value to sanitize.
* @param int $user_id User ID.
* @param string $context The context to filter within.
$value = apply_filters( "user_{$field}", $value, $user_id, $context );
if ( 'user_url' === $field ) {
$value = esc_url( $value );
if ( 'attribute' === $context ) {
$value = esc_attr( $value );
} elseif ( 'js' === $context ) {
$value = esc_js( $value );
// Restore the type for integer fields after esc_attr().
if ( in_array( $field, $int_fields, true ) ) {
* Updates all user caches.
* @param object|WP_User $user User object or database row to be cached
* @return void|false Void on success, false on failure.
function update_user_caches( $user ) {
if ( $user instanceof WP_User ) {
if ( ! $user->exists() ) {
wp_cache_add( $user->ID, $user, 'users' );
wp_cache_add( $user->user_login, $user->ID, 'userlogins' );
wp_cache_add( $user->user_nicename, $user->ID, 'userslugs' );
if ( ! empty( $user->user_email ) ) {
wp_cache_add( $user->user_email, $user->ID, 'useremail' );
* Cleans all user caches.