wp/wp-includes/user.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
   147 	$user = get_user_by( 'login', $username );
   147 	$user = get_user_by( 'login', $username );
   148 
   148 
   149 	if ( ! $user ) {
   149 	if ( ! $user ) {
   150 		return new WP_Error(
   150 		return new WP_Error(
   151 			'invalid_username',
   151 			'invalid_username',
   152 			__( 'Unknown username. Check again or try your email address.' )
   152 			sprintf(
       
   153 				/* translators: %s: User name. */
       
   154 				__( '<strong>Error</strong>: The username <strong>%s</strong> is not registered on this site. If you are unsure of your username, try your email address instead.' ),
       
   155 				$username
       
   156 			)
   153 		);
   157 		);
   154 	}
   158 	}
   155 
   159 
   156 	/**
   160 	/**
   157 	 * Filters whether the given user can be authenticated with the provided $password.
   161 	 * Filters whether the given user can be authenticated with the provided $password.
   296 
   300 
   297 	return $user;
   301 	return $user;
   298 }
   302 }
   299 
   303 
   300 /**
   304 /**
       
   305  * Authenticates the user using an application password.
       
   306  *
       
   307  * @since 5.6.0
       
   308  *
       
   309  * @param WP_User|WP_Error|null $input_user WP_User or WP_Error object if a previous
       
   310  *                                          callback failed authentication.
       
   311  * @param string                $username   Username for authentication.
       
   312  * @param string                $password   Password for authentication.
       
   313  * @return WP_User|WP_Error|null WP_User on success, WP_Error on failure, null if
       
   314  *                               null is passed in and this isn't an API request.
       
   315  */
       
   316 function wp_authenticate_application_password( $input_user, $username, $password ) {
       
   317 	if ( $input_user instanceof WP_User ) {
       
   318 		return $input_user;
       
   319 	}
       
   320 
       
   321 	if ( ! WP_Application_Passwords::is_in_use() ) {
       
   322 		return $input_user;
       
   323 	}
       
   324 
       
   325 	$is_api_request = ( ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) );
       
   326 
       
   327 	/**
       
   328 	 * Filters whether this is an API request that Application Passwords can be used on.
       
   329 	 *
       
   330 	 * By default, Application Passwords is available for the REST API and XML-RPC.
       
   331 	 *
       
   332 	 * @since 5.6.0
       
   333 	 *
       
   334 	 * @param bool $is_api_request If this is an acceptable API request.
       
   335 	 */
       
   336 	$is_api_request = apply_filters( 'application_password_is_api_request', $is_api_request );
       
   337 
       
   338 	if ( ! $is_api_request ) {
       
   339 		return $input_user;
       
   340 	}
       
   341 
       
   342 	$error = null;
       
   343 	$user  = get_user_by( 'login', $username );
       
   344 
       
   345 	if ( ! $user && is_email( $username ) ) {
       
   346 		$user = get_user_by( 'email', $username );
       
   347 	}
       
   348 
       
   349 	// If the login name is invalid, short circuit.
       
   350 	if ( ! $user ) {
       
   351 		if ( is_email( $username ) ) {
       
   352 			$error = new WP_Error(
       
   353 				'invalid_email',
       
   354 				__( '<strong>Error</strong>: Unknown email address. Check again or try your username.' )
       
   355 			);
       
   356 		} else {
       
   357 			$error = new WP_Error(
       
   358 				'invalid_username',
       
   359 				__( '<strong>Error</strong>: Unknown username. Check again or try your email address.' )
       
   360 			);
       
   361 		}
       
   362 	} elseif ( ! wp_is_application_passwords_available() ) {
       
   363 		$error = new WP_Error(
       
   364 			'application_passwords_disabled',
       
   365 			__( 'Application passwords are not available.' )
       
   366 		);
       
   367 	} elseif ( ! wp_is_application_passwords_available_for_user( $user ) ) {
       
   368 		$error = new WP_Error(
       
   369 			'application_passwords_disabled_for_user',
       
   370 			__( 'Application passwords are not available for your account. Please contact the site administrator for assistance.' )
       
   371 		);
       
   372 	}
       
   373 
       
   374 	if ( $error ) {
       
   375 		/**
       
   376 		 * Fires when an application password failed to authenticate the user.
       
   377 		 *
       
   378 		 * @since 5.6.0
       
   379 		 *
       
   380 		 * @param WP_Error $error The authentication error.
       
   381 		 */
       
   382 		do_action( 'application_password_failed_authentication', $error );
       
   383 
       
   384 		return $error;
       
   385 	}
       
   386 
       
   387 	/*
       
   388 	 * Strip out anything non-alphanumeric. This is so passwords can be used with
       
   389 	 * or without spaces to indicate the groupings for readability.
       
   390 	 *
       
   391 	 * Generated application passwords are exclusively alphanumeric.
       
   392 	 */
       
   393 	$password = preg_replace( '/[^a-z\d]/i', '', $password );
       
   394 
       
   395 	$hashed_passwords = WP_Application_Passwords::get_user_application_passwords( $user->ID );
       
   396 
       
   397 	foreach ( $hashed_passwords as $key => $item ) {
       
   398 		if ( ! wp_check_password( $password, $item['password'], $user->ID ) ) {
       
   399 			continue;
       
   400 		}
       
   401 
       
   402 		$error = new WP_Error();
       
   403 
       
   404 		/**
       
   405 		 * Fires when an application password has been successfully checked as valid.
       
   406 		 *
       
   407 		 * This allows for plugins to add additional constraints to prevent an application password from being used.
       
   408 		 *
       
   409 		 * @since 5.6.0
       
   410 		 *
       
   411 		 * @param WP_Error $error    The error object.
       
   412 		 * @param WP_User  $user     The user authenticating.
       
   413 		 * @param array    $item     The details about the application password.
       
   414 		 * @param string   $password The raw supplied password.
       
   415 		 */
       
   416 		do_action( 'wp_authenticate_application_password_errors', $error, $user, $item, $password );
       
   417 
       
   418 		if ( is_wp_error( $error ) && $error->has_errors() ) {
       
   419 			/** This action is documented in wp-includes/user.php */
       
   420 			do_action( 'application_password_failed_authentication', $error );
       
   421 
       
   422 			return $error;
       
   423 		}
       
   424 
       
   425 		WP_Application_Passwords::record_application_password_usage( $user->ID, $item['uuid'] );
       
   426 
       
   427 		/**
       
   428 		 * Fires after an application password was used for authentication.
       
   429 		 *
       
   430 		 * @since 5.6.0
       
   431 		 *
       
   432 		 * @param WP_User $user The user who was authenticated.
       
   433 		 * @param array   $item The application password used.
       
   434 		 */
       
   435 		do_action( 'application_password_did_authenticate', $user, $item );
       
   436 
       
   437 		return $user;
       
   438 	}
       
   439 
       
   440 	$error = new WP_Error(
       
   441 		'incorrect_password',
       
   442 		__( 'The provided password is an invalid application password.' )
       
   443 	);
       
   444 
       
   445 	/** This action is documented in wp-includes/user.php */
       
   446 	do_action( 'application_password_failed_authentication', $error );
       
   447 
       
   448 	return $error;
       
   449 }
       
   450 
       
   451 /**
       
   452  * Validates the application password credentials passed via Basic Authentication.
       
   453  *
       
   454  * @since 5.6.0
       
   455  *
       
   456  * @param int|false $input_user User ID if one has been determined, false otherwise.
       
   457  * @return int|false The authenticated user ID if successful, false otherwise.
       
   458  */
       
   459 function wp_validate_application_password( $input_user ) {
       
   460 	// Don't authenticate twice.
       
   461 	if ( ! empty( $input_user ) ) {
       
   462 		return $input_user;
       
   463 	}
       
   464 
       
   465 	if ( ! wp_is_application_passwords_available() ) {
       
   466 		return $input_user;
       
   467 	}
       
   468 
       
   469 	// Both $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] must be set in order to attempt authentication.
       
   470 	if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
       
   471 		return $input_user;
       
   472 	}
       
   473 
       
   474 	$authenticated = wp_authenticate_application_password( null, $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] );
       
   475 
       
   476 	if ( $authenticated instanceof WP_User ) {
       
   477 		return $authenticated->ID;
       
   478 	}
       
   479 
       
   480 	// If it wasn't a user what got returned, just pass on what we had received originally.
       
   481 	return $input_user;
       
   482 }
       
   483 
       
   484 /**
   301  * For Multisite blogs, check if the authenticated user has been marked as a
   485  * For Multisite blogs, check if the authenticated user has been marked as a
   302  * spammer, or if the user's primary blog has been marked as spam.
   486  * spammer, or if the user's primary blog has been marked as spam.
   303  *
   487  *
   304  * @since 3.7.0
   488  * @since 3.7.0
   305  *
   489  *
   333  *
   517  *
   334  * This is a callback for the {@see 'determine_current_user'} filter, rather than API.
   518  * This is a callback for the {@see 'determine_current_user'} filter, rather than API.
   335  *
   519  *
   336  * @since 3.9.0
   520  * @since 3.9.0
   337  *
   521  *
   338  * @param int|bool $user_id The user ID (or false) as received from
   522  * @param int|false $user_id The user ID (or false) as received from
   339  *                          the `determine_current_user` filter.
   523  *                           the `determine_current_user` filter.
   340  * @return int|false User ID if validated, false otherwise. If a user ID from
   524  * @return int|false User ID if validated, false otherwise. If a user ID from
   341  *                   an earlier filter callback is received, that value is returned.
   525  *                   an earlier filter callback is received, that value is returned.
   342  */
   526  */
   343 function wp_validate_logged_in_cookie( $user_id ) {
   527 function wp_validate_logged_in_cookie( $user_id ) {
   344 	if ( $user_id ) {
   528 	if ( $user_id ) {
   565  *
   749  *
   566  * @since 3.1.0
   750  * @since 3.1.0
   567  *
   751  *
   568  * @see WP_User_Query
   752  * @see WP_User_Query
   569  *
   753  *
   570  * @param array $args Optional. Arguments to retrieve users. See WP_User_Query::prepare_query().
   754  * @param array $args Optional. Arguments to retrieve users. See WP_User_Query::prepare_query()
   571  *                    for more information on accepted arguments.
   755  *                    for more information on accepted arguments.
   572  * @return array List of users.
   756  * @return array List of users.
   573  */
   757  */
   574 function get_users( $args = array() ) {
   758 function get_users( $args = array() ) {
   575 
   759 
   590  * @global wpdb $wpdb WordPress database abstraction object.
   774  * @global wpdb $wpdb WordPress database abstraction object.
   591  *
   775  *
   592  * @param int  $user_id User ID
   776  * @param int  $user_id User ID
   593  * @param bool $all     Whether to retrieve all sites, or only sites that are not
   777  * @param bool $all     Whether to retrieve all sites, or only sites that are not
   594  *                      marked as deleted, archived, or spam.
   778  *                      marked as deleted, archived, or spam.
   595  * @return array A list of the user's sites. An empty array if the user doesn't exist
   779  * @return object[] A list of the user's sites. An empty array if the user doesn't exist
   596  *               or belongs to no sites.
   780  *                  or belongs to no sites.
   597  */
   781  */
   598 function get_blogs_of_user( $user_id, $all = false ) {
   782 function get_blogs_of_user( $user_id, $all = false ) {
   599 	global $wpdb;
   783 	global $wpdb;
   600 
   784 
   601 	$user_id = (int) $user_id;
   785 	$user_id = (int) $user_id;
   611 	 * Returning a non-null value from the filter will effectively short circuit
   795 	 * Returning a non-null value from the filter will effectively short circuit
   612 	 * get_blogs_of_user(), returning that value instead.
   796 	 * get_blogs_of_user(), returning that value instead.
   613 	 *
   797 	 *
   614 	 * @since 4.6.0
   798 	 * @since 4.6.0
   615 	 *
   799 	 *
   616 	 * @param null|array $sites   An array of site objects of which the user is a member.
   800 	 * @param null|object[] $sites   An array of site objects of which the user is a member.
   617 	 * @param int        $user_id User ID.
   801 	 * @param int           $user_id User ID.
   618 	 * @param bool       $all     Whether the returned array should contain all sites, including
   802 	 * @param bool          $all     Whether the returned array should contain all sites, including
   619 	 *                            those marked 'deleted', 'archived', or 'spam'. Default false.
   803 	 *                               those marked 'deleted', 'archived', or 'spam'. Default false.
   620 	 */
   804 	 */
   621 	$sites = apply_filters( 'pre_get_blogs_of_user', null, $user_id, $all );
   805 	$sites = apply_filters( 'pre_get_blogs_of_user', null, $user_id, $all );
   622 
   806 
   623 	if ( null !== $sites ) {
   807 	if ( null !== $sites ) {
   624 		return $sites;
   808 		return $sites;
   703 	/**
   887 	/**
   704 	 * Filters the list of sites a user belongs to.
   888 	 * Filters the list of sites a user belongs to.
   705 	 *
   889 	 *
   706 	 * @since MU (3.0.0)
   890 	 * @since MU (3.0.0)
   707 	 *
   891 	 *
   708 	 * @param array $sites   An array of site objects belonging to the user.
   892 	 * @param object[] $sites   An array of site objects belonging to the user.
   709 	 * @param int   $user_id User ID.
   893 	 * @param int      $user_id User ID.
   710 	 * @param bool  $all     Whether the returned sites array should contain all sites, including
   894 	 * @param bool     $all     Whether the returned sites array should contain all sites, including
   711 	 *                       those marked 'deleted', 'archived', or 'spam'. Default false.
   895 	 *                          those marked 'deleted', 'archived', or 'spam'. Default false.
   712 	 */
   896 	 */
   713 	return apply_filters( 'get_blogs_of_user', $sites, $user_id, $all );
   897 	return apply_filters( 'get_blogs_of_user', $sites, $user_id, $all );
   714 }
   898 }
   715 
   899 
   716 /**
   900 /**
   826  *
  1010  *
   827  * @param int    $user_id User ID.
  1011  * @param int    $user_id User ID.
   828  * @param string $key     Optional. The meta key to retrieve. By default,
  1012  * @param string $key     Optional. The meta key to retrieve. By default,
   829  *                        returns data for all keys.
  1013  *                        returns data for all keys.
   830  * @param bool   $single  Optional. Whether to return a single value.
  1014  * @param bool   $single  Optional. Whether to return a single value.
   831  *                        This parameter has no effect if $key is not specified.
  1015  *                        This parameter has no effect if `$key` is not specified.
   832  *                        Default false.
  1016  *                        Default false.
   833  * @return mixed An array if $single is false. The value of meta data field
  1017  * @return mixed An array of values if `$single` is false.
   834  *               if $single is true. False for an invalid $user_id.
  1018  *               The value of meta data field if `$single` is true.
       
  1019  *               False for an invalid `$user_id` (non-numeric, zero, or negative value).
       
  1020  *               An empty string if a valid but non-existing user ID is passed.
   835  */
  1021  */
   836 function get_user_meta( $user_id, $key = '', $single = false ) {
  1022 function get_user_meta( $user_id, $key = '', $single = false ) {
   837 	return get_metadata( 'user', $user_id, $key, $single );
  1023 	return get_metadata( 'user', $user_id, $key, $single );
   838 }
  1024 }
   839 
  1025 
   894 	if ( ! $site_id ) {
  1080 	if ( ! $site_id ) {
   895 		$site_id = get_current_blog_id();
  1081 		$site_id = get_current_blog_id();
   896 	}
  1082 	}
   897 
  1083 
   898 	/**
  1084 	/**
   899 	 * Filter the user count before queries are run. Return a non-null value to cause count_users()
  1085 	 * Filters the user count before queries are run.
   900 	 * to return early.
  1086 	 *
       
  1087 	 * Return a non-null value to cause count_users() to return early.
   901 	 *
  1088 	 *
   902 	 * @since 5.1.0
  1089 	 * @since 5.1.0
   903 	 *
  1090 	 *
   904 	 * @param null|string $result   The value to return instead. Default null to continue with the query.
  1091 	 * @param null|string $result   The value to return instead. Default null to continue with the query.
   905 	 * @param string      $strategy Optional. The computational strategy to use when counting the users.
  1092 	 * @param string      $strategy Optional. The computational strategy to use when counting the users.
  1076  *     @type string       $orderby                 Field to order found users by. Accepts user fields.
  1263  *     @type string       $orderby                 Field to order found users by. Accepts user fields.
  1077  *                                                 Default 'display_name'.
  1264  *                                                 Default 'display_name'.
  1078  *     @type string       $order                   Whether to order users in ascending or descending
  1265  *     @type string       $order                   Whether to order users in ascending or descending
  1079  *                                                 order. Accepts 'ASC' (ascending) or 'DESC' (descending).
  1266  *                                                 order. Accepts 'ASC' (ascending) or 'DESC' (descending).
  1080  *                                                 Default 'ASC'.
  1267  *                                                 Default 'ASC'.
  1081  *     @type array|string $include                 Array or comma-separated list of user IDs to include.
  1268  *     @type int[]|string $include                 Array or comma-separated list of user IDs to include.
  1082  *                                                 Default empty.
  1269  *                                                 Default empty.
  1083  *     @type array|string $exclude                 Array or comma-separated list of user IDs to exclude.
  1270  *     @type int[]|string $exclude                 Array or comma-separated list of user IDs to exclude.
  1084  *                                                 Default empty.
  1271  *                                                 Default empty.
  1085  *     @type bool|int     $multi                   Whether to skip the ID attribute on the 'select' element.
  1272  *     @type bool|int     $multi                   Whether to skip the ID attribute on the 'select' element.
  1086  *                                                 Accepts 1|true or 0|false. Default 0|false.
  1273  *                                                 Accepts 1|true or 0|false. Default 0|false.
  1087  *     @type string       $show                    User data to display. If the selected item is empty
  1274  *     @type string       $show                    User data to display. If the selected item is empty
  1088  *                                                 then the 'user_login' will be displayed in parentheses.
  1275  *                                                 then the 'user_login' will be displayed in parentheses.
  1101  *     @type string       $who                     Which type of users to query. Accepts only an empty string or
  1288  *     @type string       $who                     Which type of users to query. Accepts only an empty string or
  1102  *                                                 'authors'. Default empty.
  1289  *                                                 'authors'. Default empty.
  1103  *     @type string|array $role                    An array or a comma-separated list of role names that users must
  1290  *     @type string|array $role                    An array or a comma-separated list of role names that users must
  1104  *                                                 match to be included in results. Note that this is an inclusive
  1291  *                                                 match to be included in results. Note that this is an inclusive
  1105  *                                                 list: users must match *each* role. Default empty.
  1292  *                                                 list: users must match *each* role. Default empty.
  1106  *     @type array        $role__in                An array of role names. Matched users must have at least one of
  1293  *     @type string[]     $role__in                An array of role names. Matched users must have at least one of
  1107  *                                                 these roles. Default empty array.
  1294  *                                                 these roles. Default empty array.
  1108  *     @type array        $role__not_in            An array of role names to exclude. Users matching one or more of
  1295  *     @type string[]     $role__not_in            An array of role names to exclude. Users matching one or more of
  1109  *                                                 these roles will not be included in results. Default empty array.
  1296  *                                                 these roles will not be included in results. Default empty array.
  1110  * }
  1297  * }
  1111  * @return string HTML dropdown list of users.
  1298  * @return string HTML dropdown list of users.
  1112  */
  1299  */
  1113 function wp_dropdown_users( $args = '' ) {
  1300 function wp_dropdown_users( $args = '' ) {
  1188 		}
  1375 		}
  1189 
  1376 
  1190 		if ( $parsed_args['include_selected'] && ( $parsed_args['selected'] > 0 ) ) {
  1377 		if ( $parsed_args['include_selected'] && ( $parsed_args['selected'] > 0 ) ) {
  1191 			$found_selected          = false;
  1378 			$found_selected          = false;
  1192 			$parsed_args['selected'] = (int) $parsed_args['selected'];
  1379 			$parsed_args['selected'] = (int) $parsed_args['selected'];
       
  1380 
  1193 			foreach ( (array) $users as $user ) {
  1381 			foreach ( (array) $users as $user ) {
  1194 				$user->ID = (int) $user->ID;
  1382 				$user->ID = (int) $user->ID;
  1195 				if ( $user->ID === $parsed_args['selected'] ) {
  1383 				if ( $user->ID === $parsed_args['selected'] ) {
  1196 					$found_selected = true;
  1384 					$found_selected = true;
  1197 				}
  1385 				}
  1198 			}
  1386 			}
  1199 
  1387 
  1200 			if ( ! $found_selected ) {
  1388 			if ( ! $found_selected ) {
  1201 				$users[] = get_userdata( $parsed_args['selected'] );
  1389 				$selected_user = get_userdata( $parsed_args['selected'] );
       
  1390 				if ( $selected_user ) {
       
  1391 					$users[] = $selected_user;
       
  1392 				}
  1202 			}
  1393 			}
  1203 		}
  1394 		}
  1204 
  1395 
  1205 		foreach ( (array) $users as $user ) {
  1396 		foreach ( (array) $users as $user ) {
  1206 			if ( 'display_name_with_login' === $show ) {
  1397 			if ( 'display_name_with_login' === $show ) {
  1341 	if ( 'attribute' === $context ) {
  1532 	if ( 'attribute' === $context ) {
  1342 		$value = esc_attr( $value );
  1533 		$value = esc_attr( $value );
  1343 	} elseif ( 'js' === $context ) {
  1534 	} elseif ( 'js' === $context ) {
  1344 		$value = esc_js( $value );
  1535 		$value = esc_js( $value );
  1345 	}
  1536 	}
       
  1537 
       
  1538 	// Restore the type for integer fields after esc_attr().
       
  1539 	if ( in_array( $field, $int_fields, true ) ) {
       
  1540 		$value = (int) $value;
       
  1541 	}
       
  1542 
  1346 	return $value;
  1543 	return $value;
  1347 }
  1544 }
  1348 
  1545 
  1349 /**
  1546 /**
  1350  * Update all user caches
  1547  * Update all user caches
  1351  *
  1548  *
  1352  * @since 3.0.0
  1549  * @since 3.0.0
  1353  *
  1550  *
  1354  * @param WP_User $user User object to be cached
  1551  * @param object|WP_User $user User object or database row to be cached
  1355  * @return bool|null Returns false on failure.
  1552  * @return void|false Void on success, false on failure.
  1356  */
  1553  */
  1357 function update_user_caches( $user ) {
  1554 function update_user_caches( $user ) {
  1358 	if ( $user instanceof WP_User ) {
  1555 	if ( $user instanceof WP_User ) {
  1359 		if ( ! $user->exists() ) {
  1556 		if ( ! $user->exists() ) {
  1360 			return false;
  1557 			return false;
  1372 /**
  1569 /**
  1373  * Clean all user caches
  1570  * Clean all user caches
  1374  *
  1571  *
  1375  * @since 3.0.0
  1572  * @since 3.0.0
  1376  * @since 4.4.0 'clean_user_cache' action was added.
  1573  * @since 4.4.0 'clean_user_cache' action was added.
       
  1574  * @since 5.8.0 Refreshes the global user instance if cleaning the user cache for the current user.
       
  1575  *
       
  1576  * @global WP_User $current_user The current user object which holds the user data.
  1377  *
  1577  *
  1378  * @param WP_User|int $user User object or ID to be cleaned from the cache
  1578  * @param WP_User|int $user User object or ID to be cleaned from the cache
  1379  */
  1579  */
  1380 function clean_user_cache( $user ) {
  1580 function clean_user_cache( $user ) {
       
  1581 	global $current_user;
       
  1582 
  1381 	if ( is_numeric( $user ) ) {
  1583 	if ( is_numeric( $user ) ) {
  1382 		$user = new WP_User( $user );
  1584 		$user = new WP_User( $user );
  1383 	}
  1585 	}
  1384 
  1586 
  1385 	if ( ! $user->exists() ) {
  1587 	if ( ! $user->exists() ) {
  1398 	 *
  1600 	 *
  1399 	 * @param int     $user_id User ID.
  1601 	 * @param int     $user_id User ID.
  1400 	 * @param WP_User $user    User object.
  1602 	 * @param WP_User $user    User object.
  1401 	 */
  1603 	 */
  1402 	do_action( 'clean_user_cache', $user->ID, $user );
  1604 	do_action( 'clean_user_cache', $user->ID, $user );
       
  1605 
       
  1606 	// Refresh the global user instance if the cleaning current user.
       
  1607 	if ( get_current_user_id() === (int) $user->ID ) {
       
  1608 		$user_id      = (int) $user->ID;
       
  1609 		$current_user = null;
       
  1610 		wp_set_current_user( $user_id, '' );
       
  1611 	}
  1403 }
  1612 }
  1404 
  1613 
  1405 /**
  1614 /**
  1406  * Determines whether the given username exists.
  1615  * Determines whether the given username exists.
  1407  *
  1616  *
  1409  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  1618  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  1410  * Conditional Tags} article in the Theme Developer Handbook.
  1619  * Conditional Tags} article in the Theme Developer Handbook.
  1411  *
  1620  *
  1412  * @since 2.0.0
  1621  * @since 2.0.0
  1413  *
  1622  *
  1414  * @param string $username Username.
  1623  * @param string $username The username to check for existence.
  1415  * @return int|false The user's ID on success, and false on failure.
  1624  * @return int|false The user ID on success, false on failure.
  1416  */
  1625  */
  1417 function username_exists( $username ) {
  1626 function username_exists( $username ) {
  1418 	$user = get_user_by( 'login', $username );
  1627 	$user = get_user_by( 'login', $username );
  1419 	if ( $user ) {
  1628 	if ( $user ) {
  1420 		$user_id = $user->ID;
  1629 		$user_id = $user->ID;
  1421 	} else {
  1630 	} else {
  1422 		$user_id = false;
  1631 		$user_id = false;
  1423 	}
  1632 	}
  1424 
  1633 
  1425 	/**
  1634 	/**
  1426 	 * Filters whether the given username exists or not.
  1635 	 * Filters whether the given username exists.
  1427 	 *
  1636 	 *
  1428 	 * @since 4.9.0
  1637 	 * @since 4.9.0
  1429 	 *
  1638 	 *
  1430 	 * @param int|false $user_id  The user's ID on success, and false on failure.
  1639 	 * @param int|false $user_id  The user ID associated with the username,
  1431 	 * @param string    $username Username to check.
  1640 	 *                            or false if the username does not exist.
       
  1641 	 * @param string    $username The username to check for existence.
  1432 	 */
  1642 	 */
  1433 	return apply_filters( 'username_exists', $user_id, $username );
  1643 	return apply_filters( 'username_exists', $user_id, $username );
  1434 }
  1644 }
  1435 
  1645 
  1436 /**
  1646 /**
  1440  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  1650  * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  1441  * Conditional Tags} article in the Theme Developer Handbook.
  1651  * Conditional Tags} article in the Theme Developer Handbook.
  1442  *
  1652  *
  1443  * @since 2.1.0
  1653  * @since 2.1.0
  1444  *
  1654  *
  1445  * @param string $email Email.
  1655  * @param string $email The email to check for existence.
  1446  * @return int|false The user's ID on success, and false on failure.
  1656  * @return int|false The user ID on success, false on failure.
  1447  */
  1657  */
  1448 function email_exists( $email ) {
  1658 function email_exists( $email ) {
  1449 	$user = get_user_by( 'email', $email );
  1659 	$user = get_user_by( 'email', $email );
  1450 	if ( $user ) {
  1660 	if ( $user ) {
  1451 		return $user->ID;
  1661 		$user_id = $user->ID;
  1452 	}
  1662 	} else {
  1453 	return false;
  1663 		$user_id = false;
       
  1664 	}
       
  1665 
       
  1666 	/**
       
  1667 	 * Filters whether the given email exists.
       
  1668 	 *
       
  1669 	 * @since 5.6.0
       
  1670 	 *
       
  1671 	 * @param int|false $user_id The user ID associated with the email,
       
  1672 	 *                           or false if the email does not exist.
       
  1673 	 * @param string    $email   The email to check for existence.
       
  1674 	 */
       
  1675 	return apply_filters( 'email_exists', $user_id, $email );
  1454 }
  1676 }
  1455 
  1677 
  1456 /**
  1678 /**
  1457  * Checks whether a username is valid.
  1679  * Checks whether a username is valid.
  1458  *
  1680  *
  1459  * @since 2.0.1
  1681  * @since 2.0.1
  1460  * @since 4.4.0 Empty sanitized usernames are now considered invalid
  1682  * @since 4.4.0 Empty sanitized usernames are now considered invalid.
  1461  *
  1683  *
  1462  * @param string $username Username.
  1684  * @param string $username Username.
  1463  * @return bool Whether username given is valid
  1685  * @return bool Whether username given is valid.
  1464  */
  1686  */
  1465 function validate_username( $username ) {
  1687 function validate_username( $username ) {
  1466 	$sanitized = sanitize_user( $username, true );
  1688 	$sanitized = sanitize_user( $username, true );
  1467 	$valid     = ( $sanitized == $username && ! empty( $sanitized ) );
  1689 	$valid     = ( $sanitized == $username && ! empty( $sanitized ) );
  1468 
  1690 
  1469 	/**
  1691 	/**
  1470 	 * Filters whether the provided username is valid or not.
  1692 	 * Filters whether the provided username is valid.
  1471 	 *
  1693 	 *
  1472 	 * @since 2.0.1
  1694 	 * @since 2.0.1
  1473 	 *
  1695 	 *
  1474 	 * @param bool   $valid    Whether given username is valid.
  1696 	 * @param bool   $valid    Whether given username is valid.
  1475 	 * @param string $username Username to check.
  1697 	 * @param string $username Username to check.
  1656 	 */
  1878 	 */
  1657 	$user_email = apply_filters( 'pre_user_email', $raw_user_email );
  1879 	$user_email = apply_filters( 'pre_user_email', $raw_user_email );
  1658 
  1880 
  1659 	/*
  1881 	/*
  1660 	 * If there is no update, just check for `email_exists`. If there is an update,
  1882 	 * If there is no update, just check for `email_exists`. If there is an update,
  1661 	 * check if current email and new email are the same, or not, and check `email_exists`
  1883 	 * check if current email and new email are the same, and check `email_exists`
  1662 	 * accordingly.
  1884 	 * accordingly.
  1663 	 */
  1885 	 */
  1664 	if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) )
  1886 	if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) )
  1665 		&& ! defined( 'WP_IMPORTING' )
  1887 		&& ! defined( 'WP_IMPORTING' )
  1666 		&& email_exists( $user_email )
  1888 		&& email_exists( $user_email )
  1789 	}
  2011 	}
  1790 
  2012 
  1791 	/**
  2013 	/**
  1792 	 * Filters user data before the record is created or updated.
  2014 	 * Filters user data before the record is created or updated.
  1793 	 *
  2015 	 *
  1794 	 * It only includes data in the wp_users table wp_user, not any user metadata.
  2016 	 * It only includes data in the users table, not any user metadata.
  1795 	 *
  2017 	 *
  1796 	 * @since 4.9.0
  2018 	 * @since 4.9.0
       
  2019 	 * @since 5.8.0 The $userdata parameter was added.
  1797 	 *
  2020 	 *
  1798 	 * @param array    $data {
  2021 	 * @param array    $data {
  1799 	 *     Values and keys for the user.
  2022 	 *     Values and keys for the user.
  1800 	 *
  2023 	 *
  1801 	 *     @type string $user_login      The user's login. Only included if $update == false
  2024 	 *     @type string $user_login      The user's login. Only included if $update == false
  1805 	 *     @type string $user_nicename   The user's nice name. Defaults to a URL-safe version of user's login
  2028 	 *     @type string $user_nicename   The user's nice name. Defaults to a URL-safe version of user's login
  1806 	 *     @type string $display_name    The user's display name.
  2029 	 *     @type string $display_name    The user's display name.
  1807 	 *     @type string $user_registered MySQL timestamp describing the moment when the user registered. Defaults to
  2030 	 *     @type string $user_registered MySQL timestamp describing the moment when the user registered. Defaults to
  1808 	 *                                   the current UTC timestamp.
  2031 	 *                                   the current UTC timestamp.
  1809 	 * }
  2032 	 * }
  1810 	 * @param bool     $update Whether the user is being updated rather than created.
  2033 	 * @param bool     $update   Whether the user is being updated rather than created.
  1811 	 * @param int|null $id     ID of the user to be updated, or NULL if the user is being created.
  2034 	 * @param int|null $id       ID of the user to be updated, or NULL if the user is being created.
  1812 	 */
  2035 	 * @param array    $userdata The raw array of data passed to wp_insert_user().
  1813 	$data = apply_filters( 'wp_pre_insert_user_data', $data, $update, $update ? (int) $ID : null );
  2036 	 */
       
  2037 	$data = apply_filters( 'wp_pre_insert_user_data', $data, $update, ( $update ? (int) $ID : null ), $userdata );
  1814 
  2038 
  1815 	if ( empty( $data ) || ! is_array( $data ) ) {
  2039 	if ( empty( $data ) || ! is_array( $data ) ) {
  1816 		return new WP_Error( 'empty_data', __( 'Not enough data to create this user.' ) );
  2040 		return new WP_Error( 'empty_data', __( 'Not enough data to create this user.' ) );
  1817 	}
  2041 	}
  1818 
  2042 
  1834 	 * and before any user meta is inserted or updated.
  2058 	 * and before any user meta is inserted or updated.
  1835 	 *
  2059 	 *
  1836 	 * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`.
  2060 	 * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`.
  1837 	 *
  2061 	 *
  1838 	 * @since 4.4.0
  2062 	 * @since 4.4.0
       
  2063 	 * @since 5.8.0 The $userdata parameter was added.
  1839 	 *
  2064 	 *
  1840 	 * @param array $meta {
  2065 	 * @param array $meta {
  1841 	 *     Default meta values and keys for the user.
  2066 	 *     Default meta values and keys for the user.
  1842 	 *
  2067 	 *
  1843 	 *     @type string   $nickname             The user's nickname. Default is the user's username.
  2068 	 *     @type string   $nickname             The user's nickname. Default is the user's username.
  1852 	 *                                          is not forced.
  2077 	 *                                          is not forced.
  1853 	 *     @type string   $show_admin_bar_front Whether to show the admin bar on the front end for the user.
  2078 	 *     @type string   $show_admin_bar_front Whether to show the admin bar on the front end for the user.
  1854 	 *                                          Default 'true'.
  2079 	 *                                          Default 'true'.
  1855 	 *     @type string   $locale               User's locale. Default empty.
  2080 	 *     @type string   $locale               User's locale. Default empty.
  1856 	 * }
  2081 	 * }
  1857 	 * @param WP_User $user   User object.
  2082 	 * @param WP_User $user     User object.
  1858 	 * @param bool    $update Whether the user is being updated rather than created.
  2083 	 * @param bool    $update   Whether the user is being updated rather than created.
  1859 	 */
  2084 	 * @param array   $userdata The raw array of data passed to wp_insert_user().
  1860 	$meta = apply_filters( 'insert_user_meta', $meta, $user, $update );
  2085 	 */
       
  2086 	$meta = apply_filters( 'insert_user_meta', $meta, $user, $update, $userdata );
  1861 
  2087 
  1862 	// Update user meta.
  2088 	// Update user meta.
  1863 	foreach ( $meta as $key => $value ) {
  2089 	foreach ( $meta as $key => $value ) {
  1864 		update_user_meta( $user_id, $key, $value );
  2090 		update_user_meta( $user_id, $key, $value );
  1865 	}
  2091 	}
  1881 	if ( $update ) {
  2107 	if ( $update ) {
  1882 		/**
  2108 		/**
  1883 		 * Fires immediately after an existing user is updated.
  2109 		 * Fires immediately after an existing user is updated.
  1884 		 *
  2110 		 *
  1885 		 * @since 2.0.0
  2111 		 * @since 2.0.0
       
  2112 		 * @since 5.8.0 The $userdata parameter was added.
  1886 		 *
  2113 		 *
  1887 		 * @param int     $user_id       User ID.
  2114 		 * @param int     $user_id       User ID.
  1888 		 * @param WP_User $old_user_data Object containing user's data prior to update.
  2115 		 * @param WP_User $old_user_data Object containing user's data prior to update.
       
  2116 		 * @param array   $userdata      The raw array of data passed to wp_insert_user().
  1889 		 */
  2117 		 */
  1890 		do_action( 'profile_update', $user_id, $old_user_data );
  2118 		do_action( 'profile_update', $user_id, $old_user_data, $userdata );
  1891 
  2119 
  1892 		if ( isset( $userdata['spam'] ) && $userdata['spam'] != $old_user_data->spam ) {
  2120 		if ( isset( $userdata['spam'] ) && $userdata['spam'] != $old_user_data->spam ) {
  1893 			if ( 1 == $userdata['spam'] ) {
  2121 			if ( 1 == $userdata['spam'] ) {
  1894 				/**
  2122 				/**
  1895 				 * Fires after the user is marked as a SPAM user.
  2123 				 * Fires after the user is marked as a SPAM user.
  1913 	} else {
  2141 	} else {
  1914 		/**
  2142 		/**
  1915 		 * Fires immediately after a new user is registered.
  2143 		 * Fires immediately after a new user is registered.
  1916 		 *
  2144 		 *
  1917 		 * @since 1.5.0
  2145 		 * @since 1.5.0
       
  2146 		 * @since 5.8.0 The $userdata parameter was added.
  1918 		 *
  2147 		 *
  1919 		 * @param int $user_id User ID.
  2148 		 * @param int   $user_id  User ID.
       
  2149 		 * @param array $userdata The raw array of data passed to wp_insert_user().
  1920 		 */
  2150 		 */
  1921 		do_action( 'user_register', $user_id );
  2151 		do_action( 'user_register', $user_id, $userdata );
  1922 	}
  2152 	}
  1923 
  2153 
  1924 	return $user_id;
  2154 	return $user_id;
  1925 }
  2155 }
  1926 
  2156 
  2046 			 * Filters the contents of the email sent when the user's password is changed.
  2276 			 * Filters the contents of the email sent when the user's password is changed.
  2047 			 *
  2277 			 *
  2048 			 * @since 4.3.0
  2278 			 * @since 4.3.0
  2049 			 *
  2279 			 *
  2050 			 * @param array $pass_change_email {
  2280 			 * @param array $pass_change_email {
  2051 			 *            Used to build wp_mail().
  2281 			 *     Used to build wp_mail().
  2052 			 *
  2282 			 *
  2053 			 *            @type string $to      The intended recipients. Add emails in a comma separated string.
  2283 			 *     @type string $to      The intended recipients. Add emails in a comma separated string.
  2054 			 *            @type string $subject The subject of the email.
  2284 			 *     @type string $subject The subject of the email.
  2055 			 *            @type string $message The content of the email.
  2285 			 *     @type string $message The content of the email.
  2056 			 *                The following strings have a special meaning and will get replaced dynamically:
  2286 			 *         The following strings have a special meaning and will get replaced dynamically:
  2057 			 *                - ###USERNAME###    The current user's username.
  2287 			 *         - ###USERNAME###    The current user's username.
  2058 			 *                - ###ADMIN_EMAIL### The admin email in case this was unexpected.
  2288 			 *         - ###ADMIN_EMAIL### The admin email in case this was unexpected.
  2059 			 *                - ###EMAIL###       The user's email address.
  2289 			 *         - ###EMAIL###       The user's email address.
  2060 			 *                - ###SITENAME###    The name of the site.
  2290 			 *         - ###SITENAME###    The name of the site.
  2061 			 *                - ###SITEURL###     The URL to the site.
  2291 			 *         - ###SITEURL###     The URL to the site.
  2062 			 *            @type string $headers Headers. Add headers in a newline (\r\n) separated string.
  2292 			 *     @type string $headers Headers. Add headers in a newline (\r\n) separated string.
  2063 			 *        }
  2293 			 * }
  2064 			 * @param array $user     The original user array.
  2294 			 * @param array $user     The original user array.
  2065 			 * @param array $userdata The updated user array.
  2295 			 * @param array $userdata The updated user array.
  2066 			 */
  2296 			 */
  2067 			$pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
  2297 			$pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );
  2068 
  2298 
  2104 			 * Filters the contents of the email sent when the user's email is changed.
  2334 			 * Filters the contents of the email sent when the user's email is changed.
  2105 			 *
  2335 			 *
  2106 			 * @since 4.3.0
  2336 			 * @since 4.3.0
  2107 			 *
  2337 			 *
  2108 			 * @param array $email_change_email {
  2338 			 * @param array $email_change_email {
  2109 			 *            Used to build wp_mail().
  2339 			 *     Used to build wp_mail().
  2110 			 *
  2340 			 *
  2111 			 *            @type string $to      The intended recipients.
  2341 			 *     @type string $to      The intended recipients.
  2112 			 *            @type string $subject The subject of the email.
  2342 			 *     @type string $subject The subject of the email.
  2113 			 *            @type string $message The content of the email.
  2343 			 *     @type string $message The content of the email.
  2114 			 *                The following strings have a special meaning and will get replaced dynamically:
  2344 			 *         The following strings have a special meaning and will get replaced dynamically:
  2115 			 *                - ###USERNAME###    The current user's username.
  2345 			 *         - ###USERNAME###    The current user's username.
  2116 			 *                - ###ADMIN_EMAIL### The admin email in case this was unexpected.
  2346 			 *         - ###ADMIN_EMAIL### The admin email in case this was unexpected.
  2117 			 *                - ###NEW_EMAIL###   The new email address.
  2347 			 *         - ###NEW_EMAIL###   The new email address.
  2118 			 *                - ###EMAIL###       The old email address.
  2348 			 *         - ###EMAIL###       The old email address.
  2119 			 *                - ###SITENAME###    The name of the site.
  2349 			 *         - ###SITENAME###    The name of the site.
  2120 			 *                - ###SITEURL###     The URL to the site.
  2350 			 *         - ###SITEURL###     The URL to the site.
  2121 			 *            @type string $headers Headers.
  2351 			 *     @type string $headers Headers.
  2122 			 *        }
  2352 			 * }
  2123 			 * @param array $user     The original user array.
  2353 			 * @param array $user     The original user array.
  2124 			 * @param array $userdata The updated user array.
  2354 			 * @param array $userdata The updated user array.
  2125 			 */
  2355 			 */
  2126 			$email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
  2356 			$email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );
  2127 
  2357 
  2456 
  2686 
  2457 	return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
  2687 	return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
  2458 }
  2688 }
  2459 
  2689 
  2460 /**
  2690 /**
       
  2691  * Handles sending a password retrieval email to a user.
       
  2692  *
       
  2693  * @since 2.5.0
       
  2694  * @since 5.7.0 Added `$user_login` parameter.
       
  2695  *
       
  2696  * @global wpdb         $wpdb       WordPress database abstraction object.
       
  2697  * @global PasswordHash $wp_hasher  Portable PHP password hashing framework.
       
  2698  *
       
  2699  * @param string $user_login Optional. Username to send a password retrieval email for.
       
  2700  *                           Defaults to `$_POST['user_login']` if not set.
       
  2701  * @return true|WP_Error True when finished, WP_Error object on error.
       
  2702  */
       
  2703 function retrieve_password( $user_login = null ) {
       
  2704 	$errors    = new WP_Error();
       
  2705 	$user_data = false;
       
  2706 
       
  2707 	// Use the passed $user_login if available, otherwise use $_POST['user_login'].
       
  2708 	if ( ! $user_login && ! empty( $_POST['user_login'] ) ) {
       
  2709 		$user_login = $_POST['user_login'];
       
  2710 	}
       
  2711 
       
  2712 	if ( empty( $user_login ) ) {
       
  2713 		$errors->add( 'empty_username', __( '<strong>Error</strong>: Please enter a username or email address.' ) );
       
  2714 	} elseif ( strpos( $user_login, '@' ) ) {
       
  2715 		$user_data = get_user_by( 'email', trim( wp_unslash( $user_login ) ) );
       
  2716 		if ( empty( $user_data ) ) {
       
  2717 			$errors->add( 'invalid_email', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
       
  2718 		}
       
  2719 	} else {
       
  2720 		$user_data = get_user_by( 'login', trim( wp_unslash( $user_login ) ) );
       
  2721 	}
       
  2722 
       
  2723 	/**
       
  2724 	 * Filters the user data during a password reset request.
       
  2725 	 *
       
  2726 	 * Allows, for example, custom validation using data other than username or email address.
       
  2727 	 *
       
  2728 	 * @since 5.7.0
       
  2729 	 *
       
  2730 	 * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
       
  2731 	 * @param WP_Error      $errors    A WP_Error object containing any errors generated
       
  2732 	 *                                 by using invalid credentials.
       
  2733 	 */
       
  2734 	$user_data = apply_filters( 'lostpassword_user_data', $user_data, $errors );
       
  2735 
       
  2736 	/**
       
  2737 	 * Fires before errors are returned from a password reset request.
       
  2738 	 *
       
  2739 	 * @since 2.1.0
       
  2740 	 * @since 4.4.0 Added the `$errors` parameter.
       
  2741 	 * @since 5.4.0 Added the `$user_data` parameter.
       
  2742 	 *
       
  2743 	 * @param WP_Error      $errors    A WP_Error object containing any errors generated
       
  2744 	 *                                 by using invalid credentials.
       
  2745 	 * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
       
  2746 	 */
       
  2747 	do_action( 'lostpassword_post', $errors, $user_data );
       
  2748 
       
  2749 	/**
       
  2750 	 * Filters the errors encountered on a password reset request.
       
  2751 	 *
       
  2752 	 * The filtered WP_Error object may, for example, contain errors for an invalid
       
  2753 	 * username or email address. A WP_Error object should always be returned,
       
  2754 	 * but may or may not contain errors.
       
  2755 	 *
       
  2756 	 * If any errors are present in $errors, this will abort the password reset request.
       
  2757 	 *
       
  2758 	 * @since 5.5.0
       
  2759 	 *
       
  2760 	 * @param WP_Error      $errors    A WP_Error object containing any errors generated
       
  2761 	 *                                 by using invalid credentials.
       
  2762 	 * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
       
  2763 	 */
       
  2764 	$errors = apply_filters( 'lostpassword_errors', $errors, $user_data );
       
  2765 
       
  2766 	if ( $errors->has_errors() ) {
       
  2767 		return $errors;
       
  2768 	}
       
  2769 
       
  2770 	if ( ! $user_data ) {
       
  2771 		$errors->add( 'invalidcombo', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
       
  2772 		return $errors;
       
  2773 	}
       
  2774 
       
  2775 	// Redefining user_login ensures we return the right case in the email.
       
  2776 	$user_login = $user_data->user_login;
       
  2777 	$user_email = $user_data->user_email;
       
  2778 	$key        = get_password_reset_key( $user_data );
       
  2779 
       
  2780 	if ( is_wp_error( $key ) ) {
       
  2781 		return $key;
       
  2782 	}
       
  2783 
       
  2784 	// Localize password reset message content for user.
       
  2785 	$locale = get_user_locale( $user_data );
       
  2786 
       
  2787 	$switched_locale = switch_to_locale( $locale );
       
  2788 
       
  2789 	if ( is_multisite() ) {
       
  2790 		$site_name = get_network()->site_name;
       
  2791 	} else {
       
  2792 		/*
       
  2793 		 * The blogname option is escaped with esc_html on the way into the database
       
  2794 		 * in sanitize_option. We want to reverse this for the plain text arena of emails.
       
  2795 		 */
       
  2796 		$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
       
  2797 	}
       
  2798 
       
  2799 	$message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
       
  2800 	/* translators: %s: Site name. */
       
  2801 	$message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
       
  2802 	/* translators: %s: User login. */
       
  2803 	$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
       
  2804 	$message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n";
       
  2805 	$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
       
  2806 	$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n";
       
  2807 
       
  2808 	if ( ! is_user_logged_in() ) {
       
  2809 		$requester_ip = $_SERVER['REMOTE_ADDR'];
       
  2810 		if ( $requester_ip ) {
       
  2811 			$message .= sprintf(
       
  2812 				/* translators: %s: IP address of password reset requester. */
       
  2813 				__( 'This password reset request originated from the IP address %s.' ),
       
  2814 				$requester_ip
       
  2815 			) . "\r\n";
       
  2816 		}
       
  2817 	}
       
  2818 
       
  2819 	/* translators: Password reset notification email subject. %s: Site title. */
       
  2820 	$title = sprintf( __( '[%s] Password Reset' ), $site_name );
       
  2821 
       
  2822 	/**
       
  2823 	 * Filters the subject of the password reset email.
       
  2824 	 *
       
  2825 	 * @since 2.8.0
       
  2826 	 * @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
       
  2827 	 *
       
  2828 	 * @param string  $title      Email subject.
       
  2829 	 * @param string  $user_login The username for the user.
       
  2830 	 * @param WP_User $user_data  WP_User object.
       
  2831 	 */
       
  2832 	$title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
       
  2833 
       
  2834 	/**
       
  2835 	 * Filters the message body of the password reset mail.
       
  2836 	 *
       
  2837 	 * If the filtered message is empty, the password reset email will not be sent.
       
  2838 	 *
       
  2839 	 * @since 2.8.0
       
  2840 	 * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
       
  2841 	 *
       
  2842 	 * @param string  $message    Email message.
       
  2843 	 * @param string  $key        The activation key.
       
  2844 	 * @param string  $user_login The username for the user.
       
  2845 	 * @param WP_User $user_data  WP_User object.
       
  2846 	 */
       
  2847 	$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
       
  2848 
       
  2849 	if ( $switched_locale ) {
       
  2850 		restore_previous_locale();
       
  2851 	}
       
  2852 
       
  2853 	if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
       
  2854 		$errors->add(
       
  2855 			'retrieve_password_email_failure',
       
  2856 			sprintf(
       
  2857 				/* translators: %s: Documentation URL. */
       
  2858 				__( '<strong>Error</strong>: The email could not be sent. Your site may not be correctly configured to send emails. <a href="%s">Get support for resetting your password</a>.' ),
       
  2859 				esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )
       
  2860 			)
       
  2861 		);
       
  2862 		return $errors;
       
  2863 	}
       
  2864 
       
  2865 	return true;
       
  2866 }
       
  2867 
       
  2868 /**
  2461  * Handles resetting the user's password.
  2869  * Handles resetting the user's password.
  2462  *
  2870  *
  2463  * @since 2.5.0
  2871  * @since 2.5.0
  2464  *
  2872  *
  2465  * @param WP_User $user     The user
  2873  * @param WP_User $user     The user
  2475 	 * @param string  $new_pass New user password.
  2883 	 * @param string  $new_pass New user password.
  2476 	 */
  2884 	 */
  2477 	do_action( 'password_reset', $user, $new_pass );
  2885 	do_action( 'password_reset', $user, $new_pass );
  2478 
  2886 
  2479 	wp_set_password( $new_pass, $user->ID );
  2887 	wp_set_password( $new_pass, $user->ID );
  2480 	update_user_option( $user->ID, 'default_password_nag', false, true );
  2888 	update_user_meta( $user->ID, 'default_password_nag', false );
  2481 
  2889 
  2482 	/**
  2890 	/**
  2483 	 * Fires after the user's password is reset.
  2891 	 * Fires after the user's password is reset.
  2484 	 *
  2892 	 *
  2485 	 * @since 4.4.0
  2893 	 * @since 4.4.0
  2586 			)
  2994 			)
  2587 		);
  2995 		);
  2588 		return $errors;
  2996 		return $errors;
  2589 	}
  2997 	}
  2590 
  2998 
  2591 	update_user_option( $user_id, 'default_password_nag', true, true ); // Set up the password change nag.
  2999 	update_user_meta( $user_id, 'default_password_nag', true ); // Set up the password change nag.
  2592 
  3000 
  2593 	/**
  3001 	/**
  2594 	 * Fires after a new user registration has been recorded.
  3002 	 * Fires after a new user registration has been recorded.
  2595 	 *
  3003 	 *
  2596 	 * @since 4.4.0
  3004 	 * @since 4.4.0
  2778 	 * Returning a value of false will effectively short-circuit setting
  3186 	 * Returning a value of false will effectively short-circuit setting
  2779 	 * the current user.
  3187 	 * the current user.
  2780 	 *
  3188 	 *
  2781 	 * @since 3.9.0
  3189 	 * @since 3.9.0
  2782 	 *
  3190 	 *
  2783 	 * @param int|bool $user_id User ID if one has been determined, false otherwise.
  3191 	 * @param int|false $user_id User ID if one has been determined, false otherwise.
  2784 	 */
  3192 	 */
  2785 	$user_id = apply_filters( 'determine_current_user', false );
  3193 	$user_id = apply_filters( 'determine_current_user', false );
  2786 	if ( ! $user_id ) {
  3194 	if ( ! $user_id ) {
  2787 		wp_set_current_user( 0 );
  3195 		wp_set_current_user( 0 );
  2788 		return $current_user;
  3196 		return $current_user;
  2923 		}
  3331 		}
  2924 	}
  3332 	}
  2925 }
  3333 }
  2926 
  3334 
  2927 /**
  3335 /**
  2928  * Get all user privacy request types.
  3336  * Get all personal data request types.
  2929  *
  3337  *
  2930  * @since 4.9.6
  3338  * @since 4.9.6
  2931  * @access private
  3339  * @access private
  2932  *
  3340  *
  2933  * @return array List of core privacy action types.
  3341  * @return array List of core privacy action types.
  3236 		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
  3644 		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
  3237 		'siteurl'     => home_url(),
  3645 		'siteurl'     => home_url(),
  3238 		'admin_email' => $admin_email,
  3646 		'admin_email' => $admin_email,
  3239 	);
  3647 	);
  3240 
  3648 
  3241 	/* translators: Do not translate SITENAME, USER_EMAIL, DESCRIPTION, MANAGE_URL, SITEURL; those are placeholders. */
  3649 	$subject = sprintf(
  3242 	$email_text = __(
  3650 		/* translators: Privacy data request confirmed notification email subject. 1: Site title, 2: Name of the confirmed action. */
  3243 		'Howdy,
  3651 		__( '[%1$s] Action Confirmed: %2$s' ),
  3244 
  3652 		$email_data['sitename'],
  3245 A user data privacy request has been confirmed on ###SITENAME###:
  3653 		$action_description
  3246 
       
  3247 User: ###USER_EMAIL###
       
  3248 Request: ###DESCRIPTION###
       
  3249 
       
  3250 You can view and manage these data privacy requests here:
       
  3251 
       
  3252 ###MANAGE_URL###
       
  3253 
       
  3254 Regards,
       
  3255 All at ###SITENAME###
       
  3256 ###SITEURL###'
       
  3257 	);
  3654 	);
  3258 
  3655 
  3259 	/**
  3656 	/**
  3260 	 * Filters the body of the user request confirmation email.
  3657 	 * Filters the subject of the user request confirmation email.
  3261 	 *
  3658 	 *
  3262 	 * The email is sent to an administrator when an user request is confirmed.
  3659 	 * @since 4.9.8
  3263 	 * The following strings have a special meaning and will get replaced dynamically:
  3660 	 *
  3264 	 *
  3661 	 * @param string $subject    The email subject.
  3265 	 * ###SITENAME###    The name of the site.
  3662 	 * @param string $sitename   The name of the site.
  3266 	 * ###USER_EMAIL###  The user email for the request.
       
  3267 	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
       
  3268 	 * ###MANAGE_URL###  The URL to manage requests.
       
  3269 	 * ###SITEURL###     The URL to the site.
       
  3270 	 *
       
  3271 	 * @since 4.9.6
       
  3272 	 *
       
  3273 	 * @param string $email_text Text in the email.
       
  3274 	 * @param array  $email_data {
  3663 	 * @param array  $email_data {
  3275 	 *     Data relating to the account action email.
  3664 	 *     Data relating to the account action email.
  3276 	 *
  3665 	 *
  3277 	 *     @type WP_User_Request $request     User request object.
  3666 	 *     @type WP_User_Request $request     User request object.
  3278 	 *     @type string          $user_email  The email address confirming a request
  3667 	 *     @type string          $user_email  The email address confirming a request
  3281 	 *     @type string          $sitename    The site name sending the mail.
  3670 	 *     @type string          $sitename    The site name sending the mail.
  3282 	 *     @type string          $siteurl     The site URL sending the mail.
  3671 	 *     @type string          $siteurl     The site URL sending the mail.
  3283 	 *     @type string          $admin_email The administrator email receiving the mail.
  3672 	 *     @type string          $admin_email The administrator email receiving the mail.
  3284 	 * }
  3673 	 * }
  3285 	 */
  3674 	 */
  3286 	$content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
  3675 	$subject = apply_filters( 'user_request_confirmed_email_subject', $subject, $email_data['sitename'], $email_data );
  3287 
  3676 
  3288 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
  3677 	/* translators: Do not translate SITENAME, USER_EMAIL, DESCRIPTION, MANAGE_URL, SITEURL; those are placeholders. */
  3289 	$content = str_replace( '###USER_EMAIL###', $email_data['user_email'], $content );
  3678 	$content = __(
  3290 	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
  3679 		'Howdy,
  3291 	$content = str_replace( '###MANAGE_URL###', esc_url_raw( $email_data['manage_url'] ), $content );
  3680 
  3292 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
  3681 A user data privacy request has been confirmed on ###SITENAME###:
  3293 
  3682 
  3294 	$subject = sprintf(
  3683 User: ###USER_EMAIL###
  3295 		/* translators: Privacy data request confirmed notification email subject. 1: Site title, 2: Name of the confirmed action. */
  3684 Request: ###DESCRIPTION###
  3296 		__( '[%1$s] Action Confirmed: %2$s' ),
  3685 
  3297 		$email_data['sitename'],
  3686 You can view and manage these data privacy requests here:
  3298 		$action_description
  3687 
       
  3688 ###MANAGE_URL###
       
  3689 
       
  3690 Regards,
       
  3691 All at ###SITENAME###
       
  3692 ###SITEURL###'
  3299 	);
  3693 	);
  3300 
  3694 
  3301 	/**
  3695 	/**
  3302 	 * Filters the subject of the user request confirmation email.
  3696 	 * Filters the body of the user request confirmation email.
  3303 	 *
  3697 	 *
  3304 	 * @since 4.9.8
  3698 	 * The email is sent to an administrator when a user request is confirmed.
  3305 	 *
  3699 	 *
  3306 	 * @param string $subject    The email subject.
  3700 	 * The following strings have a special meaning and will get replaced dynamically:
  3307 	 * @param string $sitename   The name of the site.
  3701 	 *
       
  3702 	 * ###SITENAME###    The name of the site.
       
  3703 	 * ###USER_EMAIL###  The user email for the request.
       
  3704 	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
       
  3705 	 * ###MANAGE_URL###  The URL to manage requests.
       
  3706 	 * ###SITEURL###     The URL to the site.
       
  3707 	 *
       
  3708 	 * @since 4.9.6
       
  3709 	 * @deprecated 5.8.0 Use {@see 'user_request_confirmed_email_content'} instead.
       
  3710 	 *                   For user erasure fulfillment email content
       
  3711 	 *                   use {@see 'user_erasure_fulfillment_email_content'} instead.
       
  3712 	 *
       
  3713 	 * @param string $content    The email content.
       
  3714 	 * @param array  $email_data {
       
  3715 	 *     Data relating to the account action email.
       
  3716 	 *
       
  3717 	 *     @type WP_User_Request $request     User request object.
       
  3718 	 *     @type string          $user_email  The email address confirming a request
       
  3719 	 *     @type string          $description Description of the action being performed
       
  3720 	 *                                        so the user knows what the email is for.
       
  3721 	 *     @type string          $manage_url  The link to click manage privacy requests of this type.
       
  3722 	 *     @type string          $sitename    The site name sending the mail.
       
  3723 	 *     @type string          $siteurl     The site URL sending the mail.
       
  3724 	 *     @type string          $admin_email The administrator email receiving the mail.
       
  3725 	 * }
       
  3726 	 */
       
  3727 	$content = apply_filters_deprecated(
       
  3728 		'user_confirmed_action_email_content',
       
  3729 		array( $content, $email_data ),
       
  3730 		'5.8.0',
       
  3731 		sprintf(
       
  3732 			/* translators: 1 & 2: Deprecation replacement options. */
       
  3733 			__( '%1$s or %2$s' ),
       
  3734 			'user_request_confirmed_email_content',
       
  3735 			'user_erasure_fulfillment_email_content'
       
  3736 		)
       
  3737 	);
       
  3738 
       
  3739 	/**
       
  3740 	 * Filters the body of the user request confirmation email.
       
  3741 	 *
       
  3742 	 * The email is sent to an administrator when a user request is confirmed.
       
  3743 	 * The following strings have a special meaning and will get replaced dynamically:
       
  3744 	 *
       
  3745 	 * ###SITENAME###    The name of the site.
       
  3746 	 * ###USER_EMAIL###  The user email for the request.
       
  3747 	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
       
  3748 	 * ###MANAGE_URL###  The URL to manage requests.
       
  3749 	 * ###SITEURL###     The URL to the site.
       
  3750 	 *
       
  3751 	 * @since 5.8.0
       
  3752 	 *
       
  3753 	 * @param string $content    The email content.
  3308 	 * @param array  $email_data {
  3754 	 * @param array  $email_data {
  3309 	 *     Data relating to the account action email.
  3755 	 *     Data relating to the account action email.
  3310 	 *
  3756 	 *
  3311 	 *     @type WP_User_Request $request     User request object.
  3757 	 *     @type WP_User_Request $request     User request object.
  3312 	 *     @type string          $user_email  The email address confirming a request
  3758 	 *     @type string          $user_email  The email address confirming a request
  3315 	 *     @type string          $sitename    The site name sending the mail.
  3761 	 *     @type string          $sitename    The site name sending the mail.
  3316 	 *     @type string          $siteurl     The site URL sending the mail.
  3762 	 *     @type string          $siteurl     The site URL sending the mail.
  3317 	 *     @type string          $admin_email The administrator email receiving the mail.
  3763 	 *     @type string          $admin_email The administrator email receiving the mail.
  3318 	 * }
  3764 	 * }
  3319 	 */
  3765 	 */
  3320 	$subject = apply_filters( 'user_request_confirmed_email_subject', $subject, $email_data['sitename'], $email_data );
  3766 	$content = apply_filters( 'user_request_confirmed_email_content', $content, $email_data );
       
  3767 
       
  3768 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
       
  3769 	$content = str_replace( '###USER_EMAIL###', $email_data['user_email'], $content );
       
  3770 	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
       
  3771 	$content = str_replace( '###MANAGE_URL###', esc_url_raw( $email_data['manage_url'] ), $content );
       
  3772 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
  3321 
  3773 
  3322 	$headers = '';
  3774 	$headers = '';
  3323 
  3775 
  3324 	/**
  3776 	/**
  3325 	 * Filters the headers of the user request confirmation email.
  3777 	 * Filters the headers of the user request confirmation email.
  3408 
  3860 
  3409 	/**
  3861 	/**
  3410 	 * Filters the subject of the email sent when an erasure request is completed.
  3862 	 * Filters the subject of the email sent when an erasure request is completed.
  3411 	 *
  3863 	 *
  3412 	 * @since 4.9.8
  3864 	 * @since 4.9.8
       
  3865 	 * @deprecated 5.8.0 Use {@see 'user_erasure_fulfillment_email_subject'} instead.
  3413 	 *
  3866 	 *
  3414 	 * @param string $subject    The email subject.
  3867 	 * @param string $subject    The email subject.
  3415 	 * @param string $sitename   The name of the site.
  3868 	 * @param string $sitename   The name of the site.
  3416 	 * @param array  $email_data {
  3869 	 * @param array  $email_data {
  3417 	 *     Data relating to the account action email.
  3870 	 *     Data relating to the account action email.
  3423 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3876 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3424 	 *     @type string          $sitename           The site name sending the mail.
  3877 	 *     @type string          $sitename           The site name sending the mail.
  3425 	 *     @type string          $siteurl            The site URL sending the mail.
  3878 	 *     @type string          $siteurl            The site URL sending the mail.
  3426 	 * }
  3879 	 * }
  3427 	 */
  3880 	 */
  3428 	$subject = apply_filters( 'user_erasure_complete_email_subject', $subject, $email_data['sitename'], $email_data );
  3881 	$subject = apply_filters_deprecated(
  3429 
  3882 		'user_erasure_complete_email_subject',
  3430 	if ( empty( $email_data['privacy_policy_url'] ) ) {
  3883 		array( $subject, $email_data['sitename'], $email_data ),
  3431 		/* translators: Do not translate SITENAME, SITEURL; those are placeholders. */
  3884 		'5.8.0',
  3432 		$email_text = __(
  3885 		'user_erasure_fulfillment_email_subject'
  3433 			'Howdy,
  3886 	);
  3434 
  3887 
  3435 Your request to erase your personal data on ###SITENAME### has been completed.
  3888 	/**
  3436 
  3889 	 * Filters the subject of the email sent when an erasure request is completed.
  3437 If you have any follow-up questions or concerns, please contact the site administrator.
  3890 	 *
  3438 
  3891 	 * @since 5.8.0
  3439 Regards,
  3892 	 *
  3440 All at ###SITENAME###
  3893 	 * @param string $subject    The email subject.
  3441 ###SITEURL###'
  3894 	 * @param string $sitename   The name of the site.
  3442 		);
       
  3443 	} else {
       
  3444 		/* translators: Do not translate SITENAME, SITEURL, PRIVACY_POLICY_URL; those are placeholders. */
       
  3445 		$email_text = __(
       
  3446 			'Howdy,
       
  3447 
       
  3448 Your request to erase your personal data on ###SITENAME### has been completed.
       
  3449 
       
  3450 If you have any follow-up questions or concerns, please contact the site administrator.
       
  3451 
       
  3452 For more information, you can also read our privacy policy: ###PRIVACY_POLICY_URL###
       
  3453 
       
  3454 Regards,
       
  3455 All at ###SITENAME###
       
  3456 ###SITEURL###'
       
  3457 		);
       
  3458 	}
       
  3459 
       
  3460 	/**
       
  3461 	 * Filters the body of the data erasure fulfillment notification.
       
  3462 	 *
       
  3463 	 * The email is sent to a user when a their data erasure request is fulfilled
       
  3464 	 * by an administrator.
       
  3465 	 *
       
  3466 	 * The following strings have a special meaning and will get replaced dynamically:
       
  3467 	 *
       
  3468 	 * ###SITENAME###           The name of the site.
       
  3469 	 * ###PRIVACY_POLICY_URL### Privacy policy page URL.
       
  3470 	 * ###SITEURL###            The URL to the site.
       
  3471 	 *
       
  3472 	 * @since 4.9.6
       
  3473 	 *
       
  3474 	 * @param string $email_text Text in the email.
       
  3475 	 * @param array  $email_data {
  3895 	 * @param array  $email_data {
  3476 	 *     Data relating to the account action email.
  3896 	 *     Data relating to the account action email.
  3477 	 *
  3897 	 *
  3478 	 *     @type WP_User_Request $request            User request object.
  3898 	 *     @type WP_User_Request $request            User request object.
  3479 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
  3899 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
  3482 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3902 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3483 	 *     @type string          $sitename           The site name sending the mail.
  3903 	 *     @type string          $sitename           The site name sending the mail.
  3484 	 *     @type string          $siteurl            The site URL sending the mail.
  3904 	 *     @type string          $siteurl            The site URL sending the mail.
  3485 	 * }
  3905 	 * }
  3486 	 */
  3906 	 */
  3487 	$content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data );
  3907 	$subject = apply_filters( 'user_erasure_fulfillment_email_subject', $subject, $email_data['sitename'], $email_data );
  3488 
  3908 
  3489 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
  3909 	/* translators: Do not translate SITENAME, SITEURL; those are placeholders. */
  3490 	$content = str_replace( '###PRIVACY_POLICY_URL###', $email_data['privacy_policy_url'], $content );
  3910 	$content = __(
  3491 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
  3911 		'Howdy,
  3492 
  3912 
  3493 	$headers = '';
  3913 Your request to erase your personal data on ###SITENAME### has been completed.
  3494 
  3914 
  3495 	/**
  3915 If you have any follow-up questions or concerns, please contact the site administrator.
  3496 	 * Filters the headers of the data erasure fulfillment notification.
  3916 
  3497 	 *
  3917 Regards,
  3498 	 * @since 5.4.0
  3918 All at ###SITENAME###
  3499 	 *
  3919 ###SITEURL###'
  3500 	 * @param string|array $headers    The email headers.
  3920 	);
  3501 	 * @param string       $subject    The email subject.
  3921 
  3502 	 * @param string       $content    The email content.
  3922 	if ( ! empty( $email_data['privacy_policy_url'] ) ) {
  3503 	 * @param int          $request_id The request ID.
  3923 		/* translators: Do not translate SITENAME, SITEURL, PRIVACY_POLICY_URL; those are placeholders. */
  3504 	 * @param array        $email_data {
  3924 		$content = __(
       
  3925 			'Howdy,
       
  3926 
       
  3927 Your request to erase your personal data on ###SITENAME### has been completed.
       
  3928 
       
  3929 If you have any follow-up questions or concerns, please contact the site administrator.
       
  3930 
       
  3931 For more information, you can also read our privacy policy: ###PRIVACY_POLICY_URL###
       
  3932 
       
  3933 Regards,
       
  3934 All at ###SITENAME###
       
  3935 ###SITEURL###'
       
  3936 		);
       
  3937 	}
       
  3938 
       
  3939 	/**
       
  3940 	 * Filters the body of the data erasure fulfillment notification.
       
  3941 	 *
       
  3942 	 * The email is sent to a user when their data erasure request is fulfilled
       
  3943 	 * by an administrator.
       
  3944 	 *
       
  3945 	 * The following strings have a special meaning and will get replaced dynamically:
       
  3946 	 *
       
  3947 	 * ###SITENAME###           The name of the site.
       
  3948 	 * ###PRIVACY_POLICY_URL### Privacy policy page URL.
       
  3949 	 * ###SITEURL###            The URL to the site.
       
  3950 	 *
       
  3951 	 * @since 4.9.6
       
  3952 	 * @deprecated 5.8.0 Use {@see 'user_erasure_fulfillment_email_content'} instead.
       
  3953 	 *                   For user request confirmation email content
       
  3954 	 *                   use {@see 'user_request_confirmed_email_content'} instead.
       
  3955 	 *
       
  3956 	 * @param string $content The email content.
       
  3957 	 * @param array  $email_data {
  3505 	 *     Data relating to the account action email.
  3958 	 *     Data relating to the account action email.
  3506 	 *
  3959 	 *
  3507 	 *     @type WP_User_Request $request            User request object.
  3960 	 *     @type WP_User_Request $request            User request object.
  3508 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
  3961 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
  3509 	 *                                               to the value of `$request->email`, but can be changed
  3962 	 *                                               to the value of `$request->email`, but can be changed
  3511 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3964 	 *     @type string          $privacy_policy_url Privacy policy URL.
  3512 	 *     @type string          $sitename           The site name sending the mail.
  3965 	 *     @type string          $sitename           The site name sending the mail.
  3513 	 *     @type string          $siteurl            The site URL sending the mail.
  3966 	 *     @type string          $siteurl            The site URL sending the mail.
  3514 	 * }
  3967 	 * }
  3515 	 */
  3968 	 */
  3516 	$headers = apply_filters( 'user_erasure_complete_email_headers', $headers, $subject, $content, $request_id, $email_data );
  3969 	$content = apply_filters_deprecated(
       
  3970 		'user_confirmed_action_email_content',
       
  3971 		array( $content, $email_data ),
       
  3972 		'5.8.0',
       
  3973 		sprintf(
       
  3974 			/* translators: 1 & 2: Deprecation replacement options. */
       
  3975 			__( '%1$s or %2$s' ),
       
  3976 			'user_erasure_fulfillment_email_content',
       
  3977 			'user_request_confirmed_email_content'
       
  3978 		)
       
  3979 	);
       
  3980 
       
  3981 	/**
       
  3982 	 * Filters the body of the data erasure fulfillment notification.
       
  3983 	 *
       
  3984 	 * The email is sent to a user when their data erasure request is fulfilled
       
  3985 	 * by an administrator.
       
  3986 	 *
       
  3987 	 * The following strings have a special meaning and will get replaced dynamically:
       
  3988 	 *
       
  3989 	 * ###SITENAME###           The name of the site.
       
  3990 	 * ###PRIVACY_POLICY_URL### Privacy policy page URL.
       
  3991 	 * ###SITEURL###            The URL to the site.
       
  3992 	 *
       
  3993 	 * @since 5.8.0
       
  3994 	 *
       
  3995 	 * @param string $content The email content.
       
  3996 	 * @param array  $email_data {
       
  3997 	 *     Data relating to the account action email.
       
  3998 	 *
       
  3999 	 *     @type WP_User_Request $request            User request object.
       
  4000 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
       
  4001 	 *                                               to the value of `$request->email`, but can be changed
       
  4002 	 *                                               by the `user_erasure_fulfillment_email_to` filter.
       
  4003 	 *     @type string          $privacy_policy_url Privacy policy URL.
       
  4004 	 *     @type string          $sitename           The site name sending the mail.
       
  4005 	 *     @type string          $siteurl            The site URL sending the mail.
       
  4006 	 * }
       
  4007 	 */
       
  4008 	$content = apply_filters( 'user_erasure_fulfillment_email_content', $content, $email_data );
       
  4009 
       
  4010 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
       
  4011 	$content = str_replace( '###PRIVACY_POLICY_URL###', $email_data['privacy_policy_url'], $content );
       
  4012 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
       
  4013 
       
  4014 	$headers = '';
       
  4015 
       
  4016 	/**
       
  4017 	 * Filters the headers of the data erasure fulfillment notification.
       
  4018 	 *
       
  4019 	 * @since 5.4.0
       
  4020 	 * @deprecated 5.8.0 Use {@see 'user_erasure_fulfillment_email_headers'} instead.
       
  4021 	 *
       
  4022 	 * @param string|array $headers    The email headers.
       
  4023 	 * @param string       $subject    The email subject.
       
  4024 	 * @param string       $content    The email content.
       
  4025 	 * @param int          $request_id The request ID.
       
  4026 	 * @param array        $email_data {
       
  4027 	 *     Data relating to the account action email.
       
  4028 	 *
       
  4029 	 *     @type WP_User_Request $request            User request object.
       
  4030 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
       
  4031 	 *                                               to the value of `$request->email`, but can be changed
       
  4032 	 *                                               by the `user_erasure_fulfillment_email_to` filter.
       
  4033 	 *     @type string          $privacy_policy_url Privacy policy URL.
       
  4034 	 *     @type string          $sitename           The site name sending the mail.
       
  4035 	 *     @type string          $siteurl            The site URL sending the mail.
       
  4036 	 * }
       
  4037 	 */
       
  4038 	$headers = apply_filters_deprecated(
       
  4039 		'user_erasure_complete_email_headers',
       
  4040 		array( $headers, $subject, $content, $request_id, $email_data ),
       
  4041 		'5.8.0',
       
  4042 		'user_erasure_fulfillment_email_headers'
       
  4043 	);
       
  4044 
       
  4045 	/**
       
  4046 	 * Filters the headers of the data erasure fulfillment notification.
       
  4047 	 *
       
  4048 	 * @since 5.8.0
       
  4049 	 *
       
  4050 	 * @param string|array $headers    The email headers.
       
  4051 	 * @param string       $subject    The email subject.
       
  4052 	 * @param string       $content    The email content.
       
  4053 	 * @param int          $request_id The request ID.
       
  4054 	 * @param array        $email_data {
       
  4055 	 *     Data relating to the account action email.
       
  4056 	 *
       
  4057 	 *     @type WP_User_Request $request            User request object.
       
  4058 	 *     @type string          $message_recipient  The address that the email will be sent to. Defaults
       
  4059 	 *                                               to the value of `$request->email`, but can be changed
       
  4060 	 *                                               by the `user_erasure_fulfillment_email_to` filter.
       
  4061 	 *     @type string          $privacy_policy_url Privacy policy URL.
       
  4062 	 *     @type string          $sitename           The site name sending the mail.
       
  4063 	 *     @type string          $siteurl            The site URL sending the mail.
       
  4064 	 * }
       
  4065 	 */
       
  4066 	$headers = apply_filters( 'user_erasure_fulfillment_email_headers', $headers, $subject, $content, $request_id, $email_data );
  3517 
  4067 
  3518 	$email_sent = wp_mail( $user_email, $subject, $content, $headers );
  4068 	$email_sent = wp_mail( $user_email, $subject, $content, $headers );
  3519 
  4069 
  3520 	if ( $switched_locale ) {
  4070 	if ( $switched_locale ) {
  3521 		restore_previous_locale();
  4071 		restore_previous_locale();
  3569  *
  4119  *
  3570  * Requests are stored inside a post type named `user_request` since they can apply to both
  4120  * Requests are stored inside a post type named `user_request` since they can apply to both
  3571  * users on the site, or guests without a user account.
  4121  * users on the site, or guests without a user account.
  3572  *
  4122  *
  3573  * @since 4.9.6
  4123  * @since 4.9.6
  3574  *
  4124  * @since 5.7.0 Added the `$status` parameter.
  3575  * @param string $email_address User email address. This can be the address of a registered or non-registered user.
  4125  *
  3576  * @param string $action_name   Name of the action that is being confirmed. Required.
  4126  * @param string $email_address           User email address. This can be the address of a registered
  3577  * @param array  $request_data  Misc data you want to send with the verification request and pass to the actions once the request is confirmed.
  4127  *                                        or non-registered user.
  3578  * @return int|WP_Error Returns the request ID if successful, or a WP_Error object on failure.
  4128  * @param string $action_name             Name of the action that is being confirmed. Required.
  3579  */
  4129  * @param array  $request_data            Misc data you want to send with the verification request and pass
  3580 function wp_create_user_request( $email_address = '', $action_name = '', $request_data = array() ) {
  4130  *                                        to the actions once the request is confirmed.
       
  4131  * @param string $status                  Optional request status (pending or confirmed). Default 'pending'.
       
  4132  * @return int|WP_Error                   Returns the request ID if successful, or a WP_Error object on failure.
       
  4133  */
       
  4134 function wp_create_user_request( $email_address = '', $action_name = '', $request_data = array(), $status = 'pending' ) {
  3581 	$email_address = sanitize_email( $email_address );
  4135 	$email_address = sanitize_email( $email_address );
  3582 	$action_name   = sanitize_key( $action_name );
  4136 	$action_name   = sanitize_key( $action_name );
  3583 
  4137 
  3584 	if ( ! is_email( $email_address ) ) {
  4138 	if ( ! is_email( $email_address ) ) {
  3585 		return new WP_Error( 'invalid_email', __( 'Invalid email address.' ) );
  4139 		return new WP_Error( 'invalid_email', __( 'Invalid email address.' ) );
  3586 	}
  4140 	}
  3587 
  4141 
  3588 	if ( ! $action_name ) {
  4142 	if ( ! in_array( $action_name, _wp_privacy_action_request_types(), true ) ) {
  3589 		return new WP_Error( 'invalid_action', __( 'Invalid action name.' ) );
  4143 		return new WP_Error( 'invalid_action', __( 'Invalid action name.' ) );
       
  4144 	}
       
  4145 
       
  4146 	if ( ! in_array( $status, array( 'pending', 'confirmed' ), true ) ) {
       
  4147 		return new WP_Error( 'invalid_status', __( 'Invalid request status.' ) );
  3590 	}
  4148 	}
  3591 
  4149 
  3592 	$user    = get_user_by( 'email', $email_address );
  4150 	$user    = get_user_by( 'email', $email_address );
  3593 	$user_id = $user && ! is_wp_error( $user ) ? $user->ID : 0;
  4151 	$user_id = $user && ! is_wp_error( $user ) ? $user->ID : 0;
  3594 
  4152 
  3605 			'fields'        => 'ids',
  4163 			'fields'        => 'ids',
  3606 		)
  4164 		)
  3607 	);
  4165 	);
  3608 
  4166 
  3609 	if ( $requests_query->found_posts ) {
  4167 	if ( $requests_query->found_posts ) {
  3610 		return new WP_Error( 'duplicate_request', __( 'An incomplete request for this email address already exists.' ) );
  4168 		return new WP_Error( 'duplicate_request', __( 'An incomplete personal data request for this email address already exists.' ) );
  3611 	}
  4169 	}
  3612 
  4170 
  3613 	$request_id = wp_insert_post(
  4171 	$request_id = wp_insert_post(
  3614 		array(
  4172 		array(
  3615 			'post_author'   => $user_id,
  4173 			'post_author'   => $user_id,
  3616 			'post_name'     => $action_name,
  4174 			'post_name'     => $action_name,
  3617 			'post_title'    => $email_address,
  4175 			'post_title'    => $email_address,
  3618 			'post_content'  => wp_json_encode( $request_data ),
  4176 			'post_content'  => wp_json_encode( $request_data ),
  3619 			'post_status'   => 'request-pending',
  4177 			'post_status'   => 'request-' . $status,
  3620 			'post_type'     => 'user_request',
  4178 			'post_type'     => 'user_request',
  3621 			'post_date'     => current_time( 'mysql', false ),
  4179 			'post_date'     => current_time( 'mysql', false ),
  3622 			'post_date_gmt' => current_time( 'mysql', true ),
  4180 			'post_date_gmt' => current_time( 'mysql', true ),
  3623 		),
  4181 		),
  3624 		true
  4182 		true
  3666  * If the request is not already pending, it will be updated.
  4224  * If the request is not already pending, it will be updated.
  3667  *
  4225  *
  3668  * @since 4.9.6
  4226  * @since 4.9.6
  3669  *
  4227  *
  3670  * @param string $request_id ID of the request created via wp_create_user_request().
  4228  * @param string $request_id ID of the request created via wp_create_user_request().
  3671  * @return bool|WP_Error True on success, `WP_Error` on failure.
  4229  * @return true|WP_Error True on success, `WP_Error` on failure.
  3672  */
  4230  */
  3673 function wp_send_user_request( $request_id ) {
  4231 function wp_send_user_request( $request_id ) {
  3674 	$request_id = absint( $request_id );
  4232 	$request_id = absint( $request_id );
  3675 	$request    = wp_get_user_request( $request_id );
  4233 	$request    = wp_get_user_request( $request_id );
  3676 
  4234 
  3677 	if ( ! $request ) {
  4235 	if ( ! $request ) {
  3678 		return new WP_Error( 'invalid_request', __( 'Invalid user request.' ) );
  4236 		return new WP_Error( 'invalid_request', __( 'Invalid personal data request.' ) );
  3679 	}
  4237 	}
  3680 
  4238 
  3681 	// Localize message content for user; fallback to site default for visitors.
  4239 	// Localize message content for user; fallback to site default for visitors.
  3682 	if ( ! empty( $request->user_id ) ) {
  4240 	if ( ! empty( $request->user_id ) ) {
  3683 		$locale = get_user_locale( $request->user_id );
  4241 		$locale = get_user_locale( $request->user_id );
  3701 		),
  4259 		),
  3702 		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
  4260 		'sitename'    => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
  3703 		'siteurl'     => home_url(),
  4261 		'siteurl'     => home_url(),
  3704 	);
  4262 	);
  3705 
  4263 
  3706 	/* translators: Do not translate DESCRIPTION, CONFIRM_URL, SITENAME, SITEURL: those are placeholders. */
  4264 	/* translators: Confirm privacy data request notification email subject. 1: Site title, 2: Name of the action. */
  3707 	$email_text = __(
  4265 	$subject = sprintf( __( '[%1$s] Confirm Action: %2$s' ), $email_data['sitename'], $email_data['description'] );
  3708 		'Howdy,
  4266 
  3709 
  4267 	/**
  3710 A request has been made to perform the following action on your account:
  4268 	 * Filters the subject of the email sent when an account action is attempted.
  3711 
       
  3712      ###DESCRIPTION###
       
  3713 
       
  3714 To confirm this, please click on the following link:
       
  3715 ###CONFIRM_URL###
       
  3716 
       
  3717 You can safely ignore and delete this email if you do not want to
       
  3718 take this action.
       
  3719 
       
  3720 Regards,
       
  3721 All at ###SITENAME###
       
  3722 ###SITEURL###'
       
  3723 	);
       
  3724 
       
  3725 	/**
       
  3726 	 * Filters the text of the email sent when an account action is attempted.
       
  3727 	 *
       
  3728 	 * The following strings have a special meaning and will get replaced dynamically:
       
  3729 	 *
       
  3730 	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
       
  3731 	 * ###CONFIRM_URL### The link to click on to confirm the account action.
       
  3732 	 * ###SITENAME###    The name of the site.
       
  3733 	 * ###SITEURL###     The URL to the site.
       
  3734 	 *
  4269 	 *
  3735 	 * @since 4.9.6
  4270 	 * @since 4.9.6
  3736 	 *
  4271 	 *
  3737 	 * @param string $email_text Text in the email.
  4272 	 * @param string $subject    The email subject.
       
  4273 	 * @param string $sitename   The name of the site.
  3738 	 * @param array  $email_data {
  4274 	 * @param array  $email_data {
  3739 	 *     Data relating to the account action email.
  4275 	 *     Data relating to the account action email.
  3740 	 *
  4276 	 *
  3741 	 *     @type WP_User_Request $request     User request object.
  4277 	 *     @type WP_User_Request $request     User request object.
  3742 	 *     @type string          $email       The email address this is being sent to.
  4278 	 *     @type string          $email       The email address this is being sent to.
  3744 	 *     @type string          $confirm_url The link to click on to confirm the account action.
  4280 	 *     @type string          $confirm_url The link to click on to confirm the account action.
  3745 	 *     @type string          $sitename    The site name sending the mail.
  4281 	 *     @type string          $sitename    The site name sending the mail.
  3746 	 *     @type string          $siteurl     The site URL sending the mail.
  4282 	 *     @type string          $siteurl     The site URL sending the mail.
  3747 	 * }
  4283 	 * }
  3748 	 */
  4284 	 */
  3749 	$content = apply_filters( 'user_request_action_email_content', $email_text, $email_data );
  4285 	$subject = apply_filters( 'user_request_action_email_subject', $subject, $email_data['sitename'], $email_data );
  3750 
  4286 
  3751 	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
  4287 	/* translators: Do not translate DESCRIPTION, CONFIRM_URL, SITENAME, SITEURL: those are placeholders. */
  3752 	$content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content );
  4288 	$content = __(
  3753 	$content = str_replace( '###EMAIL###', $email_data['email'], $content );
  4289 		'Howdy,
  3754 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
  4290 
  3755 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
  4291 A request has been made to perform the following action on your account:
  3756 
  4292 
  3757 	/* translators: Confirm privacy data request notification email subject. 1: Site title, 2: Name of the action. */
  4293      ###DESCRIPTION###
  3758 	$subject = sprintf( __( '[%1$s] Confirm Action: %2$s' ), $email_data['sitename'], $email_data['description'] );
  4294 
  3759 
  4295 To confirm this, please click on the following link:
  3760 	/**
  4296 ###CONFIRM_URL###
  3761 	 * Filters the subject of the email sent when an account action is attempted.
  4297 
       
  4298 You can safely ignore and delete this email if you do not want to
       
  4299 take this action.
       
  4300 
       
  4301 Regards,
       
  4302 All at ###SITENAME###
       
  4303 ###SITEURL###'
       
  4304 	);
       
  4305 
       
  4306 	/**
       
  4307 	 * Filters the text of the email sent when an account action is attempted.
       
  4308 	 *
       
  4309 	 * The following strings have a special meaning and will get replaced dynamically:
       
  4310 	 *
       
  4311 	 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for.
       
  4312 	 * ###CONFIRM_URL### The link to click on to confirm the account action.
       
  4313 	 * ###SITENAME###    The name of the site.
       
  4314 	 * ###SITEURL###     The URL to the site.
  3762 	 *
  4315 	 *
  3763 	 * @since 4.9.6
  4316 	 * @since 4.9.6
  3764 	 *
  4317 	 *
  3765 	 * @param string $subject    The email subject.
  4318 	 * @param string $content Text in the email.
  3766 	 * @param string $sitename   The name of the site.
       
  3767 	 * @param array  $email_data {
  4319 	 * @param array  $email_data {
  3768 	 *     Data relating to the account action email.
  4320 	 *     Data relating to the account action email.
  3769 	 *
  4321 	 *
  3770 	 *     @type WP_User_Request $request     User request object.
  4322 	 *     @type WP_User_Request $request     User request object.
  3771 	 *     @type string          $email       The email address this is being sent to.
  4323 	 *     @type string          $email       The email address this is being sent to.
  3773 	 *     @type string          $confirm_url The link to click on to confirm the account action.
  4325 	 *     @type string          $confirm_url The link to click on to confirm the account action.
  3774 	 *     @type string          $sitename    The site name sending the mail.
  4326 	 *     @type string          $sitename    The site name sending the mail.
  3775 	 *     @type string          $siteurl     The site URL sending the mail.
  4327 	 *     @type string          $siteurl     The site URL sending the mail.
  3776 	 * }
  4328 	 * }
  3777 	 */
  4329 	 */
  3778 	$subject = apply_filters( 'user_request_action_email_subject', $subject, $email_data['sitename'], $email_data );
  4330 	$content = apply_filters( 'user_request_action_email_content', $content, $email_data );
       
  4331 
       
  4332 	$content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
       
  4333 	$content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content );
       
  4334 	$content = str_replace( '###EMAIL###', $email_data['email'], $content );
       
  4335 	$content = str_replace( '###SITENAME###', $email_data['sitename'], $content );
       
  4336 	$content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
  3779 
  4337 
  3780 	$headers = '';
  4338 	$headers = '';
  3781 
  4339 
  3782 	/**
  4340 	/**
  3783 	 * Filters the headers of the email sent when an account action is attempted.
  4341 	 * Filters the headers of the email sent when an account action is attempted.
  3850  *
  4408  *
  3851  * @since 4.9.6
  4409  * @since 4.9.6
  3852  *
  4410  *
  3853  * @param string $request_id ID of the request being confirmed.
  4411  * @param string $request_id ID of the request being confirmed.
  3854  * @param string $key        Provided key to validate.
  4412  * @param string $key        Provided key to validate.
  3855  * @return bool|WP_Error True on success, WP_Error on failure.
  4413  * @return true|WP_Error True on success, WP_Error on failure.
  3856  */
  4414  */
  3857 function wp_validate_user_request_key( $request_id, $key ) {
  4415 function wp_validate_user_request_key( $request_id, $key ) {
  3858 	global $wp_hasher;
  4416 	global $wp_hasher;
  3859 
  4417 
  3860 	$request_id = absint( $request_id );
  4418 	$request_id       = absint( $request_id );
  3861 	$request    = wp_get_user_request( $request_id );
  4419 	$request          = wp_get_user_request( $request_id );
  3862 
  4420 	$saved_key        = $request->confirm_key;
  3863 	if ( ! $request ) {
  4421 	$key_request_time = $request->modified_timestamp;
  3864 		return new WP_Error( 'invalid_request', __( 'Invalid request.' ) );
  4422 
       
  4423 	if ( ! $request || ! $saved_key || ! $key_request_time ) {
       
  4424 		return new WP_Error( 'invalid_request', __( 'Invalid personal data request.' ) );
  3865 	}
  4425 	}
  3866 
  4426 
  3867 	if ( ! in_array( $request->status, array( 'request-pending', 'request-failed' ), true ) ) {
  4427 	if ( ! in_array( $request->status, array( 'request-pending', 'request-failed' ), true ) ) {
  3868 		return new WP_Error( 'expired_link', __( 'This link has expired.' ) );
  4428 		return new WP_Error( 'expired_request', __( 'This personal data request has expired.' ) );
  3869 	}
  4429 	}
  3870 
  4430 
  3871 	if ( empty( $key ) ) {
  4431 	if ( empty( $key ) ) {
  3872 		return new WP_Error( 'missing_key', __( 'Missing confirm key.' ) );
  4432 		return new WP_Error( 'missing_key', __( 'The confirmation key is missing from this personal data request.' ) );
  3873 	}
  4433 	}
  3874 
  4434 
  3875 	if ( empty( $wp_hasher ) ) {
  4435 	if ( empty( $wp_hasher ) ) {
  3876 		require_once ABSPATH . WPINC . '/class-phpass.php';
  4436 		require_once ABSPATH . WPINC . '/class-phpass.php';
  3877 		$wp_hasher = new PasswordHash( 8, true );
  4437 		$wp_hasher = new PasswordHash( 8, true );
  3878 	}
  4438 	}
  3879 
  4439 
  3880 	$key_request_time = $request->modified_timestamp;
       
  3881 	$saved_key        = $request->confirm_key;
       
  3882 
       
  3883 	if ( ! $saved_key ) {
       
  3884 		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
       
  3885 	}
       
  3886 
       
  3887 	if ( ! $key_request_time ) {
       
  3888 		return new WP_Error( 'invalid_key', __( 'Invalid action.' ) );
       
  3889 	}
       
  3890 
       
  3891 	/**
  4440 	/**
  3892 	 * Filters the expiration time of confirm keys.
  4441 	 * Filters the expiration time of confirm keys.
  3893 	 *
  4442 	 *
  3894 	 * @since 4.9.6
  4443 	 * @since 4.9.6
  3895 	 *
  4444 	 *
  3897 	 */
  4446 	 */
  3898 	$expiration_duration = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );
  4447 	$expiration_duration = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );
  3899 	$expiration_time     = $key_request_time + $expiration_duration;
  4448 	$expiration_time     = $key_request_time + $expiration_duration;
  3900 
  4449 
  3901 	if ( ! $wp_hasher->CheckPassword( $key, $saved_key ) ) {
  4450 	if ( ! $wp_hasher->CheckPassword( $key, $saved_key ) ) {
  3902 		return new WP_Error( 'invalid_key', __( 'Invalid key.' ) );
  4451 		return new WP_Error( 'invalid_key', __( 'The confirmation key is invalid for this personal data request.' ) );
  3903 	}
  4452 	}
  3904 
  4453 
  3905 	if ( ! $expiration_time || time() > $expiration_time ) {
  4454 	if ( ! $expiration_time || time() > $expiration_time ) {
  3906 		return new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) );
  4455 		return new WP_Error( 'expired_key', __( 'The confirmation key has expired for this personal data request.' ) );
  3907 	}
  4456 	}
  3908 
  4457 
  3909 	return true;
  4458 	return true;
  3910 }
  4459 }
  3911 
  4460 
  3925 		return false;
  4474 		return false;
  3926 	}
  4475 	}
  3927 
  4476 
  3928 	return new WP_User_Request( $post );
  4477 	return new WP_User_Request( $post );
  3929 }
  4478 }
       
  4479 
       
  4480 /**
       
  4481  * Checks if Application Passwords is globally available.
       
  4482  *
       
  4483  * By default, Application Passwords is available to all sites using SSL or to local environments.
       
  4484  * Use {@see 'wp_is_application_passwords_available'} to adjust its availability.
       
  4485  *
       
  4486  * @since 5.6.0
       
  4487  *
       
  4488  * @return bool
       
  4489  */
       
  4490 function wp_is_application_passwords_available() {
       
  4491 	$available = is_ssl() || 'local' === wp_get_environment_type();
       
  4492 
       
  4493 	/**
       
  4494 	 * Filters whether Application Passwords is available.
       
  4495 	 *
       
  4496 	 * @since 5.6.0
       
  4497 	 *
       
  4498 	 * @param bool $available True if available, false otherwise.
       
  4499 	 */
       
  4500 	return apply_filters( 'wp_is_application_passwords_available', $available );
       
  4501 }
       
  4502 
       
  4503 /**
       
  4504  * Checks if Application Passwords is available for a specific user.
       
  4505  *
       
  4506  * By default all users can use Application Passwords. Use {@see 'wp_is_application_passwords_available_for_user'}
       
  4507  * to restrict availability to certain users.
       
  4508  *
       
  4509  * @since 5.6.0
       
  4510  *
       
  4511  * @param int|WP_User $user The user to check.
       
  4512  * @return bool
       
  4513  */
       
  4514 function wp_is_application_passwords_available_for_user( $user ) {
       
  4515 	if ( ! wp_is_application_passwords_available() ) {
       
  4516 		return false;
       
  4517 	}
       
  4518 
       
  4519 	if ( ! is_object( $user ) ) {
       
  4520 		$user = get_userdata( $user );
       
  4521 	}
       
  4522 
       
  4523 	if ( ! $user || ! $user->exists() ) {
       
  4524 		return false;
       
  4525 	}
       
  4526 
       
  4527 	/**
       
  4528 	 * Filters whether Application Passwords is available for a specific user.
       
  4529 	 *
       
  4530 	 * @since 5.6.0
       
  4531 	 *
       
  4532 	 * @param bool    $available True if available, false otherwise.
       
  4533 	 * @param WP_User $user      The user to check.
       
  4534 	 */
       
  4535 	return apply_filters( 'wp_is_application_passwords_available_for_user', true, $user );
       
  4536 }