--- a/wp/wp-includes/user.php Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-includes/user.php Tue Sep 27 16:37:53 2022 +0200
@@ -112,7 +112,7 @@
}
/**
- * Authenticate a user, confirming the username and password are valid.
+ * Authenticates a user, confirming the username and password are valid.
*
* @since 2.8.0
*
@@ -158,7 +158,7 @@
}
/**
- * Filters whether the given user can be authenticated with the provided $password.
+ * Filters whether the given user can be authenticated with the provided password.
*
* @since 2.5.0
*
@@ -261,7 +261,7 @@
}
/**
- * Authenticate the user using the WordPress auth cookie.
+ * Authenticates the user using the WordPress auth cookie.
*
* @since 2.8.0
*
@@ -385,7 +385,7 @@
}
/*
- * Strip out anything non-alphanumeric. This is so passwords can be used with
+ * Strips out anything non-alphanumeric. This is so passwords can be used with
* or without spaces to indicate the groupings for readability.
*
* Generated application passwords are exclusively alphanumeric.
@@ -482,7 +482,7 @@
}
/**
- * For Multisite blogs, check if the authenticated user has been marked as a
+ * For Multisite blogs, checks if the authenticated user has been marked as a
* spammer, or if the user's primary blog has been marked as spam.
*
* @since 3.7.0
@@ -537,7 +537,7 @@
}
/**
- * Number of posts user has written.
+ * Gets the number of posts a user has written.
*
* @since 3.0.0
* @since 4.1.0 Added `$post_type` argument.
@@ -574,7 +574,7 @@
}
/**
- * Number of posts written by a list of users.
+ * Gets the number of posts written by a list of users.
*
* @since 3.0.0
*
@@ -615,7 +615,7 @@
//
/**
- * Get the current user's ID
+ * Gets the current user's ID.
*
* @since MU (3.0.0)
*
@@ -630,7 +630,7 @@
}
/**
- * Retrieve user option that can be either per Site or per Network.
+ * Retrieves user option that can be either per Site or per Network.
*
* If the user ID is not given, then the current user will be used instead. If
* the user ID is given, then the user data will be retrieved. The filter for
@@ -688,7 +688,7 @@
}
/**
- * Update user option with global blog capability.
+ * Updates user option with global blog capability.
*
* User options are just like user metadata except that they have support for
* global blog options. If the 'global' parameter is false, which it is by default
@@ -719,7 +719,7 @@
}
/**
- * Delete user option with global blog capability.
+ * Deletes user option with global blog capability.
*
* User options are just like user metadata except that they have support for
* global blog options. If the 'global' parameter is false, which it is by default
@@ -745,7 +745,7 @@
}
/**
- * Retrieve list of users matching criteria.
+ * Retrieves list of users matching criteria.
*
* @since 3.1.0
*
@@ -766,7 +766,127 @@
}
/**
- * Get the sites a user belongs to.
+ * Lists all the users of the site, with several options available.
+ *
+ * @since 5.9.0
+ *
+ * @param string|array $args {
+ * Optional. Array or string of default arguments.
+ *
+ * @type string $orderby How to sort the users. Accepts 'nicename', 'email', 'url', 'registered',
+ * 'user_nicename', 'user_email', 'user_url', 'user_registered', 'name',
+ * 'display_name', 'post_count', 'ID', 'meta_value', 'user_login'. Default 'name'.
+ * @type string $order Sorting direction for $orderby. Accepts 'ASC', 'DESC'. Default 'ASC'.
+ * @type int $number Maximum users to return or display. Default empty (all users).
+ * @type bool $exclude_admin Whether to exclude the 'admin' account, if it exists. Default false.
+ * @type bool $show_fullname Whether to show the user's full name. Default false.
+ * @type string $feed If not empty, show a link to the user's feed and use this text as the alt
+ * parameter of the link. Default empty.
+ * @type string $feed_image If not empty, show a link to the user's feed and use this image URL as
+ * clickable anchor. Default empty.
+ * @type string $feed_type The feed type to link to, such as 'rss2'. Defaults to default feed type.
+ * @type bool $echo Whether to output the result or instead return it. Default true.
+ * @type string $style If 'list', each user is wrapped in an `<li>` element, otherwise the users
+ * will be separated by commas.
+ * @type bool $html Whether to list the items in HTML form or plaintext. Default true.
+ * @type string $exclude An array, comma-, or space-separated list of user IDs to exclude. Default empty.
+ * @type string $include An array, comma-, or space-separated list of user IDs to include. Default empty.
+ * }
+ * @return string|null The output if echo is false. Otherwise null.
+ */
+function wp_list_users( $args = array() ) {
+ $defaults = array(
+ 'orderby' => 'name',
+ 'order' => 'ASC',
+ 'number' => '',
+ 'exclude_admin' => true,
+ 'show_fullname' => false,
+ 'feed' => '',
+ 'feed_image' => '',
+ 'feed_type' => '',
+ 'echo' => true,
+ 'style' => 'list',
+ 'html' => true,
+ 'exclude' => '',
+ 'include' => '',
+ );
+
+ $args = wp_parse_args( $args, $defaults );
+
+ $return = '';
+
+ $query_args = wp_array_slice_assoc( $args, array( 'orderby', 'order', 'number', 'exclude', 'include' ) );
+ $query_args['fields'] = 'ids';
+ $users = get_users( $query_args );
+
+ foreach ( $users as $user_id ) {
+ $user = get_userdata( $user_id );
+
+ if ( $args['exclude_admin'] && 'admin' === $user->display_name ) {
+ continue;
+ }
+
+ if ( $args['show_fullname'] && '' !== $user->first_name && '' !== $user->last_name ) {
+ $name = "$user->first_name $user->last_name";
+ } else {
+ $name = $user->display_name;
+ }
+
+ if ( ! $args['html'] ) {
+ $return .= $name . ', ';
+
+ continue; // No need to go further to process HTML.
+ }
+
+ if ( 'list' === $args['style'] ) {
+ $return .= '<li>';
+ }
+
+ $row = $name;
+
+ if ( ! empty( $args['feed_image'] ) || ! empty( $args['feed'] ) ) {
+ $row .= ' ';
+ if ( empty( $args['feed_image'] ) ) {
+ $row .= '(';
+ }
+
+ $row .= '<a href="' . get_author_feed_link( $user->ID, $args['feed_type'] ) . '"';
+
+ $alt = '';
+ if ( ! empty( $args['feed'] ) ) {
+ $alt = ' alt="' . esc_attr( $args['feed'] ) . '"';
+ $name = $args['feed'];
+ }
+
+ $row .= '>';
+
+ if ( ! empty( $args['feed_image'] ) ) {
+ $row .= '<img src="' . esc_url( $args['feed_image'] ) . '" style="border: none;"' . $alt . ' />';
+ } else {
+ $row .= $name;
+ }
+
+ $row .= '</a>';
+
+ if ( empty( $args['feed_image'] ) ) {
+ $row .= ')';
+ }
+ }
+
+ $return .= $row;
+ $return .= ( 'list' === $args['style'] ) ? '</li>' : ', ';
+ }
+
+ $return = rtrim( $return, ', ' );
+
+ if ( ! $args['echo'] ) {
+ return $return;
+ }
+ echo $return;
+}
+
+/**
+ * Gets the sites a user belongs to.
*
* @since 3.0.0
* @since 4.7.0 Converted to use `get_sites()`.
@@ -898,7 +1018,7 @@
}
/**
- * Find out whether a user is a member of a given blog.
+ * Finds out whether a user is a member of a given blog.
*
* @since MU (3.0.0)
*
@@ -980,7 +1100,7 @@
}
/**
- * Remove metadata matching criteria from a user.
+ * Removes metadata matching criteria from a user.
*
* You can match based on the key, or key and value. Removing based on key and
* value, will keep from removing duplicate metadata with the same key. It also
@@ -1002,7 +1122,7 @@
}
/**
- * Retrieve user meta field for a user.
+ * Retrieves user meta field for a user.
*
* @since 3.0.0
*
@@ -1024,7 +1144,7 @@
}
/**
- * Update user meta field based on user ID.
+ * Updates user meta field based on user ID.
*
* Use the $prev_value parameter to differentiate between meta fields with the
* same key and user ID.
@@ -1050,7 +1170,7 @@
}
/**
- * Count number of users who have each of the user roles.
+ * Counts number of users who have each of the user roles.
*
* Assumes there are neither duplicated nor orphaned capabilities meta_values.
* Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query()
@@ -1185,12 +1305,156 @@
return $result;
}
+/**
+ * Returns the number of active users in your installation.
+ *
+ * Note that on a large site the count may be cached and only updated twice daily.
+ *
+ * @since MU (3.0.0)
+ * @since 4.8.0 The `$network_id` parameter has been added.
+ * @since 6.0.0 Moved to wp-includes/user.php.
+ *
+ * @param int|null $network_id ID of the network. Defaults to the current network.
+ * @return int Number of active users on the network.
+ */
+function get_user_count( $network_id = null ) {
+ if ( ! is_multisite() && null !== $network_id ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: %s: $network_id */
+ __( 'Unable to pass %s if not using multisite.' ),
+ '<code>$network_id</code>'
+ ),
+ '6.0.0'
+ );
+ }
+
+ return (int) get_network_option( $network_id, 'user_count', -1 );
+}
+
+/**
+ * Updates the total count of users on the site if live user counting is enabled.
+ *
+ * @since 6.0.0
+ *
+ * @param int|null $network_id ID of the network. Defaults to the current network.
+ * @return bool Whether the update was successful.
+ */
+function wp_maybe_update_user_counts( $network_id = null ) {
+ if ( ! is_multisite() && null !== $network_id ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: %s: $network_id */
+ __( 'Unable to pass %s if not using multisite.' ),
+ '<code>$network_id</code>'
+ ),
+ '6.0.0'
+ );
+ }
+
+ $is_small_network = ! wp_is_large_user_count( $network_id );
+ /** This filter is documented in wp-includes/ms-functions.php */
+ if ( ! apply_filters( 'enable_live_network_counts', $is_small_network, 'users' ) ) {
+ return false;
+ }
+
+ return wp_update_user_counts( $network_id );
+}
+
+/**
+ * Updates the total count of users on the site.
+ *
+ * @global wpdb $wpdb WordPress database abstraction object.
+ * @since 6.0.0
+ *
+ * @param int|null $network_id ID of the network. Defaults to the current network.
+ * @return bool Whether the update was successful.
+ */
+function wp_update_user_counts( $network_id = null ) {
+ global $wpdb;
+
+ if ( ! is_multisite() && null !== $network_id ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: %s: $network_id */
+ __( 'Unable to pass %s if not using multisite.' ),
+ '<code>$network_id</code>'
+ ),
+ '6.0.0'
+ );
+ }
+
+ $query = "SELECT COUNT(ID) as c FROM $wpdb->users";
+ if ( is_multisite() ) {
+ $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.
+ *
+ * @since 6.0.0
+ */
+function wp_schedule_update_user_counts() {
+ if ( ! is_main_site() ) {
+ return;
+ }
+
+ 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.
+ *
+ * @since 6.0.0
+ *
+ * @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 ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ sprintf(
+ /* translators: %s: $network_id */
+ __( 'Unable to pass %s if not using multisite.' ),
+ '<code>$network_id</code>'
+ ),
+ '6.0.0'
+ );
+ }
+
+ $count = get_user_count( $network_id );
+
+ /**
+ * Filters whether the site is considered large, based on its number of users.
+ *
+ * @since 6.0.0
+ *
+ * @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.
//
/**
- * Set up global user vars.
+ * Sets up global user vars.
*
* Used by wp_set_current_user() for back compat. Might be deprecated in the future.
*
@@ -1235,7 +1499,7 @@
}
/**
- * Create dropdown HTML content of users.
+ * Creates dropdown HTML content of users.
*
* The content can either be displayed, which it is by default or retrieved by
* setting the 'echo' argument. The 'include' and 'exclude' arguments do not
@@ -1320,13 +1584,32 @@
'role' => '',
'role__in' => array(),
'role__not_in' => array(),
+ 'capability' => '',
+ '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( $parsed_args, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who', 'role', 'role__in', 'role__not_in' ) );
+ $query_args = wp_array_slice_assoc(
+ $parsed_args,
+ array(
+ 'blog_id',
+ 'include',
+ 'exclude',
+ 'orderby',
+ 'order',
+ 'who',
+ 'role',
+ 'role__in',
+ 'role__not_in',
+ 'capability',
+ 'capability__in',
+ 'capability__not_in',
+ )
+ );
$fields = array( 'ID', 'user_login' );
@@ -1426,7 +1709,7 @@
}
/**
- * Sanitize user field based on context.
+ * 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'
@@ -1544,7 +1827,7 @@
}
/**
- * Update all user caches
+ * Updates all user caches.
*
* @since 3.0.0
*
@@ -1567,7 +1850,7 @@
}
/**
- * Clean all user caches
+ * Cleans all user caches.
*
* @since 3.0.0
* @since 4.4.0 'clean_user_cache' action was added.
@@ -1700,7 +1983,7 @@
}
/**
- * Insert a user into the database.
+ * Inserts a user into the database.
*
* Most of the `$userdata` array fields have filters associated with the values. Exceptions are
* 'ID', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl',
@@ -1711,9 +1994,10 @@
* @since 2.0.0
* @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact
* methods for new installations. See wp_get_user_contact_methods().
- * @since 4.7.0 The user's locale can be passed to `$userdata`.
+ * @since 4.7.0 The `locale` field can be passed to `$userdata`.
* @since 5.3.0 The `user_activation_key` field can be passed to `$userdata`.
* @since 5.3.0 The `spam` field can be passed to `$userdata` (Multisite only).
+ * @since 5.9.0 The `meta_input` field can be passed to `$userdata` to allow addition of user meta data.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
@@ -1749,7 +2033,7 @@
* @type string $admin_color Admin color scheme for the user. Default 'fresh'.
* @type bool $use_ssl Whether the user should always access the admin over
* https. Default false.
- * @type string $user_registered Date the user registered. Format is 'Y-m-d H:i:s'.
+ * @type string $user_registered Date the user registered in UTC. Format is 'Y-m-d H:i:s'.
* @type string $user_activation_key Password reset key. Default empty.
* @type bool $spam Multisite only. Whether the user is marked as spam.
* Default false.
@@ -1758,6 +2042,8 @@
* as a string literal, not boolean. Default 'true'.
* @type string $role User's role.
* @type string $locale User's locale. Default empty.
+ * @type array $meta_input Array of custom user meta values keyed by meta key.
+ * Default empty.
* }
* @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not
* be created.
@@ -1773,9 +2059,9 @@
// Are we updating or creating?
if ( ! empty( $userdata['ID'] ) ) {
- $ID = (int) $userdata['ID'];
+ $user_id = (int) $userdata['ID'];
$update = true;
- $old_user_data = get_userdata( $ID );
+ $old_user_data = get_userdata( $user_id );
if ( ! $old_user_data ) {
return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
@@ -1835,9 +2121,6 @@
*/
if ( ! empty( $userdata['user_nicename'] ) ) {
$user_nicename = sanitize_user( $userdata['user_nicename'], true );
- if ( mb_strlen( $user_nicename ) > 50 ) {
- return new WP_Error( 'user_nicename_too_long', __( 'Nicename may not be longer than 50 characters.' ) );
- }
} else {
$user_nicename = mb_substr( $user_login, 0, 50 );
}
@@ -1853,6 +2136,10 @@
*/
$user_nicename = apply_filters( 'pre_user_nicename', $user_nicename );
+ if ( mb_strlen( $user_nicename ) > 50 ) {
+ return new WP_Error( 'user_nicename_too_long', __( 'Nicename may not be longer than 50 characters.' ) );
+ }
+
$user_nicename_check = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1", $user_nicename, $user_login ) );
if ( $user_nicename_check ) {
@@ -1901,6 +2188,10 @@
*/
$user_url = apply_filters( 'pre_user_url', $raw_user_url );
+ if ( mb_strlen( $user_url ) > 100 ) {
+ return new WP_Error( 'user_url_too_long', __( 'User URL may not be longer than 100 characters.' ) );
+ }
+
$user_registered = empty( $userdata['user_registered'] ) ? gmdate( 'Y-m-d H:i:s' ) : $userdata['user_registered'];
$user_activation_key = empty( $userdata['user_activation_key'] ) ? '' : $userdata['user_activation_key'];
@@ -2016,7 +2307,7 @@
* It only includes data in the users table, not any user metadata.
*
* @since 4.9.0
- * @since 5.8.0 The $userdata parameter was added.
+ * @since 5.8.0 The `$userdata` parameter was added.
*
* @param array $data {
* Values and keys for the user.
@@ -2031,10 +2322,10 @@
* the current UTC timestamp.
* }
* @param bool $update Whether the user is being updated rather than created.
- * @param int|null $id ID of the user to be updated, or NULL if the user is being created.
+ * @param int|null $user_id ID of the user to be updated, or NULL if the user is being created.
* @param array $userdata The raw array of data passed to wp_insert_user().
*/
- $data = apply_filters( 'wp_pre_insert_user_data', $data, $update, ( $update ? (int) $ID : null ), $userdata );
+ $data = apply_filters( 'wp_pre_insert_user_data', $data, $update, ( $update ? $user_id : null ), $userdata );
if ( empty( $data ) || ! is_array( $data ) ) {
return new WP_Error( 'empty_data', __( 'Not enough data to create this user.' ) );
@@ -2044,8 +2335,7 @@
if ( $user_email !== $old_user_data->user_email || $user_pass !== $old_user_data->user_pass ) {
$data['user_activation_key'] = '';
}
- $wpdb->update( $wpdb->users, $data, compact( 'ID' ) );
- $user_id = (int) $ID;
+ $wpdb->update( $wpdb->users, $data, array( 'ID' => $user_id ) );
} else {
$wpdb->insert( $wpdb->users, $data );
$user_id = (int) $wpdb->insert_id;
@@ -2059,8 +2349,10 @@
*
* Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`.
*
+ * For custom meta fields, see the {@see 'insert_custom_user_meta'} filter.
+ *
* @since 4.4.0
- * @since 5.8.0 The $userdata parameter was added.
+ * @since 5.8.0 The `$userdata` parameter was added.
*
* @param array $meta {
* Default meta values and keys for the user.
@@ -2085,6 +2377,28 @@
*/
$meta = apply_filters( 'insert_user_meta', $meta, $user, $update, $userdata );
+ $custom_meta = array();
+ if ( array_key_exists( 'meta_input', $userdata ) && is_array( $userdata['meta_input'] ) && ! empty( $userdata['meta_input'] ) ) {
+ $custom_meta = $userdata['meta_input'];
+ }
+
+ /**
+ * Filters a user's custom meta values and keys immediately after the user is created or updated
+ * and before any user meta is inserted or updated.
+ *
+ * For non-custom meta fields, see the {@see 'insert_user_meta'} filter.
+ *
+ * @since 5.9.0
+ *
+ * @param array $custom_meta Array of custom user meta values keyed by meta key.
+ * @param WP_User $user User object.
+ * @param bool $update Whether the user is being updated rather than created.
+ * @param array $userdata The raw array of data passed to wp_insert_user().
+ */
+ $custom_meta = apply_filters( 'insert_custom_user_meta', $custom_meta, $user, $update, $userdata );
+
+ $meta = array_merge( $meta, $custom_meta );
+
// Update user meta.
foreach ( $meta as $key => $value ) {
update_user_meta( $user_id, $key, $value );
@@ -2109,7 +2423,7 @@
* Fires immediately after an existing user is updated.
*
* @since 2.0.0
- * @since 5.8.0 The $userdata parameter was added.
+ * @since 5.8.0 The `$userdata` parameter was added.
*
* @param int $user_id User ID.
* @param WP_User $old_user_data Object containing user's data prior to update.
@@ -2143,7 +2457,7 @@
* Fires immediately after a new user is registered.
*
* @since 1.5.0
- * @since 5.8.0 The $userdata parameter was added.
+ * @since 5.8.0 The `$userdata` parameter was added.
*
* @param int $user_id User ID.
* @param array $userdata The raw array of data passed to wp_insert_user().
@@ -2155,7 +2469,7 @@
}
/**
- * Update a user in the database.
+ * Updates a user in the database.
*
* It is possible to update a user's password by specifying the 'user_pass'
* value in the $userdata parameter array.
@@ -2177,13 +2491,13 @@
$userdata = $userdata->to_array();
}
- $ID = isset( $userdata['ID'] ) ? (int) $userdata['ID'] : 0;
- if ( ! $ID ) {
+ $user_id = isset( $userdata['ID'] ) ? (int) $userdata['ID'] : 0;
+ if ( ! $user_id ) {
return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
}
// First, get all of the original fields.
- $user_obj = get_userdata( $ID );
+ $user_obj = get_userdata( $user_id );
if ( ! $user_obj ) {
return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
}
@@ -2192,7 +2506,7 @@
// Add additional custom fields.
foreach ( _get_additional_user_keys( $user_obj ) as $key ) {
- $user[ $key ] = get_user_meta( $ID, $key, true );
+ $user[ $key ] = get_user_meta( $user_id, $key, true );
}
// Escape data pulled from DB.
@@ -2238,19 +2552,21 @@
$userdata = array_merge( $user, $userdata );
$user_id = wp_insert_user( $userdata );
- if ( ! is_wp_error( $user_id ) ) {
-
- $blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
-
- $switched_locale = false;
- if ( ! empty( $send_password_change_email ) || ! empty( $send_email_change_email ) ) {
- $switched_locale = switch_to_locale( get_user_locale( $user_id ) );
- }
-
- if ( ! empty( $send_password_change_email ) ) {
- /* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
- $pass_change_text = __(
- 'Hi ###USERNAME###,
+ if ( is_wp_error( $user_id ) ) {
+ return $user_id;
+ }
+
+ $blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
+
+ $switched_locale = false;
+ if ( ! empty( $send_password_change_email ) || ! empty( $send_email_change_email ) ) {
+ $switched_locale = switch_to_locale( get_user_locale( $user_id ) );
+ }
+
+ if ( ! empty( $send_password_change_email ) ) {
+ /* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
+ $pass_change_text = __(
+ 'Hi ###USERNAME###,
This notice confirms that your password was changed on ###SITENAME###.
@@ -2262,53 +2578,53 @@
Regards,
All at ###SITENAME###
###SITEURL###'
- );
-
- $pass_change_email = array(
- 'to' => $user['user_email'],
- /* translators: Password change notification email subject. %s: Site title. */
- 'subject' => __( '[%s] Password Changed' ),
- 'message' => $pass_change_text,
- 'headers' => '',
- );
-
- /**
- * Filters the contents of the email sent when the user's password is changed.
- *
- * @since 4.3.0
- *
- * @param array $pass_change_email {
- * Used to build wp_mail().
- *
- * @type string $to The intended recipients. Add emails in a comma separated string.
- * @type string $subject The subject of the email.
- * @type string $message The content of the email.
- * The following strings have a special meaning and will get replaced dynamically:
- * - ###USERNAME### The current user's username.
- * - ###ADMIN_EMAIL### The admin email in case this was unexpected.
- * - ###EMAIL### The user's email address.
- * - ###SITENAME### The name of the site.
- * - ###SITEURL### The URL to the site.
- * @type string $headers Headers. Add headers in a newline (\r\n) separated string.
- * }
- * @param array $user The original user array.
- * @param array $userdata The updated user array.
- */
- $pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
-
- $pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] );
- $pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] );
- $pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] );
- $pass_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $pass_change_email['message'] );
- $pass_change_email['message'] = str_replace( '###SITEURL###', home_url(), $pass_change_email['message'] );
-
- wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] );
- }
-
- if ( ! empty( $send_email_change_email ) ) {
- /* translators: Do not translate USERNAME, ADMIN_EMAIL, NEW_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
- $email_change_text = __(
- 'Hi ###USERNAME###,
+ );
+
+ $pass_change_email = array(
+ 'to' => $user['user_email'],
+ /* translators: Password change notification email subject. %s: Site title. */
+ 'subject' => __( '[%s] Password Changed' ),
+ 'message' => $pass_change_text,
+ 'headers' => '',
+ );
+
+ /**
+ * Filters the contents of the email sent when the user's password is changed.
+ *
+ * @since 4.3.0
+ *
+ * @param array $pass_change_email {
+ * Used to build wp_mail().
+ *
+ * @type string $to The intended recipients. Add emails in a comma separated string.
+ * @type string $subject The subject of the email.
+ * @type string $message The content of the email.
+ * The following strings have a special meaning and will get replaced dynamically:
+ * - ###USERNAME### The current user's username.
+ * - ###ADMIN_EMAIL### The admin email in case this was unexpected.
+ * - ###EMAIL### The user's email address.
+ * - ###SITENAME### The name of the site.
+ * - ###SITEURL### The URL to the site.
+ * @type string $headers Headers. Add headers in a newline (\r\n) separated string.
+ * }
+ * @param array $user The original user array.
+ * @param array $userdata The updated user array.
+ */
+ $pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
+
+ $pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] );
+ $pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] );
+ $pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] );
+ $pass_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $pass_change_email['message'] );
+ $pass_change_email['message'] = str_replace( '###SITEURL###', home_url(), $pass_change_email['message'] );
+
+ wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] );
+ }
+
+ if ( ! empty( $send_email_change_email ) ) {
+ /* translators: Do not translate USERNAME, ADMIN_EMAIL, NEW_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
+ $email_change_text = __(
+ 'Hi ###USERNAME###,
This notice confirms that your email address on ###SITENAME### was changed to ###NEW_EMAIL###.
@@ -2320,59 +2636,58 @@
Regards,
All at ###SITENAME###
###SITEURL###'
- );
-
- $email_change_email = array(
- 'to' => $user['user_email'],
- /* translators: Email change notification email subject. %s: Site title. */
- 'subject' => __( '[%s] Email Changed' ),
- 'message' => $email_change_text,
- 'headers' => '',
- );
-
- /**
- * Filters the contents of the email sent when the user's email is changed.
- *
- * @since 4.3.0
- *
- * @param array $email_change_email {
- * Used to build wp_mail().
- *
- * @type string $to The intended recipients.
- * @type string $subject The subject of the email.
- * @type string $message The content of the email.
- * The following strings have a special meaning and will get replaced dynamically:
- * - ###USERNAME### The current user's username.
- * - ###ADMIN_EMAIL### The admin email in case this was unexpected.
- * - ###NEW_EMAIL### The new email address.
- * - ###EMAIL### The old email address.
- * - ###SITENAME### The name of the site.
- * - ###SITEURL### The URL to the site.
- * @type string $headers Headers.
- * }
- * @param array $user The original user array.
- * @param array $userdata The updated user array.
- */
- $email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
-
- $email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] );
- $email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] );
- $email_change_email['message'] = str_replace( '###NEW_EMAIL###', $userdata['user_email'], $email_change_email['message'] );
- $email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] );
- $email_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $email_change_email['message'] );
- $email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );
-
- wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] );
- }
-
- if ( $switched_locale ) {
- restore_previous_locale();
- }
+ );
+
+ $email_change_email = array(
+ 'to' => $user['user_email'],
+ /* translators: Email change notification email subject. %s: Site title. */
+ 'subject' => __( '[%s] Email Changed' ),
+ 'message' => $email_change_text,
+ 'headers' => '',
+ );
+
+ /**
+ * Filters the contents of the email sent when the user's email is changed.
+ *
+ * @since 4.3.0
+ *
+ * @param array $email_change_email {
+ * Used to build wp_mail().
+ *
+ * @type string $to The intended recipients.
+ * @type string $subject The subject of the email.
+ * @type string $message The content of the email.
+ * The following strings have a special meaning and will get replaced dynamically:
+ * - ###USERNAME### The current user's username.
+ * - ###ADMIN_EMAIL### The admin email in case this was unexpected.
+ * - ###NEW_EMAIL### The new email address.
+ * - ###EMAIL### The old email address.
+ * - ###SITENAME### The name of the site.
+ * - ###SITEURL### The URL to the site.
+ * @type string $headers Headers.
+ * }
+ * @param array $user The original user array.
+ * @param array $userdata The updated user array.
+ */
+ $email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
+
+ $email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] );
+ $email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] );
+ $email_change_email['message'] = str_replace( '###NEW_EMAIL###', $userdata['user_email'], $email_change_email['message'] );
+ $email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] );
+ $email_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $email_change_email['message'] );
+ $email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );
+
+ wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] );
+ }
+
+ if ( $switched_locale ) {
+ restore_previous_locale();
}
// Update the cookies if the password changed.
$current_user = wp_get_current_user();
- if ( $current_user->ID == $ID ) {
+ if ( $current_user->ID == $user_id ) {
if ( isset( $plaintext_pass ) ) {
wp_clear_auth_cookie();
@@ -2380,13 +2695,13 @@
// If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
$logged_in_cookie = wp_parse_auth_cookie( '', 'logged_in' );
/** This filter is documented in wp-includes/pluggable.php */
- $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $ID, false );
+ $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $user_id, false );
$remember = false;
if ( false !== $logged_in_cookie && ( $logged_in_cookie['expiration'] - time() ) > $default_cookie_life ) {
$remember = true;
}
- wp_set_auth_cookie( $ID, $remember );
+ wp_set_auth_cookie( $user_id, $remember );
}
}
@@ -2394,7 +2709,7 @@
}
/**
- * A simpler way of inserting a user into the database.
+ * Provides a simpler way of inserting a user into the database.
*
* Creates a new user with just the username, password, and email. For more
* complex user creation use wp_insert_user() to specify more information.
@@ -2436,13 +2751,13 @@
}
/**
- * Set up the user contact methods.
+ * Sets up the user contact methods.
*
* Default contact methods were removed in 3.6. A filter dictates contact methods.
*
* @since 3.7.0
*
- * @param WP_User $user Optional. WP_User object.
+ * @param WP_User|null $user Optional. WP_User object.
* @return string[] Array of contact method labels keyed by contact method.
*/
function wp_get_user_contact_methods( $user = null ) {
@@ -2460,8 +2775,8 @@
*
* @since 2.9.0
*
- * @param string[] $methods Array of contact method labels keyed by contact method.
- * @param WP_User $user WP_User object.
+ * @param string[] $methods Array of contact method labels keyed by contact method.
+ * @param WP_User|null $user WP_User object or null if none was provided.
*/
return apply_filters( 'user_contactmethods', $methods, $user );
}
@@ -2474,7 +2789,7 @@
* @since 2.9.0
* @access private
*
- * @param WP_User $user Optional. WP_User object. Default null.
+ * @param WP_User|null $user Optional. WP_User object. Default null.
* @return string[] Array of contact method labels keyed by contact method.
*/
function _wp_get_user_contactmethods( $user = null ) {
@@ -2549,8 +2864,8 @@
*
* @since 2.7.0
*
- * @param bool $allow Whether to allow the password to be reset. Default true.
- * @param int $ID The ID of the user attempting to reset a password.
+ * @param bool $allow Whether to allow the password to be reset. Default true.
+ * @param int $user_id The ID of the user attempting to reset a password.
*/
$allow = apply_filters( 'allow_password_reset', $allow, $user->ID );
@@ -2596,7 +2911,7 @@
}
/**
- * Retrieves a user row based on password reset key and login
+ * Retrieves a user row based on password reset key and login.
*
* A key is considered 'expired' if it exactly matches the value of the
* user_activation_key field, rather than being matched after going through the
@@ -2772,6 +3087,21 @@
return $errors;
}
+ /**
+ * Filters whether to send the retrieve password email.
+ *
+ * Return false to disable sending the email.
+ *
+ * @since 6.0.0
+ *
+ * @param bool $send Whether to send the email.
+ * @param string $user_login The username for the user.
+ * @param WP_User $user_data WP_User object.
+ */
+ if ( ! apply_filters( 'send_retrieve_password_email', true, $user_login, $user_data ) ) {
+ return true;
+ }
+
// Redefining user_login ensures we return the right case in the email.
$user_login = $user_data->user_login;
$user_email = $user_data->user_email;
@@ -2846,11 +3176,57 @@
*/
$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
+ // Short-circuit on falsey $message value for backwards compatibility.
+ if ( ! $message ) {
+ return true;
+ }
+
+ /*
+ * Wrap the single notification email arguments in an array
+ * to pass them to the retrieve_password_notification_email filter.
+ */
+ $defaults = array(
+ 'to' => $user_email,
+ 'subject' => $title,
+ 'message' => $message,
+ 'headers' => '',
+ );
+
+ /**
+ * Filters the contents of the reset password notification email sent to the user.
+ *
+ * @since 6.0.0
+ *
+ * @param array $defaults {
+ * The default notification email arguments. Used to build wp_mail().
+ *
+ * @type string $to The intended recipient - user email address.
+ * @type string $subject The subject of the email.
+ * @type string $message The body of the email.
+ * @type string $headers The headers of the email.
+ * }
+ * @type string $key The activation key.
+ * @type string $user_login The username for the user.
+ * @type WP_User $user_data WP_User object.
+ */
+ $notification_email = apply_filters( 'retrieve_password_notification_email', $defaults, $key, $user_login, $user_data );
+
if ( $switched_locale ) {
restore_previous_locale();
}
- if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
+ if ( is_array( $notification_email ) ) {
+ // Force key order and merge defaults in case any value is missing in the filtered array.
+ $notification_email = array_merge( $defaults, $notification_email );
+ } else {
+ $notification_email = $defaults;
+ }
+
+ list( $to, $subject, $message, $headers ) = array_values( $notification_email );
+
+ $subject = wp_specialchars_decode( $subject );
+
+ if ( ! wp_mail( $to, $subject, $message, $headers ) ) {
$errors->add(
'retrieve_password_email_failure',
sprintf(
@@ -2941,10 +3317,17 @@
if ( '' === $user_email ) {
$errors->add( 'empty_email', __( '<strong>Error</strong>: Please type your email address.' ) );
} elseif ( ! is_email( $user_email ) ) {
- $errors->add( 'invalid_email', __( '<strong>Error</strong>: The email address isn’t correct.' ) );
+ $errors->add( 'invalid_email', __( '<strong>Error</strong>: The email address is not correct.' ) );
$user_email = '';
} elseif ( email_exists( $user_email ) ) {
- $errors->add( 'email_exists', __( '<strong>Error</strong>: This email is already registered. Please choose another one.' ) );
+ $errors->add(
+ 'email_exists',
+ sprintf(
+ /* translators: %s: Link to the login page. */
+ __( '<strong>Error:</strong> This email address is already registered. <a href="%s">Log in</a> with this address or choose another one.' ),
+ wp_login_url()
+ )
+ );
}
/**
@@ -2989,7 +3372,7 @@
'registerfail',
sprintf(
/* translators: %s: Admin email address. */
- __( '<strong>Error</strong>: Couldn’t register you… please contact the <a href="mailto:%s">site admin</a>!' ),
+ __( '<strong>Error</strong>: Could not register you… please contact the <a href="mailto:%s">site admin</a>!' ),
get_option( 'admin_email' )
)
);
@@ -2998,6 +3381,13 @@
update_user_meta( $user_id, 'default_password_nag', true ); // Set up the password change nag.
+ if ( ! empty( $_COOKIE['wp_lang'] ) ) {
+ $wp_lang = sanitize_text_field( $_COOKIE['wp_lang'] );
+ if ( in_array( $wp_lang, get_available_languages(), true ) ) {
+ update_user_meta( $user_id, 'locale', $wp_lang ); // Set user locale if defined on registration.
+ }
+ }
+
/**
* Fires after a new user registration has been recorded.
*
@@ -3029,7 +3419,7 @@
}
/**
- * Retrieve the current session token from the logged_in cookie.
+ * Retrieves the current session token from the logged_in cookie.
*
* @since 4.0.0
*
@@ -3041,7 +3431,7 @@
}
/**
- * Retrieve a list of sessions for the current user.
+ * Retrieves a list of sessions for the current user.
*
* @since 4.0.0
*
@@ -3053,7 +3443,7 @@
}
/**
- * Remove the current session token from the database.
+ * Removes the current session token from the database.
*
* @since 4.0.0
*/
@@ -3066,7 +3456,7 @@
}
/**
- * Remove all but the current session token for the current user for the database.
+ * Removes all but the current session token for the current user for the database.
*
* @since 4.0.0
*/
@@ -3079,7 +3469,7 @@
}
/**
- * Remove all session tokens for the current user from the database.
+ * Removes all session tokens for the current user from the database.
*
* @since 4.0.0
*/
@@ -3089,7 +3479,7 @@
}
/**
- * Get the user IDs of all users with no role on this site.
+ * Gets the user IDs of all users with no role on this site.
*
* @since 4.4.0
* @since 4.9.0 The `$site_id` parameter was added to support multisite.
@@ -3202,7 +3592,7 @@
}
/**
- * Send a confirmation request email when a change of user email address is attempted.
+ * Sends a confirmation request email when a change of user email address is attempted.
*
* @since 3.0.0
* @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific.
@@ -3225,7 +3615,7 @@
if ( ! is_email( $_POST['email'] ) ) {
$errors->add(
'user_email',
- __( '<strong>Error</strong>: The email address isn’t correct.' ),
+ __( '<strong>Error</strong>: The email address is not correct.' ),
array(
'form-field' => 'email',
)
@@ -3318,7 +3708,7 @@
* @since 3.0.0
* @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific.
*
- * @global string $pagenow
+ * @global string $pagenow The filename of the current screen.
*/
function new_user_email_admin_notice() {
global $pagenow;
@@ -3333,7 +3723,7 @@
}
/**
- * Get all personal data request types.
+ * Gets all personal data request types.
*
* @since 4.9.6
* @access private
@@ -3439,7 +3829,7 @@
$reserved_names = array_values( $user_props_to_export );
/**
- * Filter to extend the user's profile data for the privacy exporter.
+ * Filters the user's profile data for the privacy exporter.
*
* @since 5.4.0
*
@@ -3459,7 +3849,7 @@
// Remove items that use reserved names.
$extra_data = array_filter(
$_extra_data,
- function( $item ) use ( $reserved_names ) {
+ static function( $item ) use ( $reserved_names ) {
return ! in_array( $item['name'], $reserved_names, true );
}
);
@@ -3563,7 +3953,7 @@
}
/**
- * Update log when privacy request is confirmed.
+ * Updates log when privacy request is confirmed.
*
* @since 4.9.6
* @access private
@@ -3591,7 +3981,7 @@
}
/**
- * Notify the site administrator via email when a request is confirmed.
+ * Notifies the site administrator via email when a request is confirmed.
*
* Without this, the admin would have to manually check the site to see if any
* action was needed on their part yet.
@@ -3804,7 +4194,7 @@
}
/**
- * Notify the user when their erasure request is fulfilled.
+ * Notifies the user when their erasure request is fulfilled.
*
* Without this, the user would never know if their data was actually erased.
*
@@ -4077,7 +4467,7 @@
}
/**
- * Return request confirmation message HTML.
+ * Returns request confirmation message HTML.
*
* @since 4.9.6
* @access private
@@ -4115,7 +4505,7 @@
}
/**
- * Create and log a user request to perform a specific action.
+ * Creates and logs a user request to perform a specific action.
*
* Requests are stored inside a post type named `user_request` since they can apply to both
* users on the site, or guests without a user account.
@@ -4186,7 +4576,7 @@
}
/**
- * Get action description from the name and return a string.
+ * Gets action description from the name and return a string.
*
* @since 4.9.6
*
@@ -4404,7 +4794,7 @@
}
/**
- * Validate a user request by comparing the key with the request's key.
+ * Validates a user request by comparing the key with the request's key.
*
* @since 4.9.6
*
@@ -4459,7 +4849,7 @@
}
/**
- * Return the user request object for the specified request ID.
+ * Returns the user request object for the specified request ID.
*
* @since 4.9.6
*
@@ -4478,18 +4868,30 @@
}
/**
+ * Checks if Application Passwords is supported.
+ *
+ * Application Passwords is supported only by sites using SSL or local environments
+ * but may be made available using the {@see 'wp_is_application_passwords_available'} filter.
+ *
+ * @since 5.9.0
+ *
+ * @return bool
+ */
+function wp_is_application_passwords_supported() {
+ return is_ssl() || 'local' === wp_get_environment_type();
+}
+
+/**
* Checks if Application Passwords is globally available.
*
* By default, Application Passwords is available to all sites using SSL or to local environments.
- * Use {@see 'wp_is_application_passwords_available'} to adjust its availability.
+ * Use the {@see 'wp_is_application_passwords_available'} filter to adjust its availability.
*
* @since 5.6.0
*
* @return bool
*/
function wp_is_application_passwords_available() {
- $available = is_ssl() || 'local' === wp_get_environment_type();
-
/**
* Filters whether Application Passwords is available.
*
@@ -4497,7 +4899,7 @@
*
* @param bool $available True if available, false otherwise.
*/
- return apply_filters( 'wp_is_application_passwords_available', $available );
+ return apply_filters( 'wp_is_application_passwords_available', wp_is_application_passwords_supported() );
}
/**