wp/wp-includes/user.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * WordPress User API
     3  * WordPress User API
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
       
     6  * @subpackage Users
     6  */
     7  */
     7 
     8 
     8 /**
     9 /**
     9  * Authenticate user with remember capability.
    10  * Authenticate user with remember capability.
    10  *
    11  *
    16  * set for a longer period depending on if the 'remember' credential is set to
    17  * set for a longer period depending on if the 'remember' credential is set to
    17  * true.
    18  * true.
    18  *
    19  *
    19  * @since 2.5.0
    20  * @since 2.5.0
    20  *
    21  *
    21  * @param array $credentials Optional. User info in order to sign on.
    22  * @param array       $credentials   Optional. User info in order to sign on.
    22  * @param bool $secure_cookie Optional. Whether to use secure cookie.
    23  * @param string|bool $secure_cookie Optional. Whether to use secure cookie.
    23  * @return object Either WP_Error on failure, or WP_User on success.
    24  * @return WP_User|WP_Error WP_User on success, WP_Error on failure.
    24  */
    25  */
    25 function wp_signon( $credentials = '', $secure_cookie = '' ) {
    26 function wp_signon( $credentials = array(), $secure_cookie = '' ) {
    26 	if ( empty($credentials) ) {
    27 	if ( empty($credentials) ) {
    27 		if ( ! empty($_POST['log']) )
    28 		if ( ! empty($_POST['log']) )
    28 			$credentials['user_login'] = $_POST['log'];
    29 			$credentials['user_login'] = $_POST['log'];
    29 		if ( ! empty($_POST['pwd']) )
    30 		if ( ! empty($_POST['pwd']) )
    30 			$credentials['user_password'] = $_POST['pwd'];
    31 			$credentials['user_password'] = $_POST['pwd'];
    35 	if ( !empty($credentials['remember']) )
    36 	if ( !empty($credentials['remember']) )
    36 		$credentials['remember'] = true;
    37 		$credentials['remember'] = true;
    37 	else
    38 	else
    38 		$credentials['remember'] = false;
    39 		$credentials['remember'] = false;
    39 
    40 
    40 	// TODO do we deprecate the wp_authentication action?
    41 	/**
    41 	do_action_ref_array('wp_authenticate', array(&$credentials['user_login'], &$credentials['user_password']));
    42 	 * Fires before the user is authenticated.
       
    43 	 *
       
    44 	 * The variables passed to the callbacks are passed by reference,
       
    45 	 * and can be modified by callback functions.
       
    46 	 *
       
    47 	 * @since 1.5.1
       
    48 	 *
       
    49 	 * @todo Decide whether to deprecate the wp_authenticate action.
       
    50 	 *
       
    51 	 * @param string $user_login    Username, passed by reference.
       
    52 	 * @param string $user_password User password, passed by reference.
       
    53 	 */
       
    54 	do_action_ref_array( 'wp_authenticate', array( &$credentials['user_login'], &$credentials['user_password'] ) );
    42 
    55 
    43 	if ( '' === $secure_cookie )
    56 	if ( '' === $secure_cookie )
    44 		$secure_cookie = is_ssl();
    57 		$secure_cookie = is_ssl();
    45 
    58 
    46 	$secure_cookie = apply_filters('secure_signon_cookie', $secure_cookie, $credentials);
    59 	/**
       
    60 	 * Filter whether to use a secure sign-on cookie.
       
    61 	 *
       
    62 	 * @since 3.1.0
       
    63 	 *
       
    64 	 * @param bool  $secure_cookie Whether to use a secure sign-on cookie.
       
    65 	 * @param array $credentials {
       
    66  	 *     Array of entered sign-on data.
       
    67  	 *
       
    68  	 *     @type string $user_login    Username.
       
    69  	 *     @type string $user_password Password entered.
       
    70 	 *     @type bool   $remember      Whether to 'remember' the user. Increases the time
       
    71 	 *                                 that the cookie will be kept. Default false.
       
    72  	 * }
       
    73 	 */
       
    74 	$secure_cookie = apply_filters( 'secure_signon_cookie', $secure_cookie, $credentials );
    47 
    75 
    48 	global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
    76 	global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
    49 	$auth_secure_cookie = $secure_cookie;
    77 	$auth_secure_cookie = $secure_cookie;
    50 
    78 
    51 	add_filter('authenticate', 'wp_authenticate_cookie', 30, 3);
    79 	add_filter('authenticate', 'wp_authenticate_cookie', 30, 3);
    59 
    87 
    60 		return $user;
    88 		return $user;
    61 	}
    89 	}
    62 
    90 
    63 	wp_set_auth_cookie($user->ID, $credentials['remember'], $secure_cookie);
    91 	wp_set_auth_cookie($user->ID, $credentials['remember'], $secure_cookie);
    64 	do_action('wp_login', $user->user_login, $user);
    92 	/**
       
    93 	 * Fires after the user has successfully logged in.
       
    94 	 *
       
    95 	 * @since 1.5.0
       
    96 	 *
       
    97 	 * @param string  $user_login Username.
       
    98 	 * @param WP_User $user       WP_User object of the logged-in user.
       
    99 	 */
       
   100 	do_action( 'wp_login', $user->user_login, $user );
    65 	return $user;
   101 	return $user;
    66 }
   102 }
    67 
   103 
    68 /**
   104 /**
    69  * Authenticate the user using the username and password.
   105  * Authenticate the user using the username and password.
    70  */
   106  *
    71 add_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
   107  * @since 2.8.0
       
   108  *
       
   109  * @param WP_User|WP_Error|null $user     WP_User or WP_Error object from a previous callback. Default null.
       
   110  * @param string                $username Username for authentication.
       
   111  * @param string                $password Password for authentication.
       
   112  * @return WP_User|WP_Error WP_User on success, WP_Error on failure.
       
   113  */
    72 function wp_authenticate_username_password($user, $username, $password) {
   114 function wp_authenticate_username_password($user, $username, $password) {
    73 	if ( is_a($user, 'WP_User') ) { return $user; }
   115 	if ( $user instanceof WP_User ) {
       
   116 		return $user;
       
   117 	}
    74 
   118 
    75 	if ( empty($username) || empty($password) ) {
   119 	if ( empty($username) || empty($password) ) {
    76 		if ( is_wp_error( $user ) )
   120 		if ( is_wp_error( $user ) )
    77 			return $user;
   121 			return $user;
    78 
   122 
    88 	}
   132 	}
    89 
   133 
    90 	$user = get_user_by('login', $username);
   134 	$user = get_user_by('login', $username);
    91 
   135 
    92 	if ( !$user )
   136 	if ( !$user )
    93 		return new WP_Error( 'invalid_username', sprintf( __( '<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?' ), wp_lostpassword_url() ) );
   137 		return new WP_Error( 'invalid_username', sprintf( __( '<strong>ERROR</strong>: Invalid username. <a href="%s">Lost your password?</a>' ), wp_lostpassword_url() ) );
    94 
   138 
    95 	$user = apply_filters('wp_authenticate_user', $user, $password);
   139 	/**
       
   140 	 * Filter whether the given user can be authenticated with the provided $password.
       
   141 	 *
       
   142 	 * @since 2.5.0
       
   143 	 *
       
   144 	 * @param WP_User|WP_Error $user     WP_User or WP_Error object if a previous
       
   145 	 *                                   callback failed authentication.
       
   146 	 * @param string           $password Password to check against the user.
       
   147 	 */
       
   148 	$user = apply_filters( 'wp_authenticate_user', $user, $password );
    96 	if ( is_wp_error($user) )
   149 	if ( is_wp_error($user) )
    97 		return $user;
   150 		return $user;
    98 
   151 
    99 	if ( !wp_check_password($password, $user->user_pass, $user->ID) )
   152 	if ( !wp_check_password($password, $user->user_pass, $user->ID) )
   100 		return new WP_Error( 'incorrect_password', sprintf( __( '<strong>ERROR</strong>: The password you entered for the username <strong>%1$s</strong> is incorrect. <a href="%2$s" title="Password Lost and Found">Lost your password</a>?' ),
   153 		return new WP_Error( 'incorrect_password', sprintf( __( '<strong>ERROR</strong>: The password you entered for the username <strong>%1$s</strong> is incorrect. <a href="%2$s">Lost your password?</a>' ),
   101 		$username, wp_lostpassword_url() ) );
   154 		$username, wp_lostpassword_url() ) );
   102 
   155 
   103 	return $user;
   156 	return $user;
   104 }
   157 }
   105 
   158 
   106 /**
   159 /**
   107  * Authenticate the user using the WordPress auth cookie.
   160  * Authenticate the user using the WordPress auth cookie.
       
   161  *
       
   162  * @since 2.8.0
       
   163  *
       
   164  * @param WP_User|WP_Error|null $user     WP_User or WP_Error object from a previous callback. Default null.
       
   165  * @param string                $username Username. If not empty, cancels the cookie authentication.
       
   166  * @param string                $password Password. If not empty, cancels the cookie authentication.
       
   167  * @return WP_User|WP_Error WP_User on success, WP_Error on failure.
   108  */
   168  */
   109 function wp_authenticate_cookie($user, $username, $password) {
   169 function wp_authenticate_cookie($user, $username, $password) {
   110 	if ( is_a($user, 'WP_User') ) { return $user; }
   170 	if ( $user instanceof WP_User ) {
       
   171 		return $user;
       
   172 	}
   111 
   173 
   112 	if ( empty($username) && empty($password) ) {
   174 	if ( empty($username) && empty($password) ) {
   113 		$user_id = wp_validate_auth_cookie();
   175 		$user_id = wp_validate_auth_cookie();
   114 		if ( $user_id )
   176 		if ( $user_id )
   115 			return new WP_User($user_id);
   177 			return new WP_User($user_id);
   129 
   191 
   130 	return $user;
   192 	return $user;
   131 }
   193 }
   132 
   194 
   133 /**
   195 /**
   134  * For multisite blogs, check if the authenticated user has been marked as a
   196  * For Multisite blogs, check if the authenticated user has been marked as a
   135  * spammer, or if the user's primary blog has been marked as spam.
   197  * spammer, or if the user's primary blog has been marked as spam.
   136  *
   198  *
   137  * @since 3.7.0
   199  * @since 3.7.0
       
   200  *
       
   201  * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.
       
   202  * @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer.
   138  */
   203  */
   139 function wp_authenticate_spam_check( $user ) {
   204 function wp_authenticate_spam_check( $user ) {
   140 	if ( $user && is_a( $user, 'WP_User' ) && is_multisite() ) {
   205 	if ( $user instanceof WP_User && is_multisite() ) {
       
   206 		/**
       
   207 		 * Filter whether the user has been marked as a spammer.
       
   208 		 *
       
   209 		 * @since 3.7.0
       
   210 		 *
       
   211 		 * @param bool    $spammed Whether the user is considered a spammer.
       
   212 		 * @param WP_User $user    User to check against.
       
   213 		 */
   141 		$spammed = apply_filters( 'check_is_user_spammed', is_user_spammy(), $user );
   214 		$spammed = apply_filters( 'check_is_user_spammed', is_user_spammy(), $user );
   142 
   215 
   143 		if ( $spammed )
   216 		if ( $spammed )
   144 			return new WP_Error( 'spammer_account', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.' ) );
   217 			return new WP_Error( 'spammer_account', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.' ) );
   145 	}
   218 	}
   146 	return $user;
   219 	return $user;
   147 }
   220 }
   148 
   221 
   149 /**
   222 /**
       
   223  * Validate the logged-in cookie.
       
   224  *
       
   225  * Checks the logged-in cookie if the previous auth cookie could not be
       
   226  * validated and parsed.
       
   227  *
       
   228  * This is a callback for the determine_current_user filter, rather than API.
       
   229  *
       
   230  * @since 3.9.0
       
   231  *
       
   232  * @param int|bool $user_id The user ID (or false) as received from the
       
   233  *                       determine_current_user filter.
       
   234  * @return int|bool User ID if validated, false otherwise. If a user ID from
       
   235  *                  an earlier filter callback is received, that value is returned.
       
   236  */
       
   237 function wp_validate_logged_in_cookie( $user_id ) {
       
   238 	if ( $user_id ) {
       
   239 		return $user_id;
       
   240 	}
       
   241 
       
   242 	if ( is_blog_admin() || is_network_admin() || empty( $_COOKIE[LOGGED_IN_COOKIE] ) ) {
       
   243 		return false;
       
   244 	}
       
   245 
       
   246 	return wp_validate_auth_cookie( $_COOKIE[LOGGED_IN_COOKIE], 'logged_in' );
       
   247 }
       
   248 
       
   249 /**
   150  * Number of posts user has written.
   250  * Number of posts user has written.
   151  *
   251  *
   152  * @since 3.0.0
   252  * @since 3.0.0
   153  * @uses $wpdb WordPress database object for queries.
   253  * @since 4.1.0 Added `$post_type` argument.
   154  *
   254  *
   155  * @param int $userid User ID.
   255  * @global wpdb $wpdb WordPress database object for queries.
   156  * @return int Amount of posts user has written.
   256  *
   157  */
   257  * @param int    $userid    User ID.
   158 function count_user_posts($userid) {
   258  * @param string $post_type Optional. Post type to count the number of posts for. Default 'post'.
       
   259  * @return int Number of posts the user has written in this post type.
       
   260  */
       
   261 function count_user_posts( $userid, $post_type = 'post' ) {
   159 	global $wpdb;
   262 	global $wpdb;
   160 
   263 
   161 	$where = get_posts_by_author_sql('post', true, $userid);
   264 	$where = get_posts_by_author_sql( $post_type, true, $userid );
   162 
   265 
   163 	$count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" );
   266 	$count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" );
   164 
   267 
   165 	return apply_filters('get_usernumposts', $count, $userid);
   268 	/**
       
   269 	 * Filter the number of posts a user has written.
       
   270 	 *
       
   271 	 * @since 2.7.0
       
   272 	 * @since 4.1.0 Added `$post_type` argument.
       
   273 	 *
       
   274 	 * @param int    $count     The user's post count.
       
   275 	 * @param int    $userid    User ID.
       
   276 	 * @param string $post_type Post type to count the number of posts for.
       
   277 	 */
       
   278 	return apply_filters( 'get_usernumposts', $count, $userid, $post_type );
   166 }
   279 }
   167 
   280 
   168 /**
   281 /**
   169  * Number of posts written by a list of users.
   282  * Number of posts written by a list of users.
   170  *
   283  *
   204 
   317 
   205 /**
   318 /**
   206  * Get the current user's ID
   319  * Get the current user's ID
   207  *
   320  *
   208  * @since MU
   321  * @since MU
   209  *
       
   210  * @uses wp_get_current_user
       
   211  *
   322  *
   212  * @return int The current user's ID
   323  * @return int The current user's ID
   213  */
   324  */
   214 function get_current_user_id() {
   325 function get_current_user_id() {
   215 	if ( ! function_exists( 'wp_get_current_user' ) )
   326 	if ( ! function_exists( 'wp_get_current_user' ) )
   227  * object as the third parameter.
   338  * object as the third parameter.
   228  *
   339  *
   229  * The option will first check for the per site name and then the per Network name.
   340  * The option will first check for the per site name and then the per Network name.
   230  *
   341  *
   231  * @since 2.0.0
   342  * @since 2.0.0
   232  * @uses $wpdb WordPress database object for queries.
   343  *
   233  * @uses apply_filters() Calls 'get_user_option_$option' hook with result,
   344  * @global wpdb $wpdb WordPress database object for queries.
   234  *		option parameter, and user data object.
   345  *
   235  *
   346  * @param string $option     User option name.
   236  * @param string $option User option name.
   347  * @param int    $user       Optional. User ID.
   237  * @param int $user Optional. User ID.
   348  * @param string $deprecated Use get_option() to check for an option in the options table.
   238  * @param bool $deprecated Use get_option() to check for an option in the options table.
   349  * @return mixed User option value on success, false on failure.
   239  * @return mixed
       
   240  */
   350  */
   241 function get_user_option( $option, $user = 0, $deprecated = '' ) {
   351 function get_user_option( $option, $user = 0, $deprecated = '' ) {
   242 	global $wpdb;
   352 	global $wpdb;
   243 
   353 
   244 	if ( !empty( $deprecated ) )
   354 	if ( !empty( $deprecated ) )
   256 	elseif ( $user->has_prop( $option ) ) // User specific and cross-blog
   366 	elseif ( $user->has_prop( $option ) ) // User specific and cross-blog
   257 		$result = $user->get( $option );
   367 		$result = $user->get( $option );
   258 	else
   368 	else
   259 		$result = false;
   369 		$result = false;
   260 
   370 
   261 	return apply_filters("get_user_option_{$option}", $result, $option, $user);
   371 	/**
       
   372 	 * Filter a specific user option value.
       
   373 	 *
       
   374 	 * The dynamic portion of the hook name, `$option`, refers to the user option name.
       
   375 	 *
       
   376 	 * @since 2.5.0
       
   377 	 *
       
   378 	 * @param mixed   $result Value for the user's option.
       
   379 	 * @param string  $option Name of the option being retrieved.
       
   380 	 * @param WP_User $user   WP_User object of the user whose option is being retrieved.
       
   381 	 */
       
   382 	return apply_filters( "get_user_option_{$option}", $result, $option, $user );
   262 }
   383 }
   263 
   384 
   264 /**
   385 /**
   265  * Update user option with global blog capability.
   386  * Update user option with global blog capability.
   266  *
   387  *
   269  * it will prepend the WordPress table prefix to the option name.
   390  * it will prepend the WordPress table prefix to the option name.
   270  *
   391  *
   271  * Deletes the user option if $newvalue is empty.
   392  * Deletes the user option if $newvalue is empty.
   272  *
   393  *
   273  * @since 2.0.0
   394  * @since 2.0.0
   274  * @uses $wpdb WordPress database object for queries
   395  *
   275  *
   396  * @global wpdb $wpdb WordPress database object for queries.
   276  * @param int $user_id User ID
   397  *
       
   398  * @param int    $user_id     User ID.
   277  * @param string $option_name User option name.
   399  * @param string $option_name User option name.
   278  * @param mixed $newvalue User option value.
   400  * @param mixed  $newvalue    User option value.
   279  * @param bool $global Optional. Whether option name is global or blog specific. Default false (blog specific).
   401  * @param bool   $global      Optional. Whether option name is global or blog specific.
   280  * @return unknown
   402  *                            Default false (blog specific).
       
   403  * @return int|bool User meta ID if the option didn't exist, true on successful update,
       
   404  *                  false on failure.
   281  */
   405  */
   282 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {
   406 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {
   283 	global $wpdb;
   407 	global $wpdb;
   284 
   408 
   285 	if ( !$global )
   409 	if ( !$global )
   294  * User options are just like user metadata except that they have support for
   418  * User options are just like user metadata except that they have support for
   295  * global blog options. If the 'global' parameter is false, which it is by default
   419  * global blog options. If the 'global' parameter is false, which it is by default
   296  * it will prepend the WordPress table prefix to the option name.
   420  * it will prepend the WordPress table prefix to the option name.
   297  *
   421  *
   298  * @since 3.0.0
   422  * @since 3.0.0
   299  * @uses $wpdb WordPress database object for queries
   423  *
   300  *
   424  * @global wpdb $wpdb WordPress database object for queries.
   301  * @param int $user_id User ID
   425  *
       
   426  * @param int    $user_id     User ID
   302  * @param string $option_name User option name.
   427  * @param string $option_name User option name.
   303  * @param bool $global Optional. Whether option name is global or blog specific. Default false (blog specific).
   428  * @param bool   $global      Optional. Whether option name is global or blog specific.
   304  * @return unknown
   429  *                            Default false (blog specific).
       
   430  * @return bool True on success, false on failure.
   305  */
   431  */
   306 function delete_user_option( $user_id, $option_name, $global = false ) {
   432 function delete_user_option( $user_id, $option_name, $global = false ) {
   307 	global $wpdb;
   433 	global $wpdb;
   308 
   434 
   309 	if ( !$global )
   435 	if ( !$global )
   313 
   439 
   314 /**
   440 /**
   315  * WordPress User Query class.
   441  * WordPress User Query class.
   316  *
   442  *
   317  * @since 3.1.0
   443  * @since 3.1.0
       
   444  *
       
   445  * @see WP_User_Query::prepare_query() for information on accepted arguments.
   318  */
   446  */
   319 class WP_User_Query {
   447 class WP_User_Query {
   320 
   448 
   321 	/**
   449 	/**
   322 	 * Query vars, after parsing
   450 	 * Query vars, after parsing
   323 	 *
   451 	 *
   324 	 * @since 3.5.0
   452 	 * @since 3.5.0
   325 	 * @access public
   453 	 * @access public
   326 	 * @var array
   454 	 * @var array
   327 	 */
   455 	 */
   328 	var $query_vars = array();
   456 	public $query_vars = array();
   329 
   457 
   330 	/**
   458 	/**
   331 	 * List of found user ids
   459 	 * List of found user ids
   332 	 *
   460 	 *
   333 	 * @since 3.1.0
   461 	 * @since 3.1.0
   334 	 * @access private
   462 	 * @access private
   335 	 * @var array
   463 	 * @var array
   336 	 */
   464 	 */
   337 	var $results;
   465 	private $results;
   338 
   466 
   339 	/**
   467 	/**
   340 	 * Total number of found users for the current query
   468 	 * Total number of found users for the current query
   341 	 *
   469 	 *
   342 	 * @since 3.1.0
   470 	 * @since 3.1.0
   343 	 * @access private
   471 	 * @access private
   344 	 * @var int
   472 	 * @var int
   345 	 */
   473 	 */
   346 	var $total_users = 0;
   474 	private $total_users = 0;
       
   475 
       
   476 	/**
       
   477 	 * Metadata query container.
       
   478 	 *
       
   479 	 * @since 4.2.0
       
   480 	 * @access public
       
   481 	 * @var object WP_Meta_Query
       
   482 	 */
       
   483 	public $meta_query = false;
       
   484 
       
   485 	private $compat_fields = array( 'results', 'total_users' );
   347 
   486 
   348 	// SQL clauses
   487 	// SQL clauses
   349 	var $query_fields;
   488 	public $query_fields;
   350 	var $query_from;
   489 	public $query_from;
   351 	var $query_where;
   490 	public $query_where;
   352 	var $query_orderby;
   491 	public $query_orderby;
   353 	var $query_limit;
   492 	public $query_limit;
   354 
   493 
   355 	/**
   494 	/**
   356 	 * PHP5 constructor
   495 	 * PHP5 constructor.
   357 	 *
   496 	 *
   358 	 * @since 3.1.0
   497 	 * @since 3.1.0
   359 	 *
   498 	 *
   360 	 * @param string|array $args The query variables
   499 	 * @param null|string|array $args Optional. The query variables.
   361 	 * @return WP_User_Query
   500 	 */
   362 	 */
   501 	public function __construct( $query = null ) {
   363 	function __construct( $query = null ) {
   502 		if ( ! empty( $query ) ) {
   364 		if ( !empty( $query ) ) {
   503 			$this->prepare_query( $query );
       
   504 			$this->query();
       
   505 		}
       
   506 	}
       
   507 
       
   508 	/**
       
   509 	 * Prepare the query variables.
       
   510 	 *
       
   511 	 * @since 3.1.0
       
   512 	 * @since 4.2.0 Added 'meta_value_num' support for `$orderby` parameter. Added multi-dimensional array syntax
       
   513 	 *              for `$orderby` parameter.
       
   514 	 * @access public
       
   515 	 *
       
   516 	 * @param string|array $query {
       
   517 	 *     Optional. Array or string of Query parameters.
       
   518 	 *
       
   519 	 *     @type int          $blog_id         The site ID. Default is the global blog id.
       
   520 	 *     @type string       $role            Role name. Default empty.
       
   521 	 *     @type string       $meta_key        User meta key. Default empty.
       
   522 	 *     @type string       $meta_value      User meta value. Default empty.
       
   523 	 *     @type string       $meta_compare    Comparison operator to test the `$meta_value`. Accepts '=', '!=',
       
   524 	 *                                         '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN',
       
   525 	 *                                         'NOT BETWEEN', 'EXISTS', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP',
       
   526 	 *                                         or 'RLIKE'. Default '='.
       
   527 	 *     @type array        $include         An array of user IDs to include. Default empty array.
       
   528 	 *     @type array        $exclude         An array of user IDs to exclude. Default empty array.
       
   529 	 *     @type string       $search          Search keyword. Searches for possible string matches on columns.
       
   530 	 *                                         When `$search_columns` is left empty, it tries to determine which
       
   531 	 *                                         column to search in based on search string. Default empty.
       
   532 	 *     @type array        $search_columns  Array of column names to be searched. Accepts 'ID', 'login',
       
   533 	 *                                         'nicename', 'email', 'url'. Default empty array.
       
   534 	 *     @type string|array $orderby         Field(s) to sort the retrieved users by. May be a single value,
       
   535 	 *                                         an array of values, or a multi-dimensional array with fields as keys
       
   536 	 *                                         and orders ('ASC' or 'DESC') as values. Accepted values are'ID',
       
   537 	 *                                         'display_name' (or 'name'), 'user_login' (or 'login'),
       
   538 	 *                                         'user_nicename' (or 'nicename'), 'user_email' (or 'email'),
       
   539 	 *                                         'user_url' (or 'url'), 'user_registered' (or 'registered'),
       
   540 	 *                                         'post_count', 'meta_value', 'meta_value_num', the value of
       
   541 	 *                                         `$meta_key`, or an array key of `$meta_query`. To use 'meta_value'
       
   542 	 *                                         or 'meta_value_num', `$meta_key` must be also be defined.
       
   543 	 *                                         Default 'user_login'.
       
   544 	 *     @type string       $order           Designates ascending or descending order of users. Order values
       
   545 	 *                                         passed as part of an `$orderby` array take precedence over this
       
   546 	 *                                         parameter. Accepts 'ASC', 'DESC'. Default 'ASC'.
       
   547 	 *     @type int          $offset          Number of users to offset in retrieved results. Can be used in
       
   548 	 *                                         conjunction with pagination. Default 0.
       
   549 	 *     @type int          $number          Number of users to limit the query for. Can be used in conjunction
       
   550 	 *                                         with pagination. Value -1 (all) is not supported.
       
   551 	 *                                         Default empty (all users).
       
   552 	 *     @type bool         $count_total     Whether to count the total number of users found. If pagination is not
       
   553 	 *                                         needed, setting this to false can improve performance. Default true.
       
   554 	 *     @type string|array $fields          Which fields to return. Single or all fields (string), or array
       
   555 	 *                                         of fields. Accepts 'ID', 'display_name', 'login', 'nicename', 'email',
       
   556 	 *                                         'url', 'registered'. Use 'all' for all fields and 'all_with_meta' to
       
   557 	 *                                         include meta fields. Default 'all'.
       
   558 	 *     @type string       $who             Type of users to query. Accepts 'authors'. Default empty (all users).
       
   559 	 * }
       
   560 	 */
       
   561 	public function prepare_query( $query = array() ) {
       
   562 		global $wpdb;
       
   563 
       
   564 		if ( empty( $this->query_vars ) || ! empty( $query ) ) {
       
   565 			$this->query_limit = null;
   365 			$this->query_vars = wp_parse_args( $query, array(
   566 			$this->query_vars = wp_parse_args( $query, array(
   366 				'blog_id' => $GLOBALS['blog_id'],
   567 				'blog_id' => $GLOBALS['blog_id'],
   367 				'role' => '',
   568 				'role' => '',
   368 				'meta_key' => '',
   569 				'meta_key' => '',
   369 				'meta_value' => '',
   570 				'meta_value' => '',
   378 				'number' => '',
   579 				'number' => '',
   379 				'count_total' => true,
   580 				'count_total' => true,
   380 				'fields' => 'all',
   581 				'fields' => 'all',
   381 				'who' => ''
   582 				'who' => ''
   382 			) );
   583 			) );
   383 
   584 		}
   384 			$this->prepare_query();
   585 
   385 			$this->query();
   586 		/**
   386 		}
   587 		 * Fires before the WP_User_Query has been parsed.
   387 	}
   588 		 *
   388 
   589 		 * The passed WP_User_Query object contains the query variables, not
   389 	/**
   590 		 * yet passed into SQL.
   390 	 * Prepare the query variables
   591 		 *
   391 	 *
   592 		 * @since 4.0.0
   392 	 * @since 3.1.0
   593 		 *
   393 	 * @access private
   594 		 * @param WP_User_Query $this The current WP_User_Query instance,
   394 	 */
   595 		 *                            passed by reference.
   395 	function prepare_query() {
   596 		 */
   396 		global $wpdb;
   597 		do_action( 'pre_get_users', $this );
   397 
   598 
   398 		$qv =& $this->query_vars;
   599 		$qv =& $this->query_vars;
   399 
   600 
   400 		if ( is_array( $qv['fields'] ) ) {
   601 		if ( is_array( $qv['fields'] ) ) {
   401 			$qv['fields'] = array_unique( $qv['fields'] );
   602 			$qv['fields'] = array_unique( $qv['fields'] );
   416 			$this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields;
   617 			$this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields;
   417 
   618 
   418 		$this->query_from = "FROM $wpdb->users";
   619 		$this->query_from = "FROM $wpdb->users";
   419 		$this->query_where = "WHERE 1=1";
   620 		$this->query_where = "WHERE 1=1";
   420 
   621 
       
   622 		// Parse and sanitize 'include', for use by 'orderby' as well as 'include' below.
       
   623 		if ( ! empty( $qv['include'] ) ) {
       
   624 			$include = wp_parse_id_list( $qv['include'] );
       
   625 		} else {
       
   626 			$include = false;
       
   627 		}
       
   628 
       
   629 		$blog_id = 0;
       
   630 		if ( isset( $qv['blog_id'] ) ) {
       
   631 			$blog_id = absint( $qv['blog_id'] );
       
   632 		}
       
   633 
       
   634 		if ( isset( $qv['who'] ) && 'authors' == $qv['who'] && $blog_id ) {
       
   635 			$qv['meta_key'] = $wpdb->get_blog_prefix( $blog_id ) . 'user_level';
       
   636 			$qv['meta_value'] = 0;
       
   637 			$qv['meta_compare'] = '!=';
       
   638 			$qv['blog_id'] = $blog_id = 0; // Prevent extra meta query
       
   639 		}
       
   640 
       
   641 		// Meta query.
       
   642 		$this->meta_query = new WP_Meta_Query();
       
   643 		$this->meta_query->parse_query_vars( $qv );
       
   644 
       
   645 		$role = '';
       
   646 		if ( isset( $qv['role'] ) ) {
       
   647 			$role = trim( $qv['role'] );
       
   648 		}
       
   649 
       
   650 		if ( $blog_id && ( $role || is_multisite() ) ) {
       
   651 			$cap_meta_query = array();
       
   652 			$cap_meta_query['key'] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
       
   653 
       
   654 			if ( $role ) {
       
   655 				$cap_meta_query['value'] = '"' . $role . '"';
       
   656 				$cap_meta_query['compare'] = 'like';
       
   657 			}
       
   658 
       
   659 			if ( empty( $this->meta_query->queries ) ) {
       
   660 				$this->meta_query->queries = array( $cap_meta_query );
       
   661 			} elseif ( ! in_array( $cap_meta_query, $this->meta_query->queries, true ) ) {
       
   662 				// Append the cap query to the original queries and reparse the query.
       
   663 				$this->meta_query->queries = array(
       
   664 					'relation' => 'AND',
       
   665 					array( $this->meta_query->queries, $cap_meta_query ),
       
   666 				);
       
   667 			}
       
   668 
       
   669 			$this->meta_query->parse_query_vars( $this->meta_query->queries );
       
   670 		}
       
   671 
       
   672 		if ( ! empty( $this->meta_query->queries ) ) {
       
   673 			$clauses = $this->meta_query->get_sql( 'user', $wpdb->users, 'ID', $this );
       
   674 			$this->query_from .= $clauses['join'];
       
   675 			$this->query_where .= $clauses['where'];
       
   676 
       
   677 			if ( 'OR' == $this->meta_query->relation ) {
       
   678 				$this->query_fields = 'DISTINCT ' . $this->query_fields;
       
   679 			}
       
   680 		}
       
   681 
   421 		// sorting
   682 		// sorting
   422 		if ( isset( $qv['orderby'] ) ) {
   683 		$qv['order'] = isset( $qv['order'] ) ? strtoupper( $qv['order'] ) : '';
   423 			if ( in_array( $qv['orderby'], array('nicename', 'email', 'url', 'registered') ) ) {
   684 		$order = $this->parse_order( $qv['order'] );
   424 				$orderby = 'user_' . $qv['orderby'];
   685 
   425 			} elseif ( in_array( $qv['orderby'], array('user_nicename', 'user_email', 'user_url', 'user_registered') ) ) {
   686 		if ( empty( $qv['orderby'] ) ) {
   426 				$orderby = $qv['orderby'];
   687 			// Default order is by 'user_login'.
   427 			} elseif ( 'name' == $qv['orderby'] || 'display_name' == $qv['orderby'] ) {
   688 			$ordersby = array( 'user_login' => $order );
   428 				$orderby = 'display_name';
   689 		} else if ( is_array( $qv['orderby'] ) ) {
   429 			} elseif ( 'post_count' == $qv['orderby'] ) {
   690 			$ordersby = $qv['orderby'];
   430 				// todo: avoid the JOIN
   691 		} else {
   431 				$where = get_posts_by_author_sql('post');
   692 			// 'orderby' values may be a comma- or space-separated list.
   432 				$this->query_from .= " LEFT OUTER JOIN (
   693 			$ordersby = preg_split( '/[,\s]+/', $qv['orderby'] );
   433 					SELECT post_author, COUNT(*) as post_count
   694 		}
   434 					FROM $wpdb->posts
   695 
   435 					$where
   696 		$orderby_array = array();
   436 					GROUP BY post_author
   697 		foreach ( $ordersby as $_key => $_value ) {
   437 				) p ON ({$wpdb->users}.ID = p.post_author)
   698 			if ( ! $_value ) {
   438 				";
   699 				continue;
   439 				$orderby = 'post_count';
   700 			}
   440 			} elseif ( 'ID' == $qv['orderby'] || 'id' == $qv['orderby'] ) {
   701 
   441 				$orderby = 'ID';
   702 			if ( is_int( $_key ) ) {
   442 			} elseif ( 'meta_value' == $qv['orderby'] ) {
   703 				// Integer key means this is a flat array of 'orderby' fields.
   443 				$orderby = "$wpdb->usermeta.meta_value";
   704 				$_orderby = $_value;
       
   705 				$_order = $order;
   444 			} else {
   706 			} else {
   445 				$orderby = 'user_login';
   707 				// Non-integer key means this the key is the field and the value is ASC/DESC.
       
   708 				$_orderby = $_key;
       
   709 				$_order = $_value;
   446 			}
   710 			}
   447 		}
   711 
   448 
   712 			$parsed = $this->parse_orderby( $_orderby );
   449 		if ( empty( $orderby ) )
   713 
   450 			$orderby = 'user_login';
   714 			if ( ! $parsed ) {
   451 
   715 				continue;
   452 		$qv['order'] = isset( $qv['order'] ) ? strtoupper( $qv['order'] ) : '';
   716 			}
   453 		if ( 'ASC' == $qv['order'] )
   717 
   454 			$order = 'ASC';
   718 			$orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
   455 		else
   719 		}
   456 			$order = 'DESC';
   720 
   457 		$this->query_orderby = "ORDER BY $orderby $order";
   721 		// If no valid clauses were found, order by user_login.
       
   722 		if ( empty( $orderby_array ) ) {
       
   723 			$orderby_array[] = "user_login $order";
       
   724 		}
       
   725 
       
   726 		$this->query_orderby = 'ORDER BY ' . implode( ', ', $orderby_array );
   458 
   727 
   459 		// limit
   728 		// limit
   460 		if ( isset( $qv['number'] ) && $qv['number'] ) {
   729 		if ( isset( $qv['number'] ) && $qv['number'] ) {
   461 			if ( $qv['offset'] )
   730 			if ( $qv['offset'] )
   462 				$this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
   731 				$this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
   494 					$search_columns = array('user_url');
   763 					$search_columns = array('user_url');
   495 				else
   764 				else
   496 					$search_columns = array('user_login', 'user_nicename');
   765 					$search_columns = array('user_login', 'user_nicename');
   497 			}
   766 			}
   498 
   767 
       
   768 			/**
       
   769 			 * Filter the columns to search in a WP_User_Query search.
       
   770 			 *
       
   771 			 * The default columns depend on the search term, and include 'user_email',
       
   772 			 * 'user_login', 'ID', 'user_url', and 'user_nicename'.
       
   773 			 *
       
   774 			 * @since 3.6.0
       
   775 			 *
       
   776 			 * @param array         $search_columns Array of column names to be searched.
       
   777 			 * @param string        $search         Text being searched.
       
   778 			 * @param WP_User_Query $this           The current WP_User_Query instance.
       
   779 			 */
   499 			$search_columns = apply_filters( 'user_search_columns', $search_columns, $search, $this );
   780 			$search_columns = apply_filters( 'user_search_columns', $search_columns, $search, $this );
   500 
   781 
   501 			$this->query_where .= $this->get_search_sql( $search, $search_columns, $wild );
   782 			$this->query_where .= $this->get_search_sql( $search, $search_columns, $wild );
   502 		}
   783 		}
   503 
   784 
   504 		$blog_id = 0;
   785 		if ( ! empty( $include ) ) {
   505 		if ( isset( $qv['blog_id'] ) )
   786 			// Sanitized earlier.
   506 			$blog_id = absint( $qv['blog_id'] );
   787 			$ids = implode( ',', $include );
   507 
       
   508 		if ( isset( $qv['who'] ) && 'authors' == $qv['who'] && $blog_id ) {
       
   509 			$qv['meta_key'] = $wpdb->get_blog_prefix( $blog_id ) . 'user_level';
       
   510 			$qv['meta_value'] = 0;
       
   511 			$qv['meta_compare'] = '!=';
       
   512 			$qv['blog_id'] = $blog_id = 0; // Prevent extra meta query
       
   513 		}
       
   514 
       
   515 		$role = '';
       
   516 		if ( isset( $qv['role'] ) )
       
   517 			$role = trim( $qv['role'] );
       
   518 
       
   519 		if ( $blog_id && ( $role || is_multisite() ) ) {
       
   520 			$cap_meta_query = array();
       
   521 			$cap_meta_query['key'] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
       
   522 
       
   523 			if ( $role ) {
       
   524 				$cap_meta_query['value'] = '"' . $role . '"';
       
   525 				$cap_meta_query['compare'] = 'like';
       
   526 			}
       
   527 
       
   528 			$qv['meta_query'][] = $cap_meta_query;
       
   529 		}
       
   530 
       
   531 		$meta_query = new WP_Meta_Query();
       
   532 		$meta_query->parse_query_vars( $qv );
       
   533 
       
   534 		if ( !empty( $meta_query->queries ) ) {
       
   535 			$clauses = $meta_query->get_sql( 'user', $wpdb->users, 'ID', $this );
       
   536 			$this->query_from .= $clauses['join'];
       
   537 			$this->query_where .= $clauses['where'];
       
   538 
       
   539 			if ( 'OR' == $meta_query->relation )
       
   540 				$this->query_fields = 'DISTINCT ' . $this->query_fields;
       
   541 		}
       
   542 
       
   543 		if ( ! empty( $qv['include'] ) ) {
       
   544 			$ids = implode( ',', wp_parse_id_list( $qv['include'] ) );
       
   545 			$this->query_where .= " AND $wpdb->users.ID IN ($ids)";
   788 			$this->query_where .= " AND $wpdb->users.ID IN ($ids)";
   546 		} elseif ( ! empty( $qv['exclude'] ) ) {
   789 		} elseif ( ! empty( $qv['exclude'] ) ) {
   547 			$ids = implode( ',', wp_parse_id_list( $qv['exclude'] ) );
   790 			$ids = implode( ',', wp_parse_id_list( $qv['exclude'] ) );
   548 			$this->query_where .= " AND $wpdb->users.ID NOT IN ($ids)";
   791 			$this->query_where .= " AND $wpdb->users.ID NOT IN ($ids)";
   549 		}
   792 		}
   550 
   793 
       
   794 		// Date queries are allowed for the user_registered field.
       
   795 		if ( ! empty( $qv['date_query'] ) && is_array( $qv['date_query'] ) ) {
       
   796 			$date_query = new WP_Date_Query( $qv['date_query'], 'user_registered' );
       
   797 			$this->query_where .= $date_query->get_sql();
       
   798 		}
       
   799 
       
   800 		/**
       
   801 		 * Fires after the WP_User_Query has been parsed, and before
       
   802 		 * the query is executed.
       
   803 		 *
       
   804 		 * The passed WP_User_Query object contains SQL parts formed
       
   805 		 * from parsing the given query.
       
   806 		 *
       
   807 		 * @since 3.1.0
       
   808 		 *
       
   809 		 * @param WP_User_Query $this The current WP_User_Query instance,
       
   810 		 *                            passed by reference.
       
   811 		 */
   551 		do_action_ref_array( 'pre_user_query', array( &$this ) );
   812 		do_action_ref_array( 'pre_user_query', array( &$this ) );
   552 	}
   813 	}
   553 
   814 
   554 	/**
   815 	/**
   555 	 * Execute the query, with the current variables
   816 	 * Execute the query, with the current variables.
   556 	 *
   817 	 *
   557 	 * @since 3.1.0
   818 	 * @since 3.1.0
   558 	 * @access private
   819 	 *
   559 	 */
   820 	 * @global wpdb $wpdb WordPress database object for queries.
   560 	function query() {
   821 	 */
       
   822 	public function query() {
   561 		global $wpdb;
   823 		global $wpdb;
   562 
   824 
   563 		$qv =& $this->query_vars;
   825 		$qv =& $this->query_vars;
   564 
   826 
       
   827 		$query = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit";
       
   828 
   565 		if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {
   829 		if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) {
   566 			$this->results = $wpdb->get_results("SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit");
   830 			$this->results = $wpdb->get_results( $query );
   567 		} else {
   831 		} else {
   568 			$this->results = $wpdb->get_col("SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit");
   832 			$this->results = $wpdb->get_col( $query );
   569 		}
   833 		}
   570 
   834 
       
   835 		/**
       
   836 		 * Filter SELECT FOUND_ROWS() query for the current WP_User_Query instance.
       
   837 		 *
       
   838 		 * @since 3.2.0
       
   839 		 *
       
   840 		 * @global wpdb $wpdb WordPress database abstraction object.
       
   841 		 *
       
   842 		 * @param string $sql The SELECT FOUND_ROWS() query for the current WP_User_Query.
       
   843 		 */
   571 		if ( isset( $qv['count_total'] ) && $qv['count_total'] )
   844 		if ( isset( $qv['count_total'] ) && $qv['count_total'] )
   572 			$this->total_users = $wpdb->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) );
   845 			$this->total_users = $wpdb->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) );
   573 
   846 
   574 		if ( !$this->results )
   847 		if ( !$this->results )
   575 			return;
   848 			return;
   582 				$r[ $userid ] = new WP_User( $userid, '', $qv['blog_id'] );
   855 				$r[ $userid ] = new WP_User( $userid, '', $qv['blog_id'] );
   583 
   856 
   584 			$this->results = $r;
   857 			$this->results = $r;
   585 		} elseif ( 'all' == $qv['fields'] ) {
   858 		} elseif ( 'all' == $qv['fields'] ) {
   586 			foreach ( $this->results as $key => $user ) {
   859 			foreach ( $this->results as $key => $user ) {
   587 				$this->results[ $key ] = new WP_User( $user );
   860 				$this->results[ $key ] = new WP_User( $user, '', $qv['blog_id'] );
   588 			}
   861 			}
   589 		}
   862 		}
   590 	}
   863 	}
   591 
   864 
   592 	/**
   865 	/**
   596 	 * @access public
   869 	 * @access public
   597 	 *
   870 	 *
   598 	 * @param string $query_var Query variable key.
   871 	 * @param string $query_var Query variable key.
   599 	 * @return mixed
   872 	 * @return mixed
   600 	 */
   873 	 */
   601 	function get( $query_var ) {
   874 	public function get( $query_var ) {
   602 		if ( isset( $this->query_vars[$query_var] ) )
   875 		if ( isset( $this->query_vars[$query_var] ) )
   603 			return $this->query_vars[$query_var];
   876 			return $this->query_vars[$query_var];
   604 
   877 
   605 		return null;
   878 		return null;
   606 	}
   879 	}
   612 	 * @access public
   885 	 * @access public
   613 	 *
   886 	 *
   614 	 * @param string $query_var Query variable key.
   887 	 * @param string $query_var Query variable key.
   615 	 * @param mixed $value Query variable value.
   888 	 * @param mixed $value Query variable value.
   616 	 */
   889 	 */
   617 	function set( $query_var, $value ) {
   890 	public function set( $query_var, $value ) {
   618 		$this->query_vars[$query_var] = $value;
   891 		$this->query_vars[$query_var] = $value;
   619 	}
   892 	}
   620 
   893 
   621 	/*
   894 	/**
   622 	 * Used internally to generate an SQL string for searching across multiple columns
   895 	 * Used internally to generate an SQL string for searching across multiple columns
   623 	 *
   896 	 *
   624 	 * @access protected
   897 	 * @access protected
   625 	 * @since 3.1.0
   898 	 * @since 3.1.0
   626 	 *
   899 	 *
   628 	 * @param array $cols
   901 	 * @param array $cols
   629 	 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for
   902 	 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for
   630 	 *  single site. Single site allows leading and trailing wildcards, Network Admin only trailing.
   903 	 *  single site. Single site allows leading and trailing wildcards, Network Admin only trailing.
   631 	 * @return string
   904 	 * @return string
   632 	 */
   905 	 */
   633 	function get_search_sql( $string, $cols, $wild = false ) {
   906 	protected function get_search_sql( $string, $cols, $wild = false ) {
   634 		$string = esc_sql( $string );
   907 		global $wpdb;
   635 
   908 
   636 		$searches = array();
   909 		$searches = array();
   637 		$leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
   910 		$leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
   638 		$trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
   911 		$trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
       
   912 		$like = $leading_wild . $wpdb->esc_like( $string ) . $trailing_wild;
       
   913 
   639 		foreach ( $cols as $col ) {
   914 		foreach ( $cols as $col ) {
   640 			if ( 'ID' == $col )
   915 			if ( 'ID' == $col ) {
   641 				$searches[] = "$col = '$string'";
   916 				$searches[] = $wpdb->prepare( "$col = %s", $string );
   642 			else
   917 			} else {
   643 				$searches[] = "$col LIKE '$leading_wild" . like_escape($string) . "$trailing_wild'";
   918 				$searches[] = $wpdb->prepare( "$col LIKE %s", $like );
       
   919 			}
   644 		}
   920 		}
   645 
   921 
   646 		return ' AND (' . implode(' OR ', $searches) . ')';
   922 		return ' AND (' . implode(' OR ', $searches) . ')';
   647 	}
   923 	}
   648 
   924 
   649 	/**
   925 	/**
   650 	 * Return the list of users
   926 	 * Return the list of users.
   651 	 *
   927 	 *
   652 	 * @since 3.1.0
   928 	 * @since 3.1.0
   653 	 * @access public
   929 	 * @access public
   654 	 *
   930 	 *
   655 	 * @return array
   931 	 * @return array Array of results.
   656 	 */
   932 	 */
   657 	function get_results() {
   933 	public function get_results() {
   658 		return $this->results;
   934 		return $this->results;
   659 	}
   935 	}
   660 
   936 
   661 	/**
   937 	/**
   662 	 * Return the total number of users for the current query
   938 	 * Return the total number of users for the current query.
   663 	 *
   939 	 *
   664 	 * @since 3.1.0
   940 	 * @since 3.1.0
   665 	 * @access public
   941 	 * @access public
   666 	 *
   942 	 *
   667 	 * @return array
   943 	 * @return int Number of total users.
   668 	 */
   944 	 */
   669 	function get_total() {
   945 	public function get_total() {
   670 		return $this->total_users;
   946 		return $this->total_users;
   671 	}
   947 	}
       
   948 
       
   949 	/**
       
   950 	 * Parse and sanitize 'orderby' keys passed to the user query.
       
   951 	 *
       
   952 	 * @since 4.2.0
       
   953 	 * @access protected
       
   954 	 *
       
   955 	 * @global wpdb $wpdb WordPress database abstraction object.
       
   956 	 *
       
   957 	 * @param string $orderby Alias for the field to order by.
       
   958 	 * @return string|bool Value to used in the ORDER clause, if `$orderby` is valid. False otherwise.
       
   959 	 */
       
   960 	protected function parse_orderby( $orderby ) {
       
   961 		global $wpdb;
       
   962 
       
   963 		$meta_query_clauses = $this->meta_query->get_clauses();
       
   964 
       
   965 		$_orderby = '';
       
   966 		if ( in_array( $orderby, array( 'login', 'nicename', 'email', 'url', 'registered' ) ) ) {
       
   967 			$_orderby = 'user_' . $orderby;
       
   968 		} elseif ( in_array( $orderby, array( 'user_login', 'user_nicename', 'user_email', 'user_url', 'user_registered' ) ) ) {
       
   969 			$_orderby = $orderby;
       
   970 		} elseif ( 'name' == $orderby || 'display_name' == $orderby ) {
       
   971 			$_orderby = 'display_name';
       
   972 		} elseif ( 'post_count' == $orderby ) {
       
   973 			// todo: avoid the JOIN
       
   974 			$where = get_posts_by_author_sql( 'post' );
       
   975 			$this->query_from .= " LEFT OUTER JOIN (
       
   976 				SELECT post_author, COUNT(*) as post_count
       
   977 				FROM $wpdb->posts
       
   978 				$where
       
   979 				GROUP BY post_author
       
   980 			) p ON ({$wpdb->users}.ID = p.post_author)
       
   981 			";
       
   982 			$_orderby = 'post_count';
       
   983 		} elseif ( 'ID' == $orderby || 'id' == $orderby ) {
       
   984 			$_orderby = 'ID';
       
   985 		} elseif ( 'meta_value' == $orderby || $this->get( 'meta_key' ) == $orderby ) {
       
   986 			$_orderby = "$wpdb->usermeta.meta_value";
       
   987 		} elseif ( 'meta_value_num' == $orderby ) {
       
   988 			$_orderby = "$wpdb->usermeta.meta_value+0";
       
   989 		} elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
       
   990 			$include = wp_parse_id_list( $this->query_vars['include'] );
       
   991 			$include_sql = implode( ',', $include );
       
   992 			$_orderby = "FIELD( $wpdb->users.ID, $include_sql )";
       
   993 		} elseif ( isset( $meta_query_clauses[ $orderby ] ) ) {
       
   994 			$meta_clause = $meta_query_clauses[ $orderby ];
       
   995 			$_orderby = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
       
   996 		}
       
   997 
       
   998 		return $_orderby;
       
   999 	}
       
  1000 
       
  1001 	/**
       
  1002 	 * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
       
  1003 	 *
       
  1004 	 * @since 4.2.0
       
  1005 	 * @access protected
       
  1006 	 *
       
  1007 	 * @param string $order The 'order' query variable.
       
  1008 	 * @return string The sanitized 'order' query variable.
       
  1009 	 */
       
  1010 	protected function parse_order( $order ) {
       
  1011 		if ( ! is_string( $order ) || empty( $order ) ) {
       
  1012 			return 'DESC';
       
  1013 		}
       
  1014 
       
  1015 		if ( 'ASC' === strtoupper( $order ) ) {
       
  1016 			return 'ASC';
       
  1017 		} else {
       
  1018 			return 'DESC';
       
  1019 		}
       
  1020 	}
       
  1021 
       
  1022 	/**
       
  1023 	 * Make private properties readable for backwards compatibility.
       
  1024 	 *
       
  1025 	 * @since 4.0.0
       
  1026 	 * @access public
       
  1027 	 *
       
  1028 	 * @param string $name Property to get.
       
  1029 	 * @return mixed Property.
       
  1030 	 */
       
  1031 	public function __get( $name ) {
       
  1032 		if ( in_array( $name, $this->compat_fields ) ) {
       
  1033 			return $this->$name;
       
  1034 		}
       
  1035 	}
       
  1036 
       
  1037 	/**
       
  1038 	 * Make private properties settable for backwards compatibility.
       
  1039 	 *
       
  1040 	 * @since 4.0.0
       
  1041 	 * @access public
       
  1042 	 *
       
  1043 	 * @param string $name  Property to check if set.
       
  1044 	 * @param mixed  $value Property value.
       
  1045 	 * @return mixed Newly-set property.
       
  1046 	 */
       
  1047 	public function __set( $name, $value ) {
       
  1048 		if ( in_array( $name, $this->compat_fields ) ) {
       
  1049 			return $this->$name = $value;
       
  1050 		}
       
  1051 	}
       
  1052 
       
  1053 	/**
       
  1054 	 * Make private properties checkable for backwards compatibility.
       
  1055 	 *
       
  1056 	 * @since 4.0.0
       
  1057 	 * @access public
       
  1058 	 *
       
  1059 	 * @param string $name Property to check if set.
       
  1060 	 * @return bool Whether the property is set.
       
  1061 	 */
       
  1062 	public function __isset( $name ) {
       
  1063 		if ( in_array( $name, $this->compat_fields ) ) {
       
  1064 			return isset( $this->$name );
       
  1065 		}
       
  1066 	}
       
  1067 
       
  1068 	/**
       
  1069 	 * Make private properties un-settable for backwards compatibility.
       
  1070 	 *
       
  1071 	 * @since 4.0.0
       
  1072 	 * @access public
       
  1073 	 *
       
  1074 	 * @param string $name Property to unset.
       
  1075 	 */
       
  1076 	public function __unset( $name ) {
       
  1077 		if ( in_array( $name, $this->compat_fields ) ) {
       
  1078 			unset( $this->$name );
       
  1079 		}
       
  1080 	}
       
  1081 
       
  1082 	/**
       
  1083 	 * Make private/protected methods readable for backwards compatibility.
       
  1084 	 *
       
  1085 	 * @since 4.0.0
       
  1086 	 * @access public
       
  1087 	 *
       
  1088 	 * @param callable $name      Method to call.
       
  1089 	 * @param array    $arguments Arguments to pass when calling.
       
  1090 	 * @return mixed|bool Return value of the callback, false otherwise.
       
  1091 	 */
       
  1092 	public function __call( $name, $arguments ) {
       
  1093 		if ( 'get_search_sql' === $name ) {
       
  1094 			return call_user_func_array( array( $this, $name ), $arguments );
       
  1095 		}
       
  1096 		return false;
       
  1097 	}
   672 }
  1098 }
   673 
  1099 
   674 /**
  1100 /**
   675  * Retrieve list of users matching criteria.
  1101  * Retrieve list of users matching criteria.
   676  *
  1102  *
   677  * @since 3.1.0
  1103  * @since 3.1.0
   678  * @uses $wpdb
  1104  *
   679  * @uses WP_User_Query See for default arguments and information.
  1105  * @see WP_User_Query
   680  *
  1106  *
   681  * @param array $args Optional.
  1107  * @param array $args Optional. Arguments to retrieve users. See {@see WP_User_Query::prepare_query()}
       
  1108  *                    for more information on accepted arguments.
   682  * @return array List of users.
  1109  * @return array List of users.
   683  */
  1110  */
   684 function get_users( $args = array() ) {
  1111 function get_users( $args = array() ) {
   685 
  1112 
   686 	$args = wp_parse_args( $args );
  1113 	$args = wp_parse_args( $args );
   694 /**
  1121 /**
   695  * Get the blogs a user belongs to.
  1122  * Get the blogs a user belongs to.
   696  *
  1123  *
   697  * @since 3.0.0
  1124  * @since 3.0.0
   698  *
  1125  *
   699  * @param int $user_id User ID
  1126  * @global wpdb $wpdb WordPress database object for queries.
   700  * @param bool $all Whether to retrieve all blogs, or only blogs that are not marked as deleted, archived, or spam.
  1127  *
   701  * @return array A list of the user's blogs. An empty array if the user doesn't exist or belongs to no blogs.
  1128  * @param int  $user_id User ID
       
  1129  * @param bool $all     Whether to retrieve all blogs, or only blogs that are not
       
  1130  *                      marked as deleted, archived, or spam.
       
  1131  * @return array A list of the user's blogs. An empty array if the user doesn't exist
       
  1132  *               or belongs to no blogs.
   702  */
  1133  */
   703 function get_blogs_of_user( $user_id, $all = false ) {
  1134 function get_blogs_of_user( $user_id, $all = false ) {
   704 	global $wpdb;
  1135 	global $wpdb;
   705 
  1136 
   706 	$user_id = (int) $user_id;
  1137 	$user_id = (int) $user_id;
   774 				'deleted'     => 0
  1205 				'deleted'     => 0
   775 			);
  1206 			);
   776 		}
  1207 		}
   777 	}
  1208 	}
   778 
  1209 
       
  1210 	/**
       
  1211 	 * Filter the list of blogs a user belongs to.
       
  1212 	 *
       
  1213 	 * @since MU
       
  1214 	 *
       
  1215 	 * @param array $blogs   An array of blog objects belonging to the user.
       
  1216 	 * @param int   $user_id User ID.
       
  1217 	 * @param bool  $all     Whether the returned blogs array should contain all blogs, including
       
  1218 	 *                       those marked 'deleted', 'archived', or 'spam'. Default false.
       
  1219 	 */
   779 	return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all );
  1220 	return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all );
   780 }
  1221 }
   781 
  1222 
   782 /**
  1223 /**
   783  * Find out whether a user is a member of a given blog.
  1224  * Find out whether a user is a member of a given blog.
   784  *
  1225  *
   785  * @since MU 1.1
  1226  * @since MU 1.1
   786  * @uses get_blogs_of_user()
       
   787  *
  1227  *
   788  * @param int $user_id Optional. The unique ID of the user. Defaults to the current user.
  1228  * @param int $user_id Optional. The unique ID of the user. Defaults to the current user.
   789  * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site.
  1229  * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site.
   790  * @return bool
  1230  * @return bool
   791  */
  1231  */
   807  * Add meta data field to a user.
  1247  * Add meta data field to a user.
   808  *
  1248  *
   809  * Post meta data is called "Custom Fields" on the Administration Screens.
  1249  * Post meta data is called "Custom Fields" on the Administration Screens.
   810  *
  1250  *
   811  * @since 3.0.0
  1251  * @since 3.0.0
   812  * @uses add_metadata()
  1252  * @link https://codex.wordpress.org/Function_Reference/add_user_meta
   813  * @link http://codex.wordpress.org/Function_Reference/add_user_meta
  1253  *
   814  *
  1254  * @param int $user_id User ID.
   815  * @param int $user_id Post ID.
       
   816  * @param string $meta_key Metadata name.
  1255  * @param string $meta_key Metadata name.
   817  * @param mixed $meta_value Metadata value.
  1256  * @param mixed $meta_value Metadata value.
   818  * @param bool $unique Optional, default is false. Whether the same key should not be added.
  1257  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   819  * @return int|bool Meta ID on success, false on failure.
  1258  * @return int|bool Meta ID on success, false on failure.
   820  */
  1259  */
   828  * You can match based on the key, or key and value. Removing based on key and
  1267  * You can match based on the key, or key and value. Removing based on key and
   829  * value, will keep from removing duplicate metadata with the same key. It also
  1268  * value, will keep from removing duplicate metadata with the same key. It also
   830  * allows removing all metadata matching key, if needed.
  1269  * allows removing all metadata matching key, if needed.
   831  *
  1270  *
   832  * @since 3.0.0
  1271  * @since 3.0.0
   833  * @uses delete_metadata()
  1272  * @link https://codex.wordpress.org/Function_Reference/delete_user_meta
   834  * @link http://codex.wordpress.org/Function_Reference/delete_user_meta
       
   835  *
  1273  *
   836  * @param int $user_id user ID
  1274  * @param int $user_id user ID
   837  * @param string $meta_key Metadata name.
  1275  * @param string $meta_key Metadata name.
   838  * @param mixed $meta_value Optional. Metadata value.
  1276  * @param mixed $meta_value Optional. Metadata value.
   839  * @return bool True on success, false on failure.
  1277  * @return bool True on success, false on failure.
   844 
  1282 
   845 /**
  1283 /**
   846  * Retrieve user meta field for a user.
  1284  * Retrieve user meta field for a user.
   847  *
  1285  *
   848  * @since 3.0.0
  1286  * @since 3.0.0
   849  * @uses get_metadata()
  1287  * @link https://codex.wordpress.org/Function_Reference/get_user_meta
   850  * @link http://codex.wordpress.org/Function_Reference/get_user_meta
  1288  *
   851  *
  1289  * @param int $user_id User ID.
   852  * @param int $user_id Post ID.
       
   853  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
  1290  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
   854  * @param bool $single Whether to return a single value.
  1291  * @param bool $single Whether to return a single value.
   855  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
  1292  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   856  *  is true.
  1293  *  is true.
   857  */
  1294  */
   866  * same key and user ID.
  1303  * same key and user ID.
   867  *
  1304  *
   868  * If the meta field for the user does not exist, it will be added.
  1305  * If the meta field for the user does not exist, it will be added.
   869  *
  1306  *
   870  * @since 3.0.0
  1307  * @since 3.0.0
   871  * @uses update_metadata
  1308  * @link https://codex.wordpress.org/Function_Reference/update_user_meta
   872  * @link http://codex.wordpress.org/Function_Reference/update_user_meta
  1309  *
   873  *
  1310  * @param int $user_id User ID.
   874  * @param int $user_id Post ID.
       
   875  * @param string $meta_key Metadata key.
  1311  * @param string $meta_key Metadata key.
   876  * @param mixed $meta_value Metadata value.
  1312  * @param mixed $meta_value Metadata value.
   877  * @param mixed $prev_value Optional. Previous value to check before removing.
  1313  * @param mixed $prev_value Optional. Previous value to check before removing.
   878  * @return bool True on success, false on failure.
  1314  * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
   879  */
  1315  */
   880 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') {
  1316 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') {
   881 	return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value);
  1317 	return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value);
   882 }
  1318 }
   883 
  1319 
   910 		$avail_roles = $wp_roles->get_names();
  1346 		$avail_roles = $wp_roles->get_names();
   911 
  1347 
   912 		// Build a CPU-intensive query that will return concise information.
  1348 		// Build a CPU-intensive query that will return concise information.
   913 		$select_count = array();
  1349 		$select_count = array();
   914 		foreach ( $avail_roles as $this_role => $name ) {
  1350 		foreach ( $avail_roles as $this_role => $name ) {
   915 			$select_count[] = "COUNT(NULLIF(`meta_value` LIKE '%\"" . like_escape( $this_role ) . "\"%', false))";
  1351 			$select_count[] = $wpdb->prepare( "COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%');
   916 		}
  1352 		}
   917 		$select_count = implode(', ', $select_count);
  1353 		$select_count = implode(', ', $select_count);
   918 
  1354 
   919 		// Add the meta_value index to the selection list, then run the query.
  1355 		// Add the meta_value index to the selection list, then run the query.
   920 		$row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N );
  1356 		$row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N );
  1010  * setting the 'echo' argument. The 'include' and 'exclude' arguments do not
  1446  * setting the 'echo' argument. The 'include' and 'exclude' arguments do not
  1011  * need to be used; all users will be displayed in that case. Only one can be
  1447  * need to be used; all users will be displayed in that case. Only one can be
  1012  * used, either 'include' or 'exclude', but not both.
  1448  * used, either 'include' or 'exclude', but not both.
  1013  *
  1449  *
  1014  * The available arguments are as follows:
  1450  * The available arguments are as follows:
  1015  * <ol>
       
  1016  * <li>show_option_all - Text to show all and whether HTML option exists.</li>
       
  1017  * <li>show_option_none - Text for show none and whether HTML option exists.</li>
       
  1018  * <li>hide_if_only_one_author - Don't create the dropdown if there is only one user.</li>
       
  1019  * <li>orderby - SQL order by clause for what order the users appear. Default is 'display_name'.</li>
       
  1020  * <li>order - Default is 'ASC'. Can also be 'DESC'.</li>
       
  1021  * <li>include - User IDs to include.</li>
       
  1022  * <li>exclude - User IDs to exclude.</li>
       
  1023  * <li>multi - Default is 'false'. Whether to skip the ID attribute on the 'select' element. A 'true' value is overridden when id argument is set.</li>
       
  1024  * <li>show - Default is 'display_name'. User table column to display. If the selected item is empty then the user_login will be displayed in parentheses</li>
       
  1025  * <li>echo - Default is '1'. Whether to display or retrieve content.</li>
       
  1026  * <li>selected - Which User ID is selected.</li>
       
  1027  * <li>include_selected - Always include the selected user ID in the dropdown. Default is false.</li>
       
  1028  * <li>name - Default is 'user'. Name attribute of select element.</li>
       
  1029  * <li>id - Default is the value of the 'name' parameter. ID attribute of select element.</li>
       
  1030  * <li>class - Class attribute of select element.</li>
       
  1031  * <li>blog_id - ID of blog (Multisite only). Defaults to ID of current blog.</li>
       
  1032  * <li>who - Which users to query. Currently only 'authors' is supported. Default is all users.</li>
       
  1033  * </ol>
       
  1034  *
  1451  *
  1035  * @since 2.3.0
  1452  * @since 2.3.0
  1036  * @uses $wpdb WordPress database object for queries
  1453  *
  1037  *
  1454  * @global wpdb $wpdb WordPress database object for queries.
  1038  * @param string|array $args Optional. Override defaults.
  1455  *
       
  1456  * @param array|string $args {
       
  1457  *     Optional. Array or string of arguments to generate a drop-down of users.
       
  1458  *     {@see WP_User_Query::prepare_query() for additional available arguments.
       
  1459  *
       
  1460  *     @type string       $show_option_all         Text to show as the drop-down default (all).
       
  1461  *                                                 Default empty.
       
  1462  *     @type string       $show_option_none        Text to show as the drop-down default when no
       
  1463  *                                                 users were found. Default empty.
       
  1464  *     @type int|string   $option_none_value       Value to use for $show_option_non when no users
       
  1465  *                                                 were found. Default -1.
       
  1466  *     @type string       $hide_if_only_one_author Whether to skip generating the drop-down
       
  1467  *                                                 if only one user was found. Default empty.
       
  1468  *     @type string       $orderby                 Field to order found users by. Accepts user fields.
       
  1469  *                                                 Default 'display_name'.
       
  1470  *     @type string       $order                   Whether to order users in ascending or descending
       
  1471  *                                                 order. Accepts 'ASC' (ascending) or 'DESC' (descending).
       
  1472  *                                                 Default 'ASC'.
       
  1473  *     @type array|string $include                 Array or comma-separated list of user IDs to include.
       
  1474  *                                                 Default empty.
       
  1475  *     @type array|string $exclude                 Array or comma-separated list of user IDs to exclude.
       
  1476  *                                                 Default empty.
       
  1477  *     @type bool|int     $multi                   Whether to skip the ID attribute on the 'select' element.
       
  1478  *                                                 Accepts 1|true or 0|false. Default 0|false.
       
  1479  *     @type string       $show                    User table column to display. If the selected item is empty
       
  1480  *                                                 then the 'user_login' will be displayed in parentheses.
       
  1481  *                                                 Accepts user fields. Default 'display_name'.
       
  1482  *     @type int|bool     $echo                    Whether to echo or return the drop-down. Accepts 1|true (echo)
       
  1483  *                                                 or 0|false (return). Default 1|true.
       
  1484  *     @type int          $selected                Which user ID should be selected. Default 0.
       
  1485  *     @type bool         $include_selected        Whether to always include the selected user ID in the drop-
       
  1486  *                                                 down. Default false.
       
  1487  *     @type string       $name                    Name attribute of select element. Default 'user'.
       
  1488  *     @type string       $id                      ID attribute of the select element. Default is the value of $name.
       
  1489  *     @type string       $class                   Class attribute of the select element. Default empty.
       
  1490  *     @type int          $blog_id                 ID of blog (Multisite only). Default is ID of the current blog.
       
  1491  *     @type string       $who                     Which type of users to query. Accepts only an empty string or
       
  1492  *                                                 'authors'. Default empty.
       
  1493  * }
  1039  * @return string|null Null on display. String of HTML content on retrieve.
  1494  * @return string|null Null on display. String of HTML content on retrieve.
  1040  */
  1495  */
  1041 function wp_dropdown_users( $args = '' ) {
  1496 function wp_dropdown_users( $args = '' ) {
  1042 	$defaults = array(
  1497 	$defaults = array(
  1043 		'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',
  1498 		'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',
  1044 		'orderby' => 'display_name', 'order' => 'ASC',
  1499 		'orderby' => 'display_name', 'order' => 'ASC',
  1045 		'include' => '', 'exclude' => '', 'multi' => 0,
  1500 		'include' => '', 'exclude' => '', 'multi' => 0,
  1046 		'show' => 'display_name', 'echo' => 1,
  1501 		'show' => 'display_name', 'echo' => 1,
  1047 		'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',
  1502 		'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',
  1048 		'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false
  1503 		'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false,
       
  1504 		'option_none_value' => -1
  1049 	);
  1505 	);
  1050 
  1506 
  1051 	$defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;
  1507 	$defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;
  1052 
  1508 
  1053 	$r = wp_parse_args( $args, $defaults );
  1509 	$r = wp_parse_args( $args, $defaults );
  1054 	extract( $r, EXTR_SKIP );
  1510 	$show = $r['show'];
       
  1511 	$show_option_all = $r['show_option_all'];
       
  1512 	$show_option_none = $r['show_option_none'];
       
  1513 	$option_none_value = $r['option_none_value'];
  1055 
  1514 
  1056 	$query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who' ) );
  1515 	$query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who' ) );
  1057 	$query_args['fields'] = array( 'ID', 'user_login', $show );
  1516 	$query_args['fields'] = array( 'ID', 'user_login', $show );
  1058 	$users = get_users( $query_args );
  1517 	$users = get_users( $query_args );
  1059 
  1518 
  1060 	$output = '';
  1519 	$output = '';
  1061 	if ( !empty($users) && ( empty($hide_if_only_one_author) || count($users) > 1 ) ) {
  1520 	if ( ! empty( $users ) && ( empty( $r['hide_if_only_one_author'] ) || count( $users ) > 1 ) ) {
  1062 		$name = esc_attr( $name );
  1521 		$name = esc_attr( $r['name'] );
  1063 		if ( $multi && ! $id )
  1522 		if ( $r['multi'] && ! $r['id'] ) {
  1064 			$id = '';
  1523 			$id = '';
  1065 		else
  1524 		} else {
  1066 			$id = $id ? " id='" . esc_attr( $id ) . "'" : " id='$name'";
  1525 			$id = $r['id'] ? " id='" . esc_attr( $r['id'] ) . "'" : " id='$name'";
  1067 
  1526 		}
  1068 		$output = "<select name='{$name}'{$id} class='$class'>\n";
  1527 		$output = "<select name='{$name}'{$id} class='" . $r['class'] . "'>\n";
  1069 
  1528 
  1070 		if ( $show_option_all )
  1529 		if ( $show_option_all ) {
  1071 			$output .= "\t<option value='0'>$show_option_all</option>\n";
  1530 			$output .= "\t<option value='0'>$show_option_all</option>\n";
       
  1531 		}
  1072 
  1532 
  1073 		if ( $show_option_none ) {
  1533 		if ( $show_option_none ) {
  1074 			$_selected = selected( -1, $selected, false );
  1534 			$_selected = selected( $option_none_value, $r['selected'], false );
  1075 			$output .= "\t<option value='-1'$_selected>$show_option_none</option>\n";
  1535 			$output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$_selected>$show_option_none</option>\n";
  1076 		}
  1536 		}
  1077 
  1537 
  1078 		$found_selected = false;
  1538 		$found_selected = false;
  1079 		foreach ( (array) $users as $user ) {
  1539 		foreach ( (array) $users as $user ) {
  1080 			$user->ID = (int) $user->ID;
  1540 			$user->ID = (int) $user->ID;
  1081 			$_selected = selected( $user->ID, $selected, false );
  1541 			$_selected = selected( $user->ID, $r['selected'], false );
  1082 			if ( $_selected )
  1542 			if ( $_selected ) {
  1083 				$found_selected = true;
  1543 				$found_selected = true;
  1084 			$display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')';
  1544 			}
  1085 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n";
  1545 			$display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')';
  1086 		}
  1546 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n";
  1087 
  1547 		}
  1088 		if ( $include_selected && ! $found_selected && ( $selected > 0 ) ) {
  1548 
  1089 			$user = get_userdata( $selected );
  1549 		if ( $r['include_selected'] && ! $found_selected && ( $r['selected'] > 0 ) ) {
  1090 			$_selected = selected( $user->ID, $selected, false );
  1550 			$user = get_userdata( $r['selected'] );
  1091 			$display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')';
  1551 			$_selected = selected( $user->ID, $r['selected'], false );
  1092 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n";
  1552 			$display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')';
       
  1553 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n";
  1093 		}
  1554 		}
  1094 
  1555 
  1095 		$output .= "</select>";
  1556 		$output .= "</select>";
  1096 	}
  1557 	}
  1097 
  1558 
  1098 	$output = apply_filters('wp_dropdown_users', $output);
  1559 	/**
  1099 
  1560 	 * Filter the wp_dropdown_users() HTML output.
  1100 	if ( $echo )
  1561 	 *
  1101 		echo $output;
  1562 	 * @since 2.3.0
  1102 
  1563 	 *
  1103 	return $output;
  1564 	 * @param string $output HTML output generated by wp_dropdown_users().
       
  1565 	 */
       
  1566 	$html = apply_filters( 'wp_dropdown_users', $output );
       
  1567 
       
  1568 	if ( $r['echo'] ) {
       
  1569 		echo $html;
       
  1570 	}
       
  1571 	return $html;
  1104 }
  1572 }
  1105 
  1573 
  1106 /**
  1574 /**
  1107  * Sanitize user field based on context.
  1575  * Sanitize user field based on context.
  1108  *
  1576  *
  1109  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
  1577  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
  1110  * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
  1578  * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
  1111  * when calling filters.
  1579  * when calling filters.
  1112  *
  1580  *
  1113  * @since 2.3.0
  1581  * @since 2.3.0
  1114  * @uses apply_filters() Calls 'edit_$field' passing $value and $user_id if $context == 'edit'.
       
  1115  *  $field is prefixed with 'user_' if it isn't already.
       
  1116  * @uses apply_filters() Calls 'pre_$field' passing $value if $context == 'db'. $field is prefixed with
       
  1117  *  'user_' if it isn't already.
       
  1118  * @uses apply_filters() Calls '$field' passing $value, $user_id and $context if $context == anything
       
  1119  *  other than 'raw', 'edit' and 'db'. $field is prefixed with 'user_' if it isn't already.
       
  1120  *
  1582  *
  1121  * @param string $field The user Object field name.
  1583  * @param string $field The user Object field name.
  1122  * @param mixed $value The user Object value.
  1584  * @param mixed $value The user Object value.
  1123  * @param int $user_id user ID.
  1585  * @param int $user_id user ID.
  1124  * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
  1586  * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
  1138 
  1600 
  1139 	$prefixed = false !== strpos( $field, 'user_' );
  1601 	$prefixed = false !== strpos( $field, 'user_' );
  1140 
  1602 
  1141 	if ( 'edit' == $context ) {
  1603 	if ( 'edit' == $context ) {
  1142 		if ( $prefixed ) {
  1604 		if ( $prefixed ) {
  1143 			$value = apply_filters("edit_{$field}", $value, $user_id);
  1605 
       
  1606 			/** This filter is documented in wp-includes/post.php */
       
  1607 			$value = apply_filters( "edit_{$field}", $value, $user_id );
  1144 		} else {
  1608 		} else {
  1145 			$value = apply_filters("edit_user_{$field}", $value, $user_id);
  1609 
       
  1610 			/**
       
  1611 			 * Filter a user field value in the 'edit' context.
       
  1612 			 *
       
  1613 			 * The dynamic portion of the hook name, `$field`, refers to the prefixed user
       
  1614 			 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
       
  1615 			 *
       
  1616 			 * @since 2.9.0
       
  1617 			 *
       
  1618 			 * @param mixed $value   Value of the prefixed user field.
       
  1619 			 * @param int   $user_id User ID.
       
  1620 			 */
       
  1621 			$value = apply_filters( "edit_user_{$field}", $value, $user_id );
  1146 		}
  1622 		}
  1147 
  1623 
  1148 		if ( 'description' == $field )
  1624 		if ( 'description' == $field )
  1149 			$value = esc_html( $value ); // textarea_escaped?
  1625 			$value = esc_html( $value ); // textarea_escaped?
  1150 		else
  1626 		else
  1151 			$value = esc_attr($value);
  1627 			$value = esc_attr($value);
  1152 	} else if ( 'db' == $context ) {
  1628 	} elseif ( 'db' == $context ) {
  1153 		if ( $prefixed ) {
  1629 		if ( $prefixed ) {
  1154 			$value = apply_filters("pre_{$field}", $value);
  1630 			/** This filter is documented in wp-includes/post.php */
       
  1631 			$value = apply_filters( "pre_{$field}", $value );
  1155 		} else {
  1632 		} else {
  1156 			$value = apply_filters("pre_user_{$field}", $value);
  1633 
       
  1634 			/**
       
  1635 			 * Filter the value of a user field in the 'db' context.
       
  1636 			 *
       
  1637 			 * The dynamic portion of the hook name, `$field`, refers to the prefixed user
       
  1638 			 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
       
  1639  			 *
       
  1640 			 * @since 2.9.0
       
  1641 			 *
       
  1642 			 * @param mixed $value Value of the prefixed user field.
       
  1643 			 */
       
  1644 			$value = apply_filters( "pre_user_{$field}", $value );
  1157 		}
  1645 		}
  1158 	} else {
  1646 	} else {
  1159 		// Use display filters by default.
  1647 		// Use display filters by default.
  1160 		if ( $prefixed )
  1648 		if ( $prefixed ) {
  1161 			$value = apply_filters($field, $value, $user_id, $context);
  1649 
  1162 		else
  1650 			/** This filter is documented in wp-includes/post.php */
  1163 			$value = apply_filters("user_{$field}", $value, $user_id, $context);
  1651 			$value = apply_filters( $field, $value, $user_id, $context );
       
  1652 		} else {
       
  1653 
       
  1654 			/**
       
  1655 			 * Filter the value of a user field in a standard context.
       
  1656 			 *
       
  1657 			 * The dynamic portion of the hook name, `$field`, refers to the prefixed user
       
  1658 			 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.
       
  1659 			 *
       
  1660 			 * @since 2.9.0
       
  1661 			 *
       
  1662 			 * @param mixed  $value   The user object value to sanitize.
       
  1663 			 * @param int    $user_id User ID.
       
  1664 			 * @param string $context The context to filter within.
       
  1665 			 */
       
  1666 			$value = apply_filters( "user_{$field}", $value, $user_id, $context );
       
  1667 		}
  1164 	}
  1668 	}
  1165 
  1669 
  1166 	if ( 'user_url' == $field )
  1670 	if ( 'user_url' == $field )
  1167 		$value = esc_url($value);
  1671 		$value = esc_url($value);
  1168 
  1672 
  1169 	if ( 'attribute' == $context )
  1673 	if ( 'attribute' == $context ) {
  1170 		$value = esc_attr($value);
  1674 		$value = esc_attr( $value );
  1171 	else if ( 'js' == $context )
  1675 	} elseif ( 'js' == $context ) {
  1172 		$value = esc_js($value);
  1676 		$value = esc_js( $value );
  1173 
  1677 	}
  1174 	return $value;
  1678 	return $value;
  1175 }
  1679 }
  1176 
  1680 
  1177 /**
  1681 /**
  1178  * Update all user caches
  1682  * Update all user caches
  1226 
  1730 
  1227 /**
  1731 /**
  1228  * Checks whether the given email exists.
  1732  * Checks whether the given email exists.
  1229  *
  1733  *
  1230  * @since 2.1.0
  1734  * @since 2.1.0
  1231  * @uses $wpdb
       
  1232  *
  1735  *
  1233  * @param string $email Email.
  1736  * @param string $email Email.
  1234  * @return bool|int The user's ID on success, and false on failure.
  1737  * @return bool|int The user's ID on success, and false on failure.
  1235  */
  1738  */
  1236 function email_exists( $email ) {
  1739 function email_exists( $email ) {
  1239 
  1742 
  1240 	return false;
  1743 	return false;
  1241 }
  1744 }
  1242 
  1745 
  1243 /**
  1746 /**
  1244  * Checks whether an username is valid.
  1747  * Checks whether a username is valid.
  1245  *
  1748  *
  1246  * @since 2.0.1
  1749  * @since 2.0.1
  1247  * @uses apply_filters() Calls 'validate_username' hook on $valid check and $username as parameters
       
  1248  *
  1750  *
  1249  * @param string $username Username.
  1751  * @param string $username Username.
  1250  * @return bool Whether username given is valid
  1752  * @return bool Whether username given is valid
  1251  */
  1753  */
  1252 function validate_username( $username ) {
  1754 function validate_username( $username ) {
  1253 	$sanitized = sanitize_user( $username, true );
  1755 	$sanitized = sanitize_user( $username, true );
  1254 	$valid = ( $sanitized == $username );
  1756 	$valid = ( $sanitized == $username );
       
  1757 	/**
       
  1758 	 * Filter whether the provided username is valid or not.
       
  1759 	 *
       
  1760 	 * @since 2.0.1
       
  1761 	 *
       
  1762 	 * @param bool   $valid    Whether given username is valid.
       
  1763 	 * @param string $username Username to check.
       
  1764 	 */
  1255 	return apply_filters( 'validate_username', $valid, $username );
  1765 	return apply_filters( 'validate_username', $valid, $username );
  1256 }
  1766 }
  1257 
  1767 
  1258 /**
  1768 /**
  1259  * Insert an user into the database.
  1769  * Insert a user into the database.
  1260  *
       
  1261  * Can update a current user or insert a new user based on whether the user's ID
       
  1262  * is present.
       
  1263  *
       
  1264  * Can be used to update the user's info (see below), set the user's role, and
       
  1265  * set the user's preference on whether they want the rich editor on.
       
  1266  *
  1770  *
  1267  * Most of the $userdata array fields have filters associated with the values.
  1771  * Most of the $userdata array fields have filters associated with the values.
  1268  * The exceptions are 'rich_editing', 'role', 'jabber', 'aim', 'yim',
  1772  * The exceptions are 'rich_editing', 'role', 'jabber', 'aim', 'yim',
  1269  * 'user_registered', and 'ID'. The filters have the prefix 'pre_user_' followed
  1773  * 'user_registered', and 'ID'. The filters have the prefix 'pre_user_' followed
  1270  * by the field name. An example using 'description' would have the filter
  1774  * by the field name. An example using 'description' would have the filter
  1271  * called, 'pre_user_description' that can be hooked into.
  1775  * called, 'pre_user_description' that can be hooked into.
  1272  *
  1776  *
  1273  * The $userdata array can contain the following fields:
       
  1274  * 'ID' - An integer that will be used for updating an existing user.
       
  1275  * 'user_pass' - A string that contains the plain text password for the user.
       
  1276  * 'user_login' - A string that contains the user's username for logging in.
       
  1277  * 'user_nicename' - A string that contains a URL-friendly name for the user.
       
  1278  *		The default is the user's username.
       
  1279  * 'user_url' - A string containing the user's URL for the user's web site.
       
  1280  * 'user_email' - A string containing the user's email address.
       
  1281  * 'display_name' - A string that will be shown on the site. Defaults to user's
       
  1282  *		username. It is likely that you will want to change this, for appearance.
       
  1283  * 'nickname' - The user's nickname, defaults to the user's username.
       
  1284  * 'first_name' - The user's first name.
       
  1285  * 'last_name' - The user's last name.
       
  1286  * 'description' - A string containing content about the user.
       
  1287  * 'rich_editing' - A string for whether to enable the rich editor. False
       
  1288  *		if not empty.
       
  1289  * 'user_registered' - The date the user registered. Format is 'Y-m-d H:i:s'.
       
  1290  * 'role' - A string used to set the user's role.
       
  1291  * 'jabber' - User's Jabber account.
       
  1292  * 'aim' - User's AOL IM account.
       
  1293  * 'yim' - User's Yahoo IM account.
       
  1294  *
       
  1295  * @since 2.0.0
  1777  * @since 2.0.0
  1296  * @uses $wpdb WordPress database layer.
  1778  *
  1297  * @uses apply_filters() Calls filters for most of the $userdata fields with the prefix 'pre_user'. See note above.
  1779  * @global wpdb $wpdb WordPress database object for queries.
  1298  * @uses do_action() Calls 'profile_update' hook when updating giving the user's ID
  1780  *
  1299  * @uses do_action() Calls 'user_register' hook when creating a new user giving the user's ID
  1781  * @param array $userdata {
  1300  *
  1782  *     An array, object, or WP_User object of user data arguments.
  1301  * @param mixed $userdata An array of user data or a user object of type stdClass or WP_User.
  1783  *
  1302  * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not be created.
  1784  *     @type int         $ID              User ID. If supplied, the user will be updated.
       
  1785  *     @type string      $user_pass       The plain-text user password.
       
  1786  *     @type string      $user_login      The user's login username.
       
  1787  *     @type string      $user_nicename   The URL-friendly user name.
       
  1788  *     @type string      $user_url        The user URL.
       
  1789  *     @type string      $user_email      The user email address.
       
  1790  *     @type string      $display_name    The user's display name.
       
  1791  *                                        Default is the the user's username.
       
  1792  *     @type string      $nickname        The user's nickname. Default
       
  1793  *                                        Default is the the user's username.
       
  1794  *     @type string      $first_name      The user's first name. For new users, will be used
       
  1795  *                                        to build $display_name if unspecified.
       
  1796  *     @type stirng      $last_name       The user's last name. For new users, will be used
       
  1797  *                                        to build $display_name if unspecified.
       
  1798  *     @type string|bool $rich_editing    Whether to enable the rich-editor for the user. False
       
  1799  *                                        if not empty.
       
  1800  *     @type string      $user_registered Date the user registered. Format is 'Y-m-d H:i:s'.
       
  1801  *     @type string      $role            User's role.
       
  1802  *     @type string      $jabber          User's Jabber account username.
       
  1803  *     @type string      $aim             User's AIM account username.
       
  1804  *     @type string      $yim             User's Yahoo! messenger username.
       
  1805  * }
       
  1806  * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not
       
  1807  *                      be created.
  1303  */
  1808  */
  1304 function wp_insert_user( $userdata ) {
  1809 function wp_insert_user( $userdata ) {
  1305 	global $wpdb;
  1810 	global $wpdb;
  1306 
  1811 
  1307 	if ( is_a( $userdata, 'stdClass' ) )
  1812 	if ( $userdata instanceof stdClass ) {
  1308 		$userdata = get_object_vars( $userdata );
  1813 		$userdata = get_object_vars( $userdata );
  1309 	elseif ( is_a( $userdata, 'WP_User' ) )
  1814 	} elseif ( $userdata instanceof WP_User ) {
  1310 		$userdata = $userdata->to_array();
  1815 		$userdata = $userdata->to_array();
  1311 
  1816 	}
  1312 	extract( $userdata, EXTR_SKIP );
       
  1313 
       
  1314 	// Are we updating or creating?
  1817 	// Are we updating or creating?
  1315 	if ( !empty($ID) ) {
  1818 	if ( ! empty( $userdata['ID'] ) ) {
  1316 		$ID = (int) $ID;
  1819 		$ID = (int) $userdata['ID'];
  1317 		$update = true;
  1820 		$update = true;
  1318 		$old_user_data = WP_User::get_data_by( 'id', $ID );
  1821 		$old_user_data = WP_User::get_data_by( 'id', $ID );
       
  1822 		// hashed in wp_update_user(), plaintext if called directly
       
  1823 		$user_pass = $userdata['user_pass'];
  1319 	} else {
  1824 	} else {
  1320 		$update = false;
  1825 		$update = false;
  1321 		// Hash the password
  1826 		// Hash the password
  1322 		$user_pass = wp_hash_password($user_pass);
  1827 		$user_pass = wp_hash_password( $userdata['user_pass'] );
  1323 	}
  1828 	}
  1324 
  1829 
  1325 	$user_login = sanitize_user($user_login, true);
  1830 	$sanitized_user_login = sanitize_user( $userdata['user_login'], true );
  1326 	$user_login = apply_filters('pre_user_login', $user_login);
  1831 
       
  1832 	/**
       
  1833 	 * Filter a username after it has been sanitized.
       
  1834 	 *
       
  1835 	 * This filter is called before the user is created or updated.
       
  1836 	 *
       
  1837 	 * @since 2.0.3
       
  1838 	 *
       
  1839 	 * @param string $sanitized_user_login Username after it has been sanitized.
       
  1840 	 */
       
  1841 	$pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login );
  1327 
  1842 
  1328 	//Remove any non-printable chars from the login string to see if we have ended up with an empty username
  1843 	//Remove any non-printable chars from the login string to see if we have ended up with an empty username
  1329 	$user_login = trim($user_login);
  1844 	$user_login = trim( $pre_user_login );
  1330 
  1845 
  1331 	if ( empty($user_login) )
  1846 	if ( empty( $user_login ) ) {
  1332 		return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') );
  1847 		return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') );
  1333 
  1848 	}
  1334 	if ( !$update && username_exists( $user_login ) )
  1849 	if ( ! $update && username_exists( $user_login ) ) {
  1335 		return new WP_Error( 'existing_user_login', __( 'Sorry, that username already exists!' ) );
  1850 		return new WP_Error( 'existing_user_login', __( 'Sorry, that username already exists!' ) );
  1336 
  1851 	}
  1337 	if ( empty($user_nicename) )
  1852 
  1338 		$user_nicename = sanitize_title( $user_login );
  1853 	// If a nicename is provided, remove unsafe user characters before
  1339 	$user_nicename = apply_filters('pre_user_nicename', $user_nicename);
  1854 	// using it. Otherwise build a nicename from the user_login.
  1340 
  1855 	if ( ! empty( $userdata['user_nicename'] ) ) {
  1341 	if ( empty($user_url) )
  1856 		$user_nicename = sanitize_user( $userdata['user_nicename'], true );
  1342 		$user_url = '';
  1857 	} else {
  1343 	$user_url = apply_filters('pre_user_url', $user_url);
  1858 		$user_nicename = $user_login;
  1344 
  1859 	}
  1345 	if ( empty($user_email) )
  1860 
  1346 		$user_email = '';
  1861 	$user_nicename = sanitize_title( $user_nicename );
  1347 	$user_email = apply_filters('pre_user_email', $user_email);
  1862 
  1348 
  1863 	// Store values to save in user meta.
  1349 	if ( !$update && ! defined( 'WP_IMPORTING' ) && email_exists($user_email) )
  1864 	$meta = array();
       
  1865 
       
  1866 	/**
       
  1867 	 * Filter a user's nicename before the user is created or updated.
       
  1868 	 *
       
  1869 	 * @since 2.0.3
       
  1870 	 *
       
  1871 	 * @param string $user_nicename The user's nicename.
       
  1872 	 */
       
  1873 	$user_nicename = apply_filters( 'pre_user_nicename', $user_nicename );
       
  1874 
       
  1875 	$raw_user_url = empty( $userdata['user_url'] ) ? '' : $userdata['user_url'];
       
  1876 
       
  1877 	/**
       
  1878 	 * Filter a user's URL before the user is created or updated.
       
  1879 	 *
       
  1880 	 * @since 2.0.3
       
  1881 	 *
       
  1882 	 * @param string $raw_user_url The user's URL.
       
  1883 	 */
       
  1884 	$user_url = apply_filters( 'pre_user_url', $raw_user_url );
       
  1885 
       
  1886 	$raw_user_email = empty( $userdata['user_email'] ) ? '' : $userdata['user_email'];
       
  1887 
       
  1888 	/**
       
  1889 	 * Filter a user's email before the user is created or updated.
       
  1890 	 *
       
  1891 	 * @since 2.0.3
       
  1892 	 *
       
  1893 	 * @param string $raw_user_email The user's email.
       
  1894 	 */
       
  1895 	$user_email = apply_filters( 'pre_user_email', $raw_user_email );
       
  1896 
       
  1897 	/*
       
  1898 	 * If there is no update, just check for `email_exists`. If there is an update,
       
  1899 	 * check if current email and new email are the same, or not, and check `email_exists`
       
  1900 	 * accordingly.
       
  1901 	 */
       
  1902 	if ( ( ! $update || ( ! empty( $old_user_data ) && $user_email !== $old_user_data->user_email ) )
       
  1903 		&& ! defined( 'WP_IMPORTING' )
       
  1904 		&& email_exists( $user_email )
       
  1905 	) {
  1350 		return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) );
  1906 		return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) );
  1351 
  1907 	}
  1352 	if ( empty($nickname) )
  1908 	$nickname = empty( $userdata['nickname'] ) ? $user_login : $userdata['nickname'];
  1353 		$nickname = $user_login;
  1909 
  1354 	$nickname = apply_filters('pre_user_nickname', $nickname);
  1910 	/**
  1355 
  1911 	 * Filter a user's nickname before the user is created or updated.
  1356 	if ( empty($first_name) )
  1912 	 *
  1357 		$first_name = '';
  1913 	 * @since 2.0.3
  1358 	$first_name = apply_filters('pre_user_first_name', $first_name);
  1914 	 *
  1359 
  1915 	 * @param string $nickname The user's nickname.
  1360 	if ( empty($last_name) )
  1916 	 */
  1361 		$last_name = '';
  1917 	$meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname );
  1362 	$last_name = apply_filters('pre_user_last_name', $last_name);
  1918 
  1363 
  1919 	$first_name = empty( $userdata['first_name'] ) ? '' : $userdata['first_name'];
  1364 	if ( empty( $display_name ) ) {
  1920 
  1365 		if ( $update )
  1921 	/**
       
  1922 	 * Filter a user's first name before the user is created or updated.
       
  1923 	 *
       
  1924 	 * @since 2.0.3
       
  1925 	 *
       
  1926 	 * @param string $first_name The user's first name.
       
  1927 	 */
       
  1928 	$meta['first_name'] = apply_filters( 'pre_user_first_name', $first_name );
       
  1929 
       
  1930 	$last_name = empty( $userdata['last_name'] ) ? '' : $userdata['last_name'];
       
  1931 
       
  1932 	/**
       
  1933 	 * Filter a user's last name before the user is created or updated.
       
  1934 	 *
       
  1935 	 * @since 2.0.3
       
  1936 	 *
       
  1937 	 * @param string $last_name The user's last name.
       
  1938 	 */
       
  1939 	$meta['last_name'] = apply_filters( 'pre_user_last_name', $last_name );
       
  1940 
       
  1941 	if ( empty( $userdata['display_name'] ) ) {
       
  1942 		if ( $update ) {
  1366 			$display_name = $user_login;
  1943 			$display_name = $user_login;
  1367 		elseif ( $first_name && $last_name )
  1944 		} elseif ( $meta['first_name'] && $meta['last_name'] ) {
  1368 			/* translators: 1: first name, 2: last name */
  1945 			/* translators: 1: first name, 2: last name */
  1369 			$display_name = sprintf( _x( '%1$s %2$s', 'Display name based on first name and last name' ), $first_name, $last_name );
  1946 			$display_name = sprintf( _x( '%1$s %2$s', 'Display name based on first name and last name' ), $meta['first_name'], $meta['last_name'] );
  1370 		elseif ( $first_name )
  1947 		} elseif ( $meta['first_name'] ) {
  1371 			$display_name = $first_name;
  1948 			$display_name = $meta['first_name'];
  1372 		elseif ( $last_name )
  1949 		} elseif ( $meta['last_name'] ) {
  1373 			$display_name = $last_name;
  1950 			$display_name = $meta['last_name'];
  1374 		else
  1951 		} else {
  1375 			$display_name = $user_login;
  1952 			$display_name = $user_login;
  1376 	}
  1953 		}
       
  1954 	} else {
       
  1955 		$display_name = $userdata['display_name'];
       
  1956 	}
       
  1957 
       
  1958 	/**
       
  1959 	 * Filter a user's display name before the user is created or updated.
       
  1960 	 *
       
  1961 	 * @since 2.0.3
       
  1962 	 *
       
  1963 	 * @param string $display_name The user's display name.
       
  1964 	 */
  1377 	$display_name = apply_filters( 'pre_user_display_name', $display_name );
  1965 	$display_name = apply_filters( 'pre_user_display_name', $display_name );
  1378 
  1966 
  1379 	if ( empty($description) )
  1967 	$description = empty( $userdata['description'] ) ? '' : $userdata['description'];
  1380 		$description = '';
  1968 
  1381 	$description = apply_filters('pre_user_description', $description);
  1969 	/**
  1382 
  1970 	 * Filter a user's description before the user is created or updated.
  1383 	if ( empty($rich_editing) )
  1971 	 *
  1384 		$rich_editing = 'true';
  1972 	 * @since 2.0.3
  1385 
  1973 	 *
  1386 	if ( empty($comment_shortcuts) )
  1974 	 * @param string $description The user's description.
  1387 		$comment_shortcuts = 'false';
  1975 	 */
  1388 
  1976 	$meta['description'] = apply_filters( 'pre_user_description', $description );
  1389 	if ( empty($admin_color) )
  1977 
  1390 		$admin_color = 'fresh';
  1978 	$meta['rich_editing'] = empty( $userdata['rich_editing'] ) ? 'true' : $userdata['rich_editing'];
  1391 	$admin_color = preg_replace('|[^a-z0-9 _.\-@]|i', '', $admin_color);
  1979 
  1392 
  1980 	$meta['comment_shortcuts'] = empty( $userdata['comment_shortcuts'] ) ? 'false' : $userdata['comment_shortcuts'];
  1393 	if ( empty($use_ssl) )
  1981 
  1394 		$use_ssl = 0;
  1982 	$admin_color = empty( $userdata['admin_color'] ) ? 'fresh' : $userdata['admin_color'];
  1395 
  1983 	$meta['admin_color'] = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $admin_color );
  1396 	if ( empty($user_registered) )
  1984 
  1397 		$user_registered = gmdate('Y-m-d H:i:s');
  1985 	$meta['use_ssl'] = empty( $userdata['use_ssl'] ) ? 0 : $userdata['use_ssl'];
  1398 
  1986 
  1399 	if ( empty($show_admin_bar_front) )
  1987 	$user_registered = empty( $userdata['user_registered'] ) ? gmdate( 'Y-m-d H:i:s' ) : $userdata['user_registered'];
  1400 		$show_admin_bar_front = 'true';
  1988 
       
  1989 	$meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front'];
  1401 
  1990 
  1402 	$user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login));
  1991 	$user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login));
  1403 
  1992 
  1404 	if ( $user_nicename_check ) {
  1993 	if ( $user_nicename_check ) {
  1405 		$suffix = 2;
  1994 		$suffix = 2;
  1409 			$suffix++;
  1998 			$suffix++;
  1410 		}
  1999 		}
  1411 		$user_nicename = $alt_user_nicename;
  2000 		$user_nicename = $alt_user_nicename;
  1412 	}
  2001 	}
  1413 
  2002 
  1414 	$data = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' );
  2003 	$compacted = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' );
  1415 	$data = wp_unslash( $data );
  2004 	$data = wp_unslash( $compacted );
  1416 
  2005 
  1417 	if ( $update ) {
  2006 	if ( $update ) {
       
  2007 		if ( $user_email !== $old_user_data->user_email ) {
       
  2008 			$data['user_activation_key'] = '';
       
  2009 		}
  1418 		$wpdb->update( $wpdb->users, $data, compact( 'ID' ) );
  2010 		$wpdb->update( $wpdb->users, $data, compact( 'ID' ) );
  1419 		$user_id = (int) $ID;
  2011 		$user_id = (int) $ID;
  1420 	} else {
  2012 	} else {
  1421 		$wpdb->insert( $wpdb->users, $data + compact( 'user_login' ) );
  2013 		$wpdb->insert( $wpdb->users, $data + compact( 'user_login' ) );
  1422 		$user_id = (int) $wpdb->insert_id;
  2014 		$user_id = (int) $wpdb->insert_id;
  1423 	}
  2015 	}
  1424 
  2016 
  1425 	$user = new WP_User( $user_id );
  2017 	$user = new WP_User( $user_id );
  1426 
  2018 
  1427 	foreach ( _get_additional_user_keys( $user ) as $key ) {
  2019 	// Update user meta.
  1428 		if ( isset( $$key ) )
  2020 	foreach ( $meta as $key => $value ) {
  1429 			update_user_meta( $user_id, $key, $$key );
  2021 		update_user_meta( $user_id, $key, $value );
  1430 	}
  2022 	}
  1431 
  2023 
  1432 	if ( isset($role) )
  2024 	foreach ( wp_get_user_contact_methods( $user ) as $key => $value ) {
  1433 		$user->set_role($role);
  2025 		if ( isset( $userdata[ $key ] ) ) {
  1434 	elseif ( !$update )
  2026 			update_user_meta( $user_id, $key, $userdata[ $key ] );
       
  2027 		}
       
  2028 	}
       
  2029 
       
  2030 	if ( isset( $userdata['role'] ) ) {
       
  2031 		$user->set_role( $userdata['role'] );
       
  2032 	} elseif ( ! $update ) {
  1435 		$user->set_role(get_option('default_role'));
  2033 		$user->set_role(get_option('default_role'));
  1436 
  2034 	}
  1437 	wp_cache_delete($user_id, 'users');
  2035 	wp_cache_delete( $user_id, 'users' );
  1438 	wp_cache_delete($user_login, 'userlogins');
  2036 	wp_cache_delete( $user_login, 'userlogins' );
  1439 
  2037 
  1440 	if ( $update )
  2038 	if ( $update ) {
  1441 		do_action('profile_update', $user_id, $old_user_data);
  2039 		/**
  1442 	else
  2040 		 * Fires immediately after an existing user is updated.
  1443 		do_action('user_register', $user_id);
  2041 		 *
       
  2042 		 * @since 2.0.0
       
  2043 		 *
       
  2044 		 * @param int    $user_id       User ID.
       
  2045 		 * @param object $old_user_data Object containing user's data prior to update.
       
  2046 		 */
       
  2047 		do_action( 'profile_update', $user_id, $old_user_data );
       
  2048 	} else {
       
  2049 		/**
       
  2050 		 * Fires immediately after a new user is registered.
       
  2051 		 *
       
  2052 		 * @since 1.5.0
       
  2053 		 *
       
  2054 		 * @param int $user_id User ID.
       
  2055 		 */
       
  2056 		do_action( 'user_register', $user_id );
       
  2057 	}
  1444 
  2058 
  1445 	return $user_id;
  2059 	return $user_id;
  1446 }
  2060 }
  1447 
  2061 
  1448 /**
  2062 /**
  1449  * Update an user in the database.
  2063  * Update a user in the database.
  1450  *
  2064  *
  1451  * It is possible to update a user's password by specifying the 'user_pass'
  2065  * It is possible to update a user's password by specifying the 'user_pass'
  1452  * value in the $userdata parameter array.
  2066  * value in the $userdata parameter array.
  1453  *
  2067  *
  1454  * If current user's password is being updated, then the cookies will be
  2068  * If current user's password is being updated, then the cookies will be
  1455  * cleared.
  2069  * cleared.
  1456  *
  2070  *
  1457  * @since 2.0.0
  2071  * @since 2.0.0
  1458  * @see wp_insert_user() For what fields can be set in $userdata
  2072  *
  1459  * @uses wp_insert_user() Used to update existing user or add new one if user doesn't exist already
  2073  * @see wp_insert_user() For what fields can be set in $userdata.
  1460  *
  2074  *
  1461  * @param mixed $userdata An array of user data or a user object of type stdClass or WP_User.
  2075  * @param mixed $userdata An array of user data or a user object of type stdClass or WP_User.
  1462  * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated.
  2076  * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated.
  1463  */
  2077  */
  1464 function wp_update_user($userdata) {
  2078 function wp_update_user($userdata) {
  1465 	if ( is_a( $userdata, 'stdClass' ) )
  2079 	if ( $userdata instanceof stdClass ) {
  1466 		$userdata = get_object_vars( $userdata );
  2080 		$userdata = get_object_vars( $userdata );
  1467 	elseif ( is_a( $userdata, 'WP_User' ) )
  2081 	} elseif ( $userdata instanceof WP_User ) {
  1468 		$userdata = $userdata->to_array();
  2082 		$userdata = $userdata->to_array();
  1469 
  2083 	}
  1470 	$ID = (int) $userdata['ID'];
  2084 
       
  2085 	$ID = isset( $userdata['ID'] ) ? (int) $userdata['ID'] : 0;
       
  2086 	if ( ! $ID ) {
       
  2087 		return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
       
  2088 	}
  1471 
  2089 
  1472 	// First, get all of the original fields
  2090 	// First, get all of the original fields
  1473 	$user_obj = get_userdata( $ID );
  2091 	$user_obj = get_userdata( $ID );
  1474 	if ( ! $user_obj )
  2092 	if ( ! $user_obj ) {
  1475 		return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
  2093 		return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
       
  2094 	}
  1476 
  2095 
  1477 	$user = $user_obj->to_array();
  2096 	$user = $user_obj->to_array();
  1478 
  2097 
  1479 	// Add additional custom fields
  2098 	// Add additional custom fields
  1480 	foreach ( _get_additional_user_keys( $user_obj ) as $key ) {
  2099 	foreach ( _get_additional_user_keys( $user_obj ) as $key ) {
  1499 	// Update the cookies if the password changed.
  2118 	// Update the cookies if the password changed.
  1500 	$current_user = wp_get_current_user();
  2119 	$current_user = wp_get_current_user();
  1501 	if ( $current_user->ID == $ID ) {
  2120 	if ( $current_user->ID == $ID ) {
  1502 		if ( isset($plaintext_pass) ) {
  2121 		if ( isset($plaintext_pass) ) {
  1503 			wp_clear_auth_cookie();
  2122 			wp_clear_auth_cookie();
  1504 			wp_set_auth_cookie($ID);
  2123 
       
  2124 			// Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
       
  2125 			// If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
       
  2126 			$logged_in_cookie    = wp_parse_auth_cookie( '', 'logged_in' );
       
  2127 			/** This filter is documented in wp-includes/pluggable.php */
       
  2128 			$default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $ID, false );
       
  2129 			$remember            = ( ( $logged_in_cookie['expiration'] - time() ) > $default_cookie_life );
       
  2130 
       
  2131 			wp_set_auth_cookie( $ID, $remember );
  1505 		}
  2132 		}
  1506 	}
  2133 	}
  1507 
  2134 
  1508 	return $user_id;
  2135 	return $user_id;
  1509 }
  2136 }
  1510 
  2137 
  1511 /**
  2138 /**
  1512  * A simpler way of inserting an user into the database.
  2139  * A simpler way of inserting a user into the database.
  1513  *
  2140  *
  1514  * Creates a new user with just the username, password, and email. For more
  2141  * Creates a new user with just the username, password, and email. For more
  1515  * complex user creation use wp_insert_user() to specify more information.
  2142  * complex user creation use {@see wp_insert_user()} to specify more information.
  1516  *
  2143  *
  1517  * @since 2.0.0
  2144  * @since 2.0.0
  1518  * @see wp_insert_user() More complete way to create a new user
  2145  * @see wp_insert_user() More complete way to create a new user
  1519  *
  2146  *
  1520  * @param string $username The user's username.
  2147  * @param string $username The user's username.
  1521  * @param string $password The user's password.
  2148  * @param string $password The user's password.
  1522  * @param string $email The user's email (optional).
  2149  * @param string $email    Optional. The user's email. Default empty.
  1523  * @return int The new user's ID.
  2150  * @return int The new user's ID.
  1524  */
  2151  */
  1525 function wp_create_user($username, $password, $email = '') {
  2152 function wp_create_user($username, $password, $email = '') {
  1526 	$user_login = wp_slash( $username );
  2153 	$user_login = wp_slash( $username );
  1527 	$user_email = wp_slash( $email    );
  2154 	$user_email = wp_slash( $email    );
  1535  * Return a list of meta keys that wp_insert_user() is supposed to set.
  2162  * Return a list of meta keys that wp_insert_user() is supposed to set.
  1536  *
  2163  *
  1537  * @since 3.3.0
  2164  * @since 3.3.0
  1538  * @access private
  2165  * @access private
  1539  *
  2166  *
  1540  * @param object $user WP_User instance.
  2167  * @param WP_User $user WP_User instance.
  1541  * @return array
  2168  * @return array
  1542  */
  2169  */
  1543 function _get_additional_user_keys( $user ) {
  2170 function _get_additional_user_keys( $user ) {
  1544 	$keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' );
  2171 	$keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' );
  1545 	return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) );
  2172 	return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) );
  1569 	 * Filter the user contact methods.
  2196 	 * Filter the user contact methods.
  1570 	 *
  2197 	 *
  1571 	 * @since 2.9.0
  2198 	 * @since 2.9.0
  1572 	 *
  2199 	 *
  1573 	 * @param array   $methods Array of contact methods and their labels.
  2200 	 * @param array   $methods Array of contact methods and their labels.
  1574  	 * @param WP_User $user    Optional. WP_User object.
  2201  	 * @param WP_User $user    WP_User object.
  1575 	 */
  2202 	 */
  1576 	return apply_filters( 'user_contactmethods', $methods, $user );
  2203 	return apply_filters( 'user_contactmethods', $methods, $user );
  1577 }
  2204 }
  1578 
  2205 
  1579 /**
  2206 /**
  1582  * @since 2.9.0
  2209  * @since 2.9.0
  1583  * @access private
  2210  * @access private
  1584  */
  2211  */
  1585 function _wp_get_user_contactmethods( $user = null ) {
  2212 function _wp_get_user_contactmethods( $user = null ) {
  1586 	return wp_get_user_contact_methods( $user );
  2213 	return wp_get_user_contact_methods( $user );
       
  2214 }
       
  2215 
       
  2216 /**
       
  2217  * Gets the text suggesting how to create strong passwords.
       
  2218  *
       
  2219  * @since 4.1.0
       
  2220  *
       
  2221  * @return string The password hint text.
       
  2222  */
       
  2223 function wp_get_password_hint() {
       
  2224 	$hint = __( 'Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ &amp; ).' );
       
  2225 
       
  2226 	/**
       
  2227 	 * Filter the text describing the site's password complexity policy.
       
  2228 	 *
       
  2229 	 * @since 4.1.0
       
  2230 	 *
       
  2231 	 * @param string $hint The password hint text.
       
  2232 	 */
       
  2233 	return apply_filters( 'password_hint', $hint );
  1587 }
  2234 }
  1588 
  2235 
  1589 /**
  2236 /**
  1590  * Retrieves a user row based on password reset key and login
  2237  * Retrieves a user row based on password reset key and login
  1591  *
  2238  *
  1592  * A key is considered 'expired' if it exactly matches the value of the
  2239  * A key is considered 'expired' if it exactly matches the value of the
  1593  * user_activation_key field, rather than being matched after going through the
  2240  * user_activation_key field, rather than being matched after going through the
  1594  * hashing process. This field is now hashed; old values are no longer accepted
  2241  * hashing process. This field is now hashed; old values are no longer accepted
  1595  * but have a different WP_Error code so good user feedback can be provided.
  2242  * but have a different WP_Error code so good user feedback can be provided.
  1596  *
  2243  *
  1597  * @uses $wpdb WordPress Database object
  2244  * @global wpdb         $wpdb      WordPress database object for queries.
       
  2245  * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
  1598  *
  2246  *
  1599  * @param string $key       Hash to validate sending user's password.
  2247  * @param string $key       Hash to validate sending user's password.
  1600  * @param string $login     The user login.
  2248  * @param string $login     The user login.
  1601  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.
  2249  * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.
  1602  */
  2250  */
  1614 	$row = $wpdb->get_row( $wpdb->prepare( "SELECT ID, user_activation_key FROM $wpdb->users WHERE user_login = %s", $login ) );
  2262 	$row = $wpdb->get_row( $wpdb->prepare( "SELECT ID, user_activation_key FROM $wpdb->users WHERE user_login = %s", $login ) );
  1615 	if ( ! $row )
  2263 	if ( ! $row )
  1616 		return new WP_Error('invalid_key', __('Invalid key'));
  2264 		return new WP_Error('invalid_key', __('Invalid key'));
  1617 
  2265 
  1618 	if ( empty( $wp_hasher ) ) {
  2266 	if ( empty( $wp_hasher ) ) {
  1619 		require_once ABSPATH . 'wp-includes/class-phpass.php';
  2267 		require_once ABSPATH . WPINC . '/class-phpass.php';
  1620 		$wp_hasher = new PasswordHash( 8, true );
  2268 		$wp_hasher = new PasswordHash( 8, true );
  1621 	}
  2269 	}
  1622 
  2270 
  1623 	if ( $wp_hasher->CheckPassword( $key, $row->user_activation_key ) )
  2271 	if ( $wp_hasher->CheckPassword( $key, $row->user_activation_key ) )
  1624 		return get_userdata( $row->ID );
  2272 		return get_userdata( $row->ID );
  1648  *
  2296  *
  1649  * @param object $user The user
  2297  * @param object $user The user
  1650  * @param string $new_pass New password for the user in plaintext
  2298  * @param string $new_pass New password for the user in plaintext
  1651  */
  2299  */
  1652 function reset_password( $user, $new_pass ) {
  2300 function reset_password( $user, $new_pass ) {
       
  2301 	/**
       
  2302 	 * Fires before the user's password is reset.
       
  2303 	 *
       
  2304 	 * @since 1.5.0
       
  2305 	 *
       
  2306 	 * @param object $user     The user.
       
  2307 	 * @param string $new_pass New user password.
       
  2308 	 */
  1653 	do_action( 'password_reset', $user, $new_pass );
  2309 	do_action( 'password_reset', $user, $new_pass );
  1654 
  2310 
  1655 	wp_set_password( $new_pass, $user->ID );
  2311 	wp_set_password( $new_pass, $user->ID );
  1656 	update_user_option( $user->ID, 'default_password_nag', false, true );
  2312 	update_user_option( $user->ID, 'default_password_nag', false, true );
  1657 
  2313 
  1667  */
  2323  */
  1668 function register_new_user( $user_login, $user_email ) {
  2324 function register_new_user( $user_login, $user_email ) {
  1669 	$errors = new WP_Error();
  2325 	$errors = new WP_Error();
  1670 
  2326 
  1671 	$sanitized_user_login = sanitize_user( $user_login );
  2327 	$sanitized_user_login = sanitize_user( $user_login );
       
  2328 	/**
       
  2329 	 * Filter the email address of a user being registered.
       
  2330 	 *
       
  2331 	 * @since 2.1.0
       
  2332 	 *
       
  2333 	 * @param string $user_email The email address of the new user.
       
  2334 	 */
  1672 	$user_email = apply_filters( 'user_registration_email', $user_email );
  2335 	$user_email = apply_filters( 'user_registration_email', $user_email );
  1673 
  2336 
  1674 	// Check the username
  2337 	// Check the username
  1675 	if ( $sanitized_user_login == '' ) {
  2338 	if ( $sanitized_user_login == '' ) {
  1676 		$errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
  2339 		$errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
  1689 		$user_email = '';
  2352 		$user_email = '';
  1690 	} elseif ( email_exists( $user_email ) ) {
  2353 	} elseif ( email_exists( $user_email ) ) {
  1691 		$errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) );
  2354 		$errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) );
  1692 	}
  2355 	}
  1693 
  2356 
       
  2357 	/**
       
  2358 	 * Fires when submitting registration form data, before the user is created.
       
  2359 	 *
       
  2360 	 * @since 2.1.0
       
  2361 	 *
       
  2362 	 * @param string   $sanitized_user_login The submitted username after being sanitized.
       
  2363 	 * @param string   $user_email           The submitted email.
       
  2364 	 * @param WP_Error $errors               Contains any errors with submitted username and email,
       
  2365 	 *                                       e.g., an empty field, an invalid username or email,
       
  2366 	 *                                       or an existing username or email.
       
  2367 	 */
  1694 	do_action( 'register_post', $sanitized_user_login, $user_email, $errors );
  2368 	do_action( 'register_post', $sanitized_user_login, $user_email, $errors );
  1695 
  2369 
       
  2370 	/**
       
  2371 	 * Filter the errors encountered when a new user is being registered.
       
  2372 	 *
       
  2373 	 * The filtered WP_Error object may, for example, contain errors for an invalid
       
  2374 	 * or existing username or email address. A WP_Error object should always returned,
       
  2375 	 * but may or may not contain errors.
       
  2376 	 *
       
  2377 	 * If any errors are present in $errors, this will abort the user's registration.
       
  2378 	 *
       
  2379 	 * @since 2.1.0
       
  2380 	 *
       
  2381 	 * @param WP_Error $errors               A WP_Error object containing any errors encountered
       
  2382 	 *                                       during registration.
       
  2383 	 * @param string   $sanitized_user_login User's username after it has been sanitized.
       
  2384 	 * @param string   $user_email           User's email.
       
  2385 	 */
  1696 	$errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
  2386 	$errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
  1697 
  2387 
  1698 	if ( $errors->get_error_code() )
  2388 	if ( $errors->get_error_code() )
  1699 		return $errors;
  2389 		return $errors;
  1700 
  2390 
  1709 
  2399 
  1710 	wp_new_user_notification( $user_id, $user_pass );
  2400 	wp_new_user_notification( $user_id, $user_pass );
  1711 
  2401 
  1712 	return $user_id;
  2402 	return $user_id;
  1713 }
  2403 }
       
  2404 
       
  2405 /**
       
  2406  * Retrieve the current session token from the logged_in cookie.
       
  2407  *
       
  2408  * @since 4.0.0
       
  2409  *
       
  2410  * @return string Token.
       
  2411  */
       
  2412 function wp_get_session_token() {
       
  2413 	$cookie = wp_parse_auth_cookie( '', 'logged_in' );
       
  2414 	return ! empty( $cookie['token'] ) ? $cookie['token'] : '';
       
  2415 }
       
  2416 
       
  2417 /**
       
  2418  * Retrieve a list of sessions for the current user.
       
  2419  *
       
  2420  * @since 4.0.0
       
  2421  * @return array Array of sessions.
       
  2422  */
       
  2423 function wp_get_all_sessions() {
       
  2424 	$manager = WP_Session_Tokens::get_instance( get_current_user_id() );
       
  2425 	return $manager->get_all();
       
  2426 }
       
  2427 
       
  2428 /**
       
  2429  * Remove the current session token from the database.
       
  2430  *
       
  2431  * @since 4.0.0
       
  2432  */
       
  2433 function wp_destroy_current_session() {
       
  2434 	$token = wp_get_session_token();
       
  2435 	if ( $token ) {
       
  2436 		$manager = WP_Session_Tokens::get_instance( get_current_user_id() );
       
  2437 		$manager->destroy( $token );
       
  2438 	}
       
  2439 }
       
  2440 
       
  2441 /**
       
  2442  * Remove all but the current session token for the current user for the database.
       
  2443  *
       
  2444  * @since 4.0.0
       
  2445  */
       
  2446 function wp_destroy_other_sessions() {
       
  2447 	$token = wp_get_session_token();
       
  2448 	if ( $token ) {
       
  2449 		$manager = WP_Session_Tokens::get_instance( get_current_user_id() );
       
  2450 		$manager->destroy_others( $token );
       
  2451 	}
       
  2452 }
       
  2453 
       
  2454 /**
       
  2455  * Remove all session tokens for the current user from the database.
       
  2456  *
       
  2457  * @since 4.0.0
       
  2458  */
       
  2459 function wp_destroy_all_sessions() {
       
  2460 	$manager = WP_Session_Tokens::get_instance( get_current_user_id() );
       
  2461 	$manager->destroy_all();
       
  2462 }