web/wp-includes/user.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
    39 
    39 
    40 	// TODO do we deprecate the wp_authentication action?
    40 	// TODO do we deprecate the wp_authentication action?
    41 	do_action_ref_array('wp_authenticate', array(&$credentials['user_login'], &$credentials['user_password']));
    41 	do_action_ref_array('wp_authenticate', array(&$credentials['user_login'], &$credentials['user_password']));
    42 
    42 
    43 	if ( '' === $secure_cookie )
    43 	if ( '' === $secure_cookie )
    44 		$secure_cookie = is_ssl() ? true : false;
    44 		$secure_cookie = is_ssl();
       
    45 
       
    46 	$secure_cookie = apply_filters('secure_signon_cookie', $secure_cookie, $credentials);
    45 
    47 
    46 	global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
    48 	global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie
    47 	$auth_secure_cookie = $secure_cookie;
    49 	$auth_secure_cookie = $secure_cookie;
    48 
    50 
    49 	add_filter('authenticate', 'wp_authenticate_cookie', 30, 3);
    51 	add_filter('authenticate', 'wp_authenticate_cookie', 30, 3);
    57 
    59 
    58 		return $user;
    60 		return $user;
    59 	}
    61 	}
    60 
    62 
    61 	wp_set_auth_cookie($user->ID, $credentials['remember'], $secure_cookie);
    63 	wp_set_auth_cookie($user->ID, $credentials['remember'], $secure_cookie);
    62 	do_action('wp_login', $credentials['user_login']);
    64 	do_action('wp_login', $user->user_login, $user);
    63 	return $user;
    65 	return $user;
    64 }
    66 }
    65 
       
    66 
    67 
    67 /**
    68 /**
    68  * Authenticate the user using the username and password.
    69  * Authenticate the user using the username and password.
    69  */
    70  */
    70 add_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
    71 add_filter('authenticate', 'wp_authenticate_username_password', 20, 3);
    81 			$error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.'));
    82 			$error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.'));
    82 
    83 
    83 		return $error;
    84 		return $error;
    84 	}
    85 	}
    85 
    86 
    86 	$userdata = get_userdatabylogin($username);
    87 	$userdata = get_user_by('login', $username);
    87 
    88 
    88 	if ( !$userdata ) {
    89 	if ( !$userdata )
    89 		return new WP_Error('invalid_username', sprintf(__('<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), site_url('wp-login.php?action=lostpassword', 'login')));
    90 		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()));
       
    91 
       
    92 	if ( is_multisite() ) {
       
    93 		// Is user marked as spam?
       
    94 		if ( 1 == $userdata->spam)
       
    95 			return new WP_Error('invalid_username', __('<strong>ERROR</strong>: Your account has been marked as a spammer.'));
       
    96 
       
    97 		// Is a user's blog marked as spam?
       
    98 		if ( !is_super_admin( $userdata->ID ) && isset($userdata->primary_blog) ) {
       
    99 			$details = get_blog_details( $userdata->primary_blog );
       
   100 			if ( is_object( $details ) && $details->spam == 1 )
       
   101 				return new WP_Error('blog_suspended', __('Site Suspended.'));
       
   102 		}
    90 	}
   103 	}
    91 
   104 
    92 	$userdata = apply_filters('wp_authenticate_user', $userdata, $password);
   105 	$userdata = apply_filters('wp_authenticate_user', $userdata, $password);
    93 	if ( is_wp_error($userdata) ) {
   106 	if ( is_wp_error($userdata) )
    94 		return $userdata;
   107 		return $userdata;
    95 	}
   108 
    96 
   109 	if ( !wp_check_password($password, $userdata->user_pass, $userdata->ID) )
    97 	if ( !wp_check_password($password, $userdata->user_pass, $userdata->ID) ) {
   110 		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>?' ),
    98 		return new WP_Error('incorrect_password', sprintf(__('<strong>ERROR</strong>: Incorrect password. <a href="%s" title="Password Lost and Found">Lost your password</a>?'), site_url('wp-login.php?action=lostpassword', 'login')));
   111 		$username, wp_lostpassword_url() ) );
    99 	}
       
   100 
   112 
   101 	$user =  new WP_User($userdata->ID);
   113 	$user =  new WP_User($userdata->ID);
   102 	return $user;
   114 	return $user;
   103 }
   115 }
   104 
   116 
   128 
   140 
   129 	return $user;
   141 	return $user;
   130 }
   142 }
   131 
   143 
   132 /**
   144 /**
   133  * Retrieve user data based on field.
       
   134  *
       
   135  * Use get_profile() will make a database query to get the value of the table
       
   136  * column. The value might be cached using the query cache, but care should be
       
   137  * taken when using the function to not make a lot of queries for retrieving
       
   138  * user profile information.
       
   139  *
       
   140  * If the $user parameter is not used, then the user will be retrieved from a
       
   141  * cookie of the user. Therefore, if the cookie does not exist, then no value
       
   142  * might be returned. Sanity checking must be done to ensure that when using
       
   143  * get_profile() that empty/null/false values are handled and that something is
       
   144  * at least displayed.
       
   145  *
       
   146  * @since 1.5.0
       
   147  * @uses $wpdb WordPress database object to create queries.
       
   148  *
       
   149  * @param string $field User field to retrieve.
       
   150  * @param string $user Optional. User username.
       
   151  * @return string The value in the field.
       
   152  */
       
   153 function get_profile($field, $user = false) {
       
   154 	global $wpdb;
       
   155 	if ( !$user )
       
   156 		$user = esc_sql( $_COOKIE[USER_COOKIE] );
       
   157 	return $wpdb->get_var( $wpdb->prepare("SELECT $field FROM $wpdb->users WHERE user_login = %s", $user) );
       
   158 }
       
   159 
       
   160 /**
       
   161  * Number of posts user has written.
   145  * Number of posts user has written.
   162  *
   146  *
   163  * @since 0.71
   147  * @since 3.0.0
   164  * @uses $wpdb WordPress database object for queries.
   148  * @uses $wpdb WordPress database object for queries.
   165  *
   149  *
   166  * @param int $userid User ID.
   150  * @param int $userid User ID.
   167  * @return int Amount of posts user has written.
   151  * @return int Amount of posts user has written.
   168  */
   152  */
   169 function get_usernumposts($userid) {
   153 function count_user_posts($userid) {
   170 	global $wpdb;
   154 	global $wpdb;
   171 	$userid = (int) $userid;
   155 
   172 	$count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = %d AND post_type = 'post' AND ", $userid) . get_private_posts_cap_sql('post'));
   156 	$where = get_posts_by_author_sql('post', true, $userid);
       
   157 
       
   158 	$count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" );
       
   159 
   173 	return apply_filters('get_usernumposts', $count, $userid);
   160 	return apply_filters('get_usernumposts', $count, $userid);
       
   161 }
       
   162 
       
   163 /**
       
   164  * Number of posts written by a list of users.
       
   165  *
       
   166  * @since 3.0.0
       
   167  *
       
   168  * @param array $users Array of user IDs.
       
   169  * @param string|array $post_type Optional. Post type to check. Defaults to post.
       
   170  * @return array Amount of posts each user has written.
       
   171  */
       
   172 function count_many_users_posts( $users, $post_type = 'post' ) {
       
   173 	global $wpdb;
       
   174 
       
   175 	$count = array();
       
   176 	if ( empty( $users ) || ! is_array( $users ) )
       
   177 		return $count;
       
   178 
       
   179 	$userlist = implode( ',', array_map( 'absint', $users ) );
       
   180 	$where = get_posts_by_author_sql( $post_type );
       
   181 
       
   182 	$result = $wpdb->get_results( "SELECT post_author, COUNT(*) FROM $wpdb->posts $where AND post_author IN ($userlist) GROUP BY post_author", ARRAY_N );
       
   183 	foreach ( $result as $row ) {
       
   184 		$count[ $row[0] ] = $row[1];
       
   185 	}
       
   186 
       
   187 	foreach ( $users as $id ) {
       
   188 		if ( ! isset( $count[ $id ] ) )
       
   189 			$count[ $id ] = 0;
       
   190 	}
       
   191 
       
   192 	return $count;
   174 }
   193 }
   175 
   194 
   176 /**
   195 /**
   177  * Check that the user login name and password is correct.
   196  * Check that the user login name and password is correct.
   178  *
   197  *
   194 //
   213 //
   195 // User option functions
   214 // User option functions
   196 //
   215 //
   197 
   216 
   198 /**
   217 /**
   199  * Retrieve user option that can be either global, user, or blog.
   218  * Get the current user's ID
       
   219  *
       
   220  * @since MU
       
   221  *
       
   222  * @uses wp_get_current_user
       
   223  *
       
   224  * @return int The current user's ID
       
   225  */
       
   226 function get_current_user_id() {
       
   227 	$user = wp_get_current_user();
       
   228 	return ( isset( $user->ID ) ? (int) $user->ID : 0 );
       
   229 }
       
   230 
       
   231 /**
       
   232  * Retrieve user option that can be either per Site or per Network.
   200  *
   233  *
   201  * If the user ID is not given, then the current user will be used instead. If
   234  * If the user ID is not given, then the current user will be used instead. If
   202  * the user ID is given, then the user data will be retrieved. The filter for
   235  * the user ID is given, then the user data will be retrieved. The filter for
   203  * the result, will also pass the original option name and finally the user data
   236  * the result, will also pass the original option name and finally the user data
   204  * object as the third parameter.
   237  * object as the third parameter.
   205  *
   238  *
   206  * The option will first check for the non-global name, then the global name,
   239  * The option will first check for the per site name and then the per Network name.
   207  * and if it still doesn't find it, it will try the blog option. The option can
       
   208  * either be modified or set by a plugin.
       
   209  *
   240  *
   210  * @since 2.0.0
   241  * @since 2.0.0
   211  * @uses $wpdb WordPress database object for queries.
   242  * @uses $wpdb WordPress database object for queries.
   212  * @uses apply_filters() Calls 'get_user_option_$option' hook with result,
   243  * @uses apply_filters() Calls 'get_user_option_$option' hook with result,
   213  *		option parameter, and user data object.
   244  *		option parameter, and user data object.
   214  *
   245  *
   215  * @param string $option User option name.
   246  * @param string $option User option name.
   216  * @param int $user Optional. User ID.
   247  * @param int $user Optional. User ID.
   217  * @param bool $check_blog_options Whether to check for an option in the options table if a per-user option does not exist. Default is true.
   248  * @param bool $deprecated Use get_option() to check for an option in the options table.
   218  * @return mixed
   249  * @return mixed
   219  */
   250  */
   220 function get_user_option( $option, $user = 0, $check_blog_options = true ) {
   251 function get_user_option( $option, $user = 0, $deprecated = '' ) {
   221 	global $wpdb;
   252 	global $wpdb;
   222 
   253 
   223 	$option = preg_replace('|[^a-z0-9_]|i', '', $option);
   254 	if ( !empty( $deprecated ) )
   224 	if ( empty($user) )
   255 		_deprecated_argument( __FUNCTION__, '3.0' );
       
   256 
       
   257 	if ( empty( $user ) )
   225 		$user = wp_get_current_user();
   258 		$user = wp_get_current_user();
   226 	else
   259 	else
   227 		$user = get_userdata($user);
   260 		$user = new WP_User( $user );
   228 
   261 
   229 	if ( isset( $user->{$wpdb->prefix . $option} ) ) // Blog specific
   262 	if ( ! $user->exists() )
   230 		$result = $user->{$wpdb->prefix . $option};
   263 		return false;
   231 	elseif ( isset( $user->{$option} ) ) // User specific and cross-blog
   264 
   232 		$result = $user->{$option};
   265 	if ( $user->has_prop( $wpdb->prefix . $option ) ) // Blog specific
   233 	elseif ( $check_blog_options ) // Blog global
   266 		$result = $user->get( $wpdb->prefix . $option );
   234 		$result = get_option( $option );
   267 	elseif ( $user->has_prop( $option ) ) // User specific and cross-blog
       
   268 		$result = $user->get( $option );
   235 	else
   269 	else
   236 		$result = false;
   270 		$result = false;
   237 
   271 
   238 	return apply_filters("get_user_option_{$option}", $result, $option, $user);
   272 	return apply_filters("get_user_option_{$option}", $result, $option, $user);
   239 }
   273 }
   243  *
   277  *
   244  * User options are just like user metadata except that they have support for
   278  * User options are just like user metadata except that they have support for
   245  * global blog options. If the 'global' parameter is false, which it is by default
   279  * global blog options. If the 'global' parameter is false, which it is by default
   246  * it will prepend the WordPress table prefix to the option name.
   280  * it will prepend the WordPress table prefix to the option name.
   247  *
   281  *
       
   282  * Deletes the user option if $newvalue is empty.
       
   283  *
   248  * @since 2.0.0
   284  * @since 2.0.0
   249  * @uses $wpdb WordPress database object for queries
   285  * @uses $wpdb WordPress database object for queries
   250  *
   286  *
   251  * @param int $user_id User ID
   287  * @param int $user_id User ID
   252  * @param string $option_name User option name.
   288  * @param string $option_name User option name.
   253  * @param mixed $newvalue User option value.
   289  * @param mixed $newvalue User option value.
   254  * @param bool $global Optional. Whether option name is blog specific or not.
   290  * @param bool $global Optional. Whether option name is global or blog specific. Default false (blog specific).
   255  * @return unknown
   291  * @return unknown
   256  */
   292  */
   257 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {
   293 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {
   258 	global $wpdb;
   294 	global $wpdb;
       
   295 
   259 	if ( !$global )
   296 	if ( !$global )
   260 		$option_name = $wpdb->prefix . $option_name;
   297 		$option_name = $wpdb->prefix . $option_name;
   261 	return update_usermeta( $user_id, $option_name, $newvalue );
   298 
   262 }
   299 	// For backward compatibility. See differences between update_user_meta() and deprecated update_usermeta().
   263 
   300 	// http://core.trac.wordpress.org/ticket/13088
   264 /**
   301 	if ( is_null( $newvalue ) || is_scalar( $newvalue ) && empty( $newvalue ) )
   265  * Get users for the blog.
   302 		return delete_user_meta( $user_id, $option_name );
   266  *
   303 
   267  * For setups that use the multi-blog feature. Can be used outside of the
   304 	return update_user_meta( $user_id, $option_name, $newvalue );
   268  * multi-blog feature.
   305 }
   269  *
   306 
   270  * @since 2.2.0
   307 /**
       
   308  * Delete user option with global blog capability.
       
   309  *
       
   310  * User options are just like user metadata except that they have support for
       
   311  * global blog options. If the 'global' parameter is false, which it is by default
       
   312  * it will prepend the WordPress table prefix to the option name.
       
   313  *
       
   314  * @since 3.0.0
   271  * @uses $wpdb WordPress database object for queries
   315  * @uses $wpdb WordPress database object for queries
   272  * @uses $blog_id The Blog id of the blog for those that use more than one blog
   316  *
   273  *
   317  * @param int $user_id User ID
   274  * @param int $id Blog ID.
   318  * @param string $option_name User option name.
   275  * @return array List of users that are part of that Blog ID
   319  * @param bool $global Optional. Whether option name is global or blog specific. Default false (blog specific).
   276  */
   320  * @return unknown
   277 function get_users_of_blog( $id = '' ) {
   321  */
   278 	global $wpdb, $blog_id;
   322 function delete_user_option( $user_id, $option_name, $global = false ) {
   279 	if ( empty($id) )
   323 	global $wpdb;
   280 		$id = (int) $blog_id;
   324 
   281 	$users = $wpdb->get_results( "SELECT user_id, user_id AS ID, user_login, display_name, user_email, meta_value FROM $wpdb->users, $wpdb->usermeta WHERE {$wpdb->users}.ID = {$wpdb->usermeta}.user_id AND meta_key = '{$wpdb->prefix}capabilities' ORDER BY {$wpdb->usermeta}.user_id" );
   325 	if ( !$global )
   282 	return $users;
   326 		$option_name = $wpdb->prefix . $option_name;
   283 }
   327 	return delete_user_meta( $user_id, $option_name );
   284 
   328 }
   285 //
   329 
   286 // User meta functions
   330 /**
   287 //
   331  * WordPress User Query class.
   288 
   332  *
   289 /**
   333  * @since 3.1.0
   290  * Remove user meta data.
   334  */
   291  *
   335 class WP_User_Query {
   292  * @since 2.0.0
   336 
   293  * @uses $wpdb WordPress database object for queries.
   337 	/**
   294  *
   338 	 * List of found user ids
   295  * @param int $user_id User ID.
   339 	 *
       
   340 	 * @since 3.1.0
       
   341 	 * @access private
       
   342 	 * @var array
       
   343 	 */
       
   344 	var $results;
       
   345 
       
   346 	/**
       
   347 	 * Total number of found users for the current query
       
   348 	 *
       
   349 	 * @since 3.1.0
       
   350 	 * @access private
       
   351 	 * @var int
       
   352 	 */
       
   353 	var $total_users = 0;
       
   354 
       
   355 	// SQL clauses
       
   356 	var $query_fields;
       
   357 	var $query_from;
       
   358 	var $query_where;
       
   359 	var $query_orderby;
       
   360 	var $query_limit;
       
   361 
       
   362 	/**
       
   363 	 * PHP5 constructor
       
   364 	 *
       
   365 	 * @since 3.1.0
       
   366 	 *
       
   367 	 * @param string|array $args The query variables
       
   368 	 * @return WP_User_Query
       
   369 	 */
       
   370 	function __construct( $query = null ) {
       
   371 		if ( !empty( $query ) ) {
       
   372 			$this->query_vars = wp_parse_args( $query, array(
       
   373 				'blog_id' => $GLOBALS['blog_id'],
       
   374 				'role' => '',
       
   375 				'meta_key' => '',
       
   376 				'meta_value' => '',
       
   377 				'meta_compare' => '',
       
   378 				'include' => array(),
       
   379 				'exclude' => array(),
       
   380 				'search' => '',
       
   381 				'search_columns' => array(),
       
   382 				'orderby' => 'login',
       
   383 				'order' => 'ASC',
       
   384 				'offset' => '',
       
   385 				'number' => '',
       
   386 				'count_total' => true,
       
   387 				'fields' => 'all',
       
   388 				'who' => ''
       
   389 			) );
       
   390 
       
   391 			$this->prepare_query();
       
   392 			$this->query();
       
   393 		}
       
   394 	}
       
   395 
       
   396 	/**
       
   397 	 * Prepare the query variables
       
   398 	 *
       
   399 	 * @since 3.1.0
       
   400 	 * @access private
       
   401 	 */
       
   402 	function prepare_query() {
       
   403 		global $wpdb;
       
   404 
       
   405 		$qv = &$this->query_vars;
       
   406 
       
   407 		if ( is_array( $qv['fields'] ) ) {
       
   408 			$qv['fields'] = array_unique( $qv['fields'] );
       
   409 
       
   410 			$this->query_fields = array();
       
   411 			foreach ( $qv['fields'] as $field )
       
   412 				$this->query_fields[] = $wpdb->users . '.' . esc_sql( $field );
       
   413 			$this->query_fields = implode( ',', $this->query_fields );
       
   414 		} elseif ( 'all' == $qv['fields'] ) {
       
   415 			$this->query_fields = "$wpdb->users.*";
       
   416 		} else {
       
   417 			$this->query_fields = "$wpdb->users.ID";
       
   418 		}
       
   419 
       
   420 		if ( $this->query_vars['count_total'] )
       
   421 			$this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields;
       
   422 
       
   423 		$this->query_from = "FROM $wpdb->users";
       
   424 		$this->query_where = "WHERE 1=1";
       
   425 
       
   426 		// sorting
       
   427 		if ( in_array( $qv['orderby'], array('nicename', 'email', 'url', 'registered') ) ) {
       
   428 			$orderby = 'user_' . $qv['orderby'];
       
   429 		} elseif ( in_array( $qv['orderby'], array('user_nicename', 'user_email', 'user_url', 'user_registered') ) ) {
       
   430 			$orderby = $qv['orderby'];
       
   431 		} elseif ( 'name' == $qv['orderby'] || 'display_name' == $qv['orderby'] ) {
       
   432 			$orderby = 'display_name';
       
   433 		} elseif ( 'post_count' == $qv['orderby'] ) {
       
   434 			// todo: avoid the JOIN
       
   435 			$where = get_posts_by_author_sql('post');
       
   436 			$this->query_from .= " LEFT OUTER JOIN (
       
   437 				SELECT post_author, COUNT(*) as post_count
       
   438 				FROM $wpdb->posts
       
   439 				$where
       
   440 				GROUP BY post_author
       
   441 			) p ON ({$wpdb->users}.ID = p.post_author)
       
   442 			";
       
   443 			$orderby = 'post_count';
       
   444 		} elseif ( 'ID' == $qv['orderby'] || 'id' == $qv['orderby'] ) {
       
   445 			$orderby = 'ID';
       
   446 		} else {
       
   447 			$orderby = 'user_login';
       
   448 		}
       
   449 
       
   450 		$qv['order'] = strtoupper( $qv['order'] );
       
   451 		if ( 'ASC' == $qv['order'] )
       
   452 			$order = 'ASC';
       
   453 		else
       
   454 			$order = 'DESC';
       
   455 		$this->query_orderby = "ORDER BY $orderby $order";
       
   456 
       
   457 		// limit
       
   458 		if ( $qv['number'] ) {
       
   459 			if ( $qv['offset'] )
       
   460 				$this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']);
       
   461 			else
       
   462 				$this->query_limit = $wpdb->prepare("LIMIT %d", $qv['number']);
       
   463 		}
       
   464 
       
   465 		$search = trim( $qv['search'] );
       
   466 		if ( $search ) {
       
   467 			$leading_wild = ( ltrim($search, '*') != $search );
       
   468 			$trailing_wild = ( rtrim($search, '*') != $search );
       
   469 			if ( $leading_wild && $trailing_wild )
       
   470 				$wild = 'both';
       
   471 			elseif ( $leading_wild )
       
   472 				$wild = 'leading';
       
   473 			elseif ( $trailing_wild )
       
   474 				$wild = 'trailing';
       
   475 			else
       
   476 				$wild = false;
       
   477 			if ( $wild )
       
   478 				$search = trim($search, '*');
       
   479 
       
   480 			$search_columns = array();
       
   481 			if ( $qv['search_columns'] )
       
   482 				$search_columns = array_intersect( $qv['search_columns'], array( 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename' ) );
       
   483 			if ( ! $search_columns ) {
       
   484 				if ( false !== strpos( $search, '@') )
       
   485 					$search_columns = array('user_email');
       
   486 				elseif ( is_numeric($search) )
       
   487 					$search_columns = array('user_login', 'ID');
       
   488 				elseif ( preg_match('|^https?://|', $search) && ! wp_is_large_network( 'users' ) )
       
   489 					$search_columns = array('user_url');
       
   490 				else
       
   491 					$search_columns = array('user_login', 'user_nicename');
       
   492 			}
       
   493 
       
   494 			$this->query_where .= $this->get_search_sql( $search, $search_columns, $wild );
       
   495 		}
       
   496 
       
   497 		$blog_id = absint( $qv['blog_id'] );
       
   498 
       
   499 		if ( 'authors' == $qv['who'] && $blog_id ) {
       
   500 			$qv['meta_key'] = $wpdb->get_blog_prefix( $blog_id ) . 'user_level';
       
   501 			$qv['meta_value'] = 0;
       
   502 			$qv['meta_compare'] = '!=';
       
   503 			$qv['blog_id'] = $blog_id = 0; // Prevent extra meta query
       
   504 		}
       
   505 
       
   506 		$role = trim( $qv['role'] );
       
   507 
       
   508 		if ( $blog_id && ( $role || is_multisite() ) ) {
       
   509 			$cap_meta_query = array();
       
   510 			$cap_meta_query['key'] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
       
   511 
       
   512 			if ( $role ) {
       
   513 				$cap_meta_query['value'] = '"' . $role . '"';
       
   514 				$cap_meta_query['compare'] = 'like';
       
   515 			}
       
   516 
       
   517 			$qv['meta_query'][] = $cap_meta_query;
       
   518 		}
       
   519 
       
   520 		$meta_query = new WP_Meta_Query();
       
   521 		$meta_query->parse_query_vars( $qv );
       
   522 
       
   523 		if ( !empty( $meta_query->queries ) ) {
       
   524 			$clauses = $meta_query->get_sql( 'user', $wpdb->users, 'ID', $this );
       
   525 			$this->query_from .= $clauses['join'];
       
   526 			$this->query_where .= $clauses['where'];
       
   527 
       
   528 			if ( 'OR' == $meta_query->relation )
       
   529 				$this->query_fields = 'DISTINCT ' . $this->query_fields;
       
   530 		}
       
   531 
       
   532 		if ( !empty( $qv['include'] ) ) {
       
   533 			$ids = implode( ',', wp_parse_id_list( $qv['include'] ) );
       
   534 			$this->query_where .= " AND $wpdb->users.ID IN ($ids)";
       
   535 		} elseif ( !empty($qv['exclude']) ) {
       
   536 			$ids = implode( ',', wp_parse_id_list( $qv['exclude'] ) );
       
   537 			$this->query_where .= " AND $wpdb->users.ID NOT IN ($ids)";
       
   538 		}
       
   539 
       
   540 		do_action_ref_array( 'pre_user_query', array( &$this ) );
       
   541 	}
       
   542 
       
   543 	/**
       
   544 	 * Execute the query, with the current variables
       
   545 	 *
       
   546 	 * @since 3.1.0
       
   547 	 * @access private
       
   548 	 */
       
   549 	function query() {
       
   550 		global $wpdb;
       
   551 
       
   552 		if ( is_array( $this->query_vars['fields'] ) || 'all' == $this->query_vars['fields'] ) {
       
   553 			$this->results = $wpdb->get_results("SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit");
       
   554 		} else {
       
   555 			$this->results = $wpdb->get_col("SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit");
       
   556 		}
       
   557 
       
   558 		if ( $this->query_vars['count_total'] )
       
   559 			$this->total_users = $wpdb->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) );
       
   560 
       
   561 		if ( !$this->results )
       
   562 			return;
       
   563 
       
   564 		if ( 'all_with_meta' == $this->query_vars['fields'] ) {
       
   565 			cache_users( $this->results );
       
   566 
       
   567 			$r = array();
       
   568 			foreach ( $this->results as $userid )
       
   569 				$r[ $userid ] = new WP_User( $userid, '', $this->query_vars['blog_id'] );
       
   570 
       
   571 			$this->results = $r;
       
   572 		}
       
   573 	}
       
   574 
       
   575 	/*
       
   576 	 * Used internally to generate an SQL string for searching across multiple columns
       
   577 	 *
       
   578 	 * @access protected
       
   579 	 * @since 3.1.0
       
   580 	 *
       
   581 	 * @param string $string
       
   582 	 * @param array $cols
       
   583 	 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for
       
   584 	 *  single site. Single site allows leading and trailing wildcards, Network Admin only trailing.
       
   585 	 * @return string
       
   586 	 */
       
   587 	function get_search_sql( $string, $cols, $wild = false ) {
       
   588 		$string = esc_sql( $string );
       
   589 
       
   590 		$searches = array();
       
   591 		$leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
       
   592 		$trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
       
   593 		foreach ( $cols as $col ) {
       
   594 			if ( 'ID' == $col )
       
   595 				$searches[] = "$col = '$string'";
       
   596 			else
       
   597 				$searches[] = "$col LIKE '$leading_wild" . like_escape($string) . "$trailing_wild'";
       
   598 		}
       
   599 
       
   600 		return ' AND (' . implode(' OR ', $searches) . ')';
       
   601 	}
       
   602 
       
   603 	/**
       
   604 	 * Return the list of users
       
   605 	 *
       
   606 	 * @since 3.1.0
       
   607 	 * @access public
       
   608 	 *
       
   609 	 * @return array
       
   610 	 */
       
   611 	function get_results() {
       
   612 		return $this->results;
       
   613 	}
       
   614 
       
   615 	/**
       
   616 	 * Return the total number of users for the current query
       
   617 	 *
       
   618 	 * @since 3.1.0
       
   619 	 * @access public
       
   620 	 *
       
   621 	 * @return array
       
   622 	 */
       
   623 	function get_total() {
       
   624 		return $this->total_users;
       
   625 	}
       
   626 }
       
   627 
       
   628 /**
       
   629  * Retrieve list of users matching criteria.
       
   630  *
       
   631  * @since 3.1.0
       
   632  * @uses $wpdb
       
   633  * @uses WP_User_Query See for default arguments and information.
       
   634  *
       
   635  * @param array $args Optional.
       
   636  * @return array List of users.
       
   637  */
       
   638 function get_users( $args = array() ) {
       
   639 
       
   640 	$args = wp_parse_args( $args );
       
   641 	$args['count_total'] = false;
       
   642 
       
   643 	$user_search = new WP_User_Query($args);
       
   644 
       
   645 	return (array) $user_search->get_results();
       
   646 }
       
   647 
       
   648 /**
       
   649  * Get the blogs a user belongs to.
       
   650  *
       
   651  * @since 3.0.0
       
   652  *
       
   653  * @param int $user_id User ID
       
   654  * @param bool $all Whether to retrieve all blogs, or only blogs that are not marked as deleted, archived, or spam.
       
   655  * @return array A list of the user's blogs. An empty array if the user doesn't exist or belongs to no blogs.
       
   656  */
       
   657 function get_blogs_of_user( $user_id, $all = false ) {
       
   658 	global $wpdb;
       
   659 
       
   660 	$user_id = (int) $user_id;
       
   661 
       
   662 	// Logged out users can't have blogs
       
   663 	if ( empty( $user_id ) )
       
   664 		return array();
       
   665 
       
   666 	$keys = get_user_meta( $user_id );
       
   667 	if ( empty( $keys ) )
       
   668 		return array();
       
   669 
       
   670 	if ( ! is_multisite() ) {
       
   671 		$blog_id = get_current_blog_id();
       
   672 		$blogs = array( $blog_id => new stdClass );
       
   673 		$blogs[ $blog_id ]->userblog_id = $blog_id;
       
   674 		$blogs[ $blog_id ]->blogname = get_option('blogname');
       
   675 		$blogs[ $blog_id ]->domain = '';
       
   676 		$blogs[ $blog_id ]->path = '';
       
   677 		$blogs[ $blog_id ]->site_id = 1;
       
   678 		$blogs[ $blog_id ]->siteurl = get_option('siteurl');
       
   679 		return $blogs;
       
   680 	}
       
   681 
       
   682 	$blogs = array();
       
   683 
       
   684 	if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) {
       
   685 		$blog = get_blog_details( 1 );
       
   686 		if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {
       
   687 			$blogs[ 1 ] = (object) array(
       
   688 				'userblog_id' => 1,
       
   689 				'blogname'    => $blog->blogname,
       
   690 				'domain'      => $blog->domain,
       
   691 				'path'        => $blog->path,
       
   692 				'site_id'     => $blog->site_id,
       
   693 				'siteurl'     => $blog->siteurl,
       
   694 			);
       
   695 		}
       
   696 		unset( $keys[ $wpdb->base_prefix . 'capabilities' ] );
       
   697 	}
       
   698 
       
   699 	$keys = array_keys( $keys );
       
   700 
       
   701 	foreach ( $keys as $key ) {
       
   702 		if ( 'capabilities' !== substr( $key, -12 ) )
       
   703 			continue;
       
   704 		if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix ) )
       
   705 			continue;
       
   706 		$blog_id = str_replace( array( $wpdb->base_prefix, '_capabilities' ), '', $key );
       
   707 		if ( ! is_numeric( $blog_id ) )
       
   708 			continue;
       
   709 
       
   710 		$blog_id = (int) $blog_id;
       
   711 		$blog = get_blog_details( $blog_id );
       
   712 		if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {
       
   713 			$blogs[ $blog_id ] = (object) array(
       
   714 				'userblog_id' => $blog_id,
       
   715 				'blogname'    => $blog->blogname,
       
   716 				'domain'      => $blog->domain,
       
   717 				'path'        => $blog->path,
       
   718 				'site_id'     => $blog->site_id,
       
   719 				'siteurl'     => $blog->siteurl,
       
   720 			);
       
   721 		}
       
   722 	}
       
   723 
       
   724 	return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all );
       
   725 }
       
   726 
       
   727 /**
       
   728  * Find out whether a user is a member of a given blog.
       
   729  *
       
   730  * @since MU 1.1
       
   731  * @uses get_blogs_of_user()
       
   732  *
       
   733  * @param int $user_id Optional. The unique ID of the user. Defaults to the current user.
       
   734  * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site.
       
   735  * @return bool
       
   736  */
       
   737 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) {
       
   738 	$user_id = (int) $user_id;
       
   739 	$blog_id = (int) $blog_id;
       
   740 
       
   741 	if ( empty( $user_id ) )
       
   742 		$user_id = get_current_user_id();
       
   743 
       
   744 	if ( empty( $blog_id ) )
       
   745 		$blog_id = get_current_blog_id();
       
   746 
       
   747 	$blogs = get_blogs_of_user( $user_id );
       
   748 	return array_key_exists( $blog_id, $blogs );
       
   749 }
       
   750 
       
   751 /**
       
   752  * Add meta data field to a user.
       
   753  *
       
   754  * Post meta data is called "Custom Fields" on the Administration Screens.
       
   755  *
       
   756  * @since 3.0.0
       
   757  * @uses add_metadata()
       
   758  * @link http://codex.wordpress.org/Function_Reference/add_user_meta
       
   759  *
       
   760  * @param int $user_id Post ID.
       
   761  * @param string $meta_key Metadata name.
       
   762  * @param mixed $meta_value Metadata value.
       
   763  * @param bool $unique Optional, default is false. Whether the same key should not be added.
       
   764  * @return bool False for failure. True for success.
       
   765  */
       
   766 function add_user_meta($user_id, $meta_key, $meta_value, $unique = false) {
       
   767 	return add_metadata('user', $user_id, $meta_key, $meta_value, $unique);
       
   768 }
       
   769 
       
   770 /**
       
   771  * Remove metadata matching criteria from a user.
       
   772  *
       
   773  * You can match based on the key, or key and value. Removing based on key and
       
   774  * value, will keep from removing duplicate metadata with the same key. It also
       
   775  * allows removing all metadata matching key, if needed.
       
   776  *
       
   777  * @since 3.0.0
       
   778  * @uses delete_metadata()
       
   779  * @link http://codex.wordpress.org/Function_Reference/delete_user_meta
       
   780  *
       
   781  * @param int $user_id user ID
       
   782  * @param string $meta_key Metadata name.
       
   783  * @param mixed $meta_value Optional. Metadata value.
       
   784  * @return bool False for failure. True for success.
       
   785  */
       
   786 function delete_user_meta($user_id, $meta_key, $meta_value = '') {
       
   787 	return delete_metadata('user', $user_id, $meta_key, $meta_value);
       
   788 }
       
   789 
       
   790 /**
       
   791  * Retrieve user meta field for a user.
       
   792  *
       
   793  * @since 3.0.0
       
   794  * @uses get_metadata()
       
   795  * @link http://codex.wordpress.org/Function_Reference/get_user_meta
       
   796  *
       
   797  * @param int $user_id Post ID.
       
   798  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
       
   799  * @param bool $single Whether to return a single value.
       
   800  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
       
   801  *  is true.
       
   802  */
       
   803 function get_user_meta($user_id, $key = '', $single = false) {
       
   804 	return get_metadata('user', $user_id, $key, $single);
       
   805 }
       
   806 
       
   807 /**
       
   808  * Update user meta field based on user ID.
       
   809  *
       
   810  * Use the $prev_value parameter to differentiate between meta fields with the
       
   811  * same key and user ID.
       
   812  *
       
   813  * If the meta field for the user does not exist, it will be added.
       
   814  *
       
   815  * @since 3.0.0
       
   816  * @uses update_metadata
       
   817  * @link http://codex.wordpress.org/Function_Reference/update_user_meta
       
   818  *
       
   819  * @param int $user_id Post ID.
   296  * @param string $meta_key Metadata key.
   820  * @param string $meta_key Metadata key.
   297  * @param mixed $meta_value Metadata value.
   821  * @param mixed $meta_value Metadata value.
   298  * @return bool True deletion completed and false if user_id is not a number.
   822  * @param mixed $prev_value Optional. Previous value to check before removing.
   299  */
   823  * @return bool False on failure, true if success.
   300 function delete_usermeta( $user_id, $meta_key, $meta_value = '' ) {
   824  */
   301 	global $wpdb;
   825 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') {
   302 	if ( !is_numeric( $user_id ) )
   826 	return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value);
   303 		return false;
   827 }
   304 	$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
   828 
   305 
   829 /**
   306 	if ( is_array($meta_value) || is_object($meta_value) )
   830  * Count number of users who have each of the user roles.
   307 		$meta_value = serialize($meta_value);
   831  *
   308 	$meta_value = trim( $meta_value );
   832  * Assumes there are neither duplicated nor orphaned capabilities meta_values.
   309 
   833  * Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query()
   310 	$cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
   834  * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users.
   311 
   835  * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257.
   312 	if ( $cur && $cur->umeta_id )
   836  *
   313 		do_action( 'delete_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value );
   837  * @since 3.0.0
   314 
   838  * @param string $strategy 'time' or 'memory'
   315 	if ( ! empty($meta_value) )
   839  * @return array Includes a grand total and an array of counts indexed by role strings.
   316 		$wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s AND meta_value = %s", $user_id, $meta_key, $meta_value) );
   840  */
   317 	else
   841 function count_users($strategy = 'time') {
   318 		$wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
   842 	global $wpdb, $wp_roles;
   319 
   843 
   320 	wp_cache_delete($user_id, 'users');
   844 	// Initialize
   321 
   845 	$id = get_current_blog_id();
   322 	if ( $cur && $cur->umeta_id )
   846 	$blog_prefix = $wpdb->get_blog_prefix($id);
   323 		do_action( 'deleted_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value );
   847 	$result = array();
   324 
   848 
   325 	return true;
   849 	if ( 'time' == $strategy ) {
   326 }
   850 		global $wp_roles;
   327 
   851 
   328 /**
   852 		if ( ! isset( $wp_roles ) )
   329  * Retrieve user metadata.
   853 			$wp_roles = new WP_Roles();
   330  *
   854 
   331  * If $user_id is not a number, then the function will fail over with a 'false'
   855 		$avail_roles = $wp_roles->get_names();
   332  * boolean return value. Other returned values depend on whether there is only
   856 
   333  * one item to be returned, which be that single item type. If there is more
   857 		// Build a CPU-intensive query that will return concise information.
   334  * than one metadata value, then it will be list of metadata values.
   858 		$select_count = array();
   335  *
   859 		foreach ( $avail_roles as $this_role => $name ) {
   336  * @since 2.0.0
   860 			$select_count[] = "COUNT(NULLIF(`meta_value` LIKE '%\"" . like_escape( $this_role ) . "\"%', false))";
   337  * @uses $wpdb WordPress database object for queries.
   861 		}
   338  *
   862 		$select_count = implode(', ', $select_count);
   339  * @param int $user_id User ID
   863 
   340  * @param string $meta_key Optional. Metadata key.
   864 		// Add the meta_value index to the selection list, then run the query.
   341  * @return mixed
   865 		$row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N );
   342  */
   866 
   343 function get_usermeta( $user_id, $meta_key = '') {
   867 		// Run the previous loop again to associate results with role names.
   344 	global $wpdb;
   868 		$col = 0;
   345 	$user_id = (int) $user_id;
   869 		$role_counts = array();
   346 
   870 		foreach ( $avail_roles as $this_role => $name ) {
   347 	if ( !$user_id )
   871 			$count = (int) $row[$col++];
   348 		return false;
   872 			if ($count > 0) {
   349 
   873 				$role_counts[$this_role] = $count;
   350 	if ( !empty($meta_key) ) {
   874 			}
   351 		$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
   875 		}
   352 		$user = wp_cache_get($user_id, 'users');
   876 
   353 		// Check the cached user object
   877 		// Get the meta_value index from the end of the result set.
   354 		if ( false !== $user && isset($user->$meta_key) )
   878 		$total_users = (int) $row[$col];
   355 			$metas = array($user->$meta_key);
   879 
   356 		else
   880 		$result['total_users'] = $total_users;
   357 			$metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
   881 		$result['avail_roles'] =& $role_counts;
   358 	} else {
   882 	} else {
   359 		$metas = $wpdb->get_col( $wpdb->prepare("SELECT meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user_id) );
   883 		$avail_roles = array();
   360 	}
   884 
   361 
   885 		$users_of_blog = $wpdb->get_col( "SELECT meta_value FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'" );
   362 	if ( empty($metas) ) {
   886 
   363 		if ( empty($meta_key) )
   887 		foreach ( $users_of_blog as $caps_meta ) {
   364 			return array();
   888 			$b_roles = maybe_unserialize($caps_meta);
   365 		else
   889 			if ( ! is_array( $b_roles ) )
   366 			return '';
   890 				continue;
   367 	}
   891 			foreach ( $b_roles as $b_role => $val ) {
   368 
   892 				if ( isset($avail_roles[$b_role]) ) {
   369 	$metas = array_map('maybe_unserialize', $metas);
   893 					$avail_roles[$b_role]++;
   370 
   894 				} else {
   371 	if ( count($metas) == 1 )
   895 					$avail_roles[$b_role] = 1;
   372 		return $metas[0];
   896 				}
   373 	else
   897 			}
   374 		return $metas;
   898 		}
   375 }
   899 
   376 
   900 		$result['total_users'] = count( $users_of_blog );
   377 /**
   901 		$result['avail_roles'] =& $avail_roles;
   378  * Update metadata of user.
   902 	}
   379  *
   903 
   380  * There is no need to serialize values, they will be serialized if it is
   904 	return $result;
   381  * needed. The metadata key can only be a string with underscores. All else will
       
   382  * be removed.
       
   383  *
       
   384  * Will remove the metadata, if the meta value is empty.
       
   385  *
       
   386  * @since 2.0.0
       
   387  * @uses $wpdb WordPress database object for queries
       
   388  *
       
   389  * @param int $user_id User ID
       
   390  * @param string $meta_key Metadata key.
       
   391  * @param mixed $meta_value Metadata value.
       
   392  * @return bool True on successful update, false on failure.
       
   393  */
       
   394 function update_usermeta( $user_id, $meta_key, $meta_value ) {
       
   395 	global $wpdb;
       
   396 	if ( !is_numeric( $user_id ) )
       
   397 		return false;
       
   398 	$meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key);
       
   399 
       
   400 	/** @todo Might need fix because usermeta data is assumed to be already escaped */
       
   401 	if ( is_string($meta_value) )
       
   402 		$meta_value = stripslashes($meta_value);
       
   403 	$meta_value = maybe_serialize($meta_value);
       
   404 
       
   405 	if (empty($meta_value)) {
       
   406 		return delete_usermeta($user_id, $meta_key);
       
   407 	}
       
   408 
       
   409 	$cur = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $user_id, $meta_key) );
       
   410 
       
   411 	if ( $cur )
       
   412 		do_action( 'update_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value );
       
   413 
       
   414 	if ( !$cur )
       
   415 		$wpdb->insert($wpdb->usermeta, compact('user_id', 'meta_key', 'meta_value') );
       
   416 	else if ( $cur->meta_value != $meta_value )
       
   417 		$wpdb->update($wpdb->usermeta, compact('meta_value'), compact('user_id', 'meta_key') );
       
   418 	else
       
   419 		return false;
       
   420 
       
   421 	wp_cache_delete($user_id, 'users');
       
   422 
       
   423 	if ( !$cur )
       
   424 		do_action( 'added_usermeta', $wpdb->insert_id, $user_id, $meta_key, $meta_value );
       
   425 	else
       
   426 		do_action( 'updated_usermeta', $cur->umeta_id, $user_id, $meta_key, $meta_value );
       
   427 
       
   428 	return true;
       
   429 }
   905 }
   430 
   906 
   431 //
   907 //
   432 // Private helper functions
   908 // Private helper functions
   433 //
   909 //
   434 
   910 
   435 /**
   911 /**
   436  * Setup global user vars.
   912  * Set up global user vars.
   437  *
   913  *
   438  * Used by set_current_user() for back compat. Might be deprecated in the
   914  * Used by wp_set_current_user() for back compat. Might be deprecated in the future.
   439  * future.
       
   440  *
   915  *
   441  * @since 2.0.4
   916  * @since 2.0.4
   442  * @global string $userdata User description.
   917  * @global string $userdata User description.
   443  * @global string $user_login The user username for logging in
   918  * @global string $user_login The user username for logging in
   444  * @global int $user_level The level of the user
   919  * @global int $user_level The level of the user
   446  * @global string $user_email The email address of the user
   921  * @global string $user_email The email address of the user
   447  * @global string $user_url The url in the user's profile
   922  * @global string $user_url The url in the user's profile
   448  * @global string $user_pass_md5 MD5 of the user's password
   923  * @global string $user_pass_md5 MD5 of the user's password
   449  * @global string $user_identity The display name of the user
   924  * @global string $user_identity The display name of the user
   450  *
   925  *
   451  * @param int $for_user_id Optional. User ID to setup global data.
   926  * @param int $for_user_id Optional. User ID to set up global data.
   452  */
   927  */
   453 function setup_userdata($for_user_id = '') {
   928 function setup_userdata($for_user_id = '') {
   454 	global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_pass_md5, $user_identity;
   929 	global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_pass_md5, $user_identity;
   455 
   930 
   456 	if ( '' == $for_user_id )
   931 	if ( '' == $for_user_id )
   457 		$user = wp_get_current_user();
   932 		$user = wp_get_current_user();
   458 	else
   933 	else
   459 		$user = new WP_User($for_user_id);
   934 		$user = new WP_User($for_user_id);
   460 
   935 
   461 	if ( 0 == $user->ID )
   936 	$userdata   = null;
       
   937 	$user_ID    = (int) $user->ID;
       
   938 	$user_level = (int) isset($user->user_level) ? $user->user_level : 0;
       
   939 
       
   940 	if ( ! $user->exists() ) {
       
   941 		$user_login = $user_email = $user_url = $user_pass_md5 = $user_identity = '';
   462 		return;
   942 		return;
   463 
   943 	}
   464 	$userdata = $user->data;
   944 
   465 	$user_login	= $user->user_login;
   945 	$userdata   = $user;
   466 	$user_level	= (int) isset($user->user_level) ? $user->user_level : 0;
   946 	$user_login = $user->user_login;
   467 	$user_ID = (int) $user->ID;
   947 	$user_email = $user->user_email;
   468 	$user_email	= $user->user_email;
   948 	$user_url   = $user->user_url;
   469 	$user_url	= $user->user_url;
   949 	$user_pass_md5 = md5( $user->user_pass );
   470 	$user_pass_md5	= md5($user->user_pass);
   950 	$user_identity = $user->display_name;
   471 	$user_identity	= $user->display_name;
       
   472 }
   951 }
   473 
   952 
   474 /**
   953 /**
   475  * Create dropdown HTML content of users.
   954  * Create dropdown HTML content of users.
   476  *
   955  *
   480  * used, either 'include' or 'exclude', but not both.
   959  * used, either 'include' or 'exclude', but not both.
   481  *
   960  *
   482  * The available arguments are as follows:
   961  * The available arguments are as follows:
   483  * <ol>
   962  * <ol>
   484  * <li>show_option_all - Text to show all and whether HTML option exists.</li>
   963  * <li>show_option_all - Text to show all and whether HTML option exists.</li>
   485  * <li>show_option_none - Text for show none and whether HTML option exists.
   964  * <li>show_option_none - Text for show none and whether HTML option exists.</li>
   486  *     </li>
   965  * <li>hide_if_only_one_author - Don't create the dropdown if there is only one user.</li>
   487  * <li>orderby - SQL order by clause for what order the users appear. Default is
   966  * <li>orderby - SQL order by clause for what order the users appear. Default is 'display_name'.</li>
   488  * 'display_name'.</li>
       
   489  * <li>order - Default is 'ASC'. Can also be 'DESC'.</li>
   967  * <li>order - Default is 'ASC'. Can also be 'DESC'.</li>
   490  * <li>include - User IDs to include.</li>
   968  * <li>include - User IDs to include.</li>
   491  * <li>exclude - User IDs to exclude.</li>
   969  * <li>exclude - User IDs to exclude.</li>
   492  * <li>multi - Default is 'false'. Whether to skip the ID attribute on the 'select' element.</li>
   970  * <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>
   493  * <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 parentesis</li>
   971  * <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>
   494  * <li>echo - Default is '1'. Whether to display or retrieve content.</li>
   972  * <li>echo - Default is '1'. Whether to display or retrieve content.</li>
   495  * <li>selected - Which User ID is selected.</li>
   973  * <li>selected - Which User ID is selected.</li>
       
   974  * <li>include_selected - Always include the selected user ID in the dropdown. Default is false.</li>
   496  * <li>name - Default is 'user'. Name attribute of select element.</li>
   975  * <li>name - Default is 'user'. Name attribute of select element.</li>
       
   976  * <li>id - Default is the value of the 'name' parameter. ID attribute of select element.</li>
   497  * <li>class - Class attribute of select element.</li>
   977  * <li>class - Class attribute of select element.</li>
       
   978  * <li>blog_id - ID of blog (Multisite only). Defaults to ID of current blog.</li>
       
   979  * <li>who - Which users to query. Currently only 'authors' is supported. Default is all users.</li>
   498  * </ol>
   980  * </ol>
   499  *
   981  *
   500  * @since 2.3.0
   982  * @since 2.3.0
   501  * @uses $wpdb WordPress database object for queries
   983  * @uses $wpdb WordPress database object for queries
   502  *
   984  *
   503  * @param string|array $args Optional. Override defaults.
   985  * @param string|array $args Optional. Override defaults.
   504  * @return string|null Null on display. String of HTML content on retrieve.
   986  * @return string|null Null on display. String of HTML content on retrieve.
   505  */
   987  */
   506 function wp_dropdown_users( $args = '' ) {
   988 function wp_dropdown_users( $args = '' ) {
   507 	global $wpdb;
       
   508 	$defaults = array(
   989 	$defaults = array(
   509 		'show_option_all' => '', 'show_option_none' => '',
   990 		'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',
   510 		'orderby' => 'display_name', 'order' => 'ASC',
   991 		'orderby' => 'display_name', 'order' => 'ASC',
   511 		'include' => '', 'exclude' => '', 'multi' => 0,
   992 		'include' => '', 'exclude' => '', 'multi' => 0,
   512 		'show' => 'display_name', 'echo' => 1,
   993 		'show' => 'display_name', 'echo' => 1,
   513 		'selected' => 0, 'name' => 'user', 'class' => ''
   994 		'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',
       
   995 		'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false
   514 	);
   996 	);
   515 
   997 
   516 	$defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;
   998 	$defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;
   517 
   999 
   518 	$r = wp_parse_args( $args, $defaults );
  1000 	$r = wp_parse_args( $args, $defaults );
   519 	extract( $r, EXTR_SKIP );
  1001 	extract( $r, EXTR_SKIP );
   520 
  1002 
   521 	$query = "SELECT * FROM $wpdb->users";
  1003 	$query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who' ) );
   522 
  1004 	$query_args['fields'] = array( 'ID', $show );
   523 	$query_where = array();
  1005 	$users = get_users( $query_args );
   524 
       
   525 	if ( is_array($include) )
       
   526 		$include = join(',', $include);
       
   527 	$include = preg_replace('/[^0-9,]/', '', $include); // (int)
       
   528 	if ( $include )
       
   529 		$query_where[] = "ID IN ($include)";
       
   530 
       
   531 	if ( is_array($exclude) )
       
   532 		$exclude = join(',', $exclude);
       
   533 	$exclude = preg_replace('/[^0-9,]/', '', $exclude); // (int)
       
   534 	if ( $exclude )
       
   535 		$query_where[] = "ID NOT IN ($exclude)";
       
   536 
       
   537 	if ( $query_where )
       
   538 		$query .= " WHERE " . join(' AND', $query_where);
       
   539 
       
   540 	$query .= " ORDER BY $orderby $order";
       
   541 
       
   542 	$users = $wpdb->get_results( $query );
       
   543 
  1006 
   544 	$output = '';
  1007 	$output = '';
   545 	if ( !empty($users) ) {
  1008 	if ( !empty($users) && ( empty($hide_if_only_one_author) || count($users) > 1 ) ) {
   546 		$id = $multi ? "" : "id='$name'";
  1009 		$name = esc_attr( $name );
   547 
  1010 		if ( $multi && ! $id )
   548 		$output = "<select name='$name' $id class='$class'>\n";
  1011 			$id = '';
       
  1012 		else
       
  1013 			$id = $id ? " id='" . esc_attr( $id ) . "'" : " id='$name'";
       
  1014 
       
  1015 		$output = "<select name='{$name}'{$id} class='$class'>\n";
   549 
  1016 
   550 		if ( $show_option_all )
  1017 		if ( $show_option_all )
   551 			$output .= "\t<option value='0'>$show_option_all</option>\n";
  1018 			$output .= "\t<option value='0'>$show_option_all</option>\n";
   552 
  1019 
   553 		if ( $show_option_none )
  1020 		if ( $show_option_none ) {
   554 			$output .= "\t<option value='-1'>$show_option_none</option>\n";
  1021 			$_selected = selected( -1, $selected, false );
   555 
  1022 			$output .= "\t<option value='-1'$_selected>$show_option_none</option>\n";
       
  1023 		}
       
  1024 
       
  1025 		$found_selected = false;
   556 		foreach ( (array) $users as $user ) {
  1026 		foreach ( (array) $users as $user ) {
   557 			$user->ID = (int) $user->ID;
  1027 			$user->ID = (int) $user->ID;
   558 			$_selected = $user->ID == $selected ? " selected='selected'" : '';
  1028 			$_selected = selected( $user->ID, $selected, false );
       
  1029 			if ( $_selected )
       
  1030 				$found_selected = true;
   559 			$display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')';
  1031 			$display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')';
   560 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n";
  1032 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n";
   561 		}
  1033 		}
   562 
  1034 
       
  1035 		if ( $include_selected && ! $found_selected && ( $selected > 0 ) ) {
       
  1036 			$user = get_userdata( $selected );
       
  1037 			$_selected = selected( $user->ID, $selected, false );
       
  1038 			$display = !empty($user->$show) ? $user->$show : '('. $user->user_login . ')';
       
  1039 			$output .= "\t<option value='$user->ID'$_selected>" . esc_html($display) . "</option>\n";
       
  1040 		}
       
  1041 
   563 		$output .= "</select>";
  1042 		$output .= "</select>";
   564 	}
  1043 	}
   565 
  1044 
   566 	$output = apply_filters('wp_dropdown_users', $output);
  1045 	$output = apply_filters('wp_dropdown_users', $output);
   567 
  1046 
   568 	if ( $echo )
  1047 	if ( $echo )
   569 		echo $output;
  1048 		echo $output;
   570 
  1049 
   571 	return $output;
  1050 	return $output;
   572 }
       
   573 
       
   574 /**
       
   575  * Add user meta data as properties to given user object.
       
   576  *
       
   577  * The finished user data is cached, but the cache is not used to fill in the
       
   578  * user data for the given object. Once the function has been used, the cache
       
   579  * should be used to retrieve user data. The purpose seems then to be to ensure
       
   580  * that the data in the object is always fresh.
       
   581  *
       
   582  * @access private
       
   583  * @since 2.5.0
       
   584  * @uses $wpdb WordPress database object for queries
       
   585  *
       
   586  * @param object $user The user data object.
       
   587  */
       
   588 function _fill_user( &$user ) {
       
   589 	global $wpdb;
       
   590 
       
   591 	$show = $wpdb->hide_errors();
       
   592 	$metavalues = $wpdb->get_results($wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->usermeta WHERE user_id = %d", $user->ID));
       
   593 	$wpdb->show_errors($show);
       
   594 
       
   595 	if ( $metavalues ) {
       
   596 		foreach ( (array) $metavalues as $meta ) {
       
   597 			$value = maybe_unserialize($meta->meta_value);
       
   598 			$user->{$meta->meta_key} = $value;
       
   599 		}
       
   600 	}
       
   601 
       
   602 	$level = $wpdb->prefix . 'user_level';
       
   603 	if ( isset( $user->{$level} ) )
       
   604 		$user->user_level = $user->{$level};
       
   605 
       
   606 	// For backwards compat.
       
   607 	if ( isset($user->first_name) )
       
   608 		$user->user_firstname = $user->first_name;
       
   609 	if ( isset($user->last_name) )
       
   610 		$user->user_lastname = $user->last_name;
       
   611 	if ( isset($user->description) )
       
   612 		$user->user_description = $user->description;
       
   613 
       
   614 	wp_cache_add($user->ID, $user, 'users');
       
   615 	wp_cache_add($user->user_login, $user->ID, 'userlogins');
       
   616 	wp_cache_add($user->user_email, $user->ID, 'useremail');
       
   617 	wp_cache_add($user->user_nicename, $user->ID, 'userslugs');
       
   618 }
       
   619 
       
   620 /**
       
   621  * Sanitize every user field.
       
   622  *
       
   623  * If the context is 'raw', then the user object or array will get minimal santization of the int fields.
       
   624  *
       
   625  * @since 2.3.0
       
   626  * @uses sanitize_user_field() Used to sanitize the fields.
       
   627  *
       
   628  * @param object|array $user The User Object or Array
       
   629  * @param string $context Optional, default is 'display'. How to sanitize user fields.
       
   630  * @return object|array The now sanitized User Object or Array (will be the same type as $user)
       
   631  */
       
   632 function sanitize_user_object($user, $context = 'display') {
       
   633 	if ( is_object($user) ) {
       
   634 		if ( !isset($user->ID) )
       
   635 			$user->ID = 0;
       
   636 		if ( isset($user->data) )
       
   637 			$vars = get_object_vars( $user->data );
       
   638 		else
       
   639 			$vars = get_object_vars($user);
       
   640 		foreach ( array_keys($vars) as $field ) {
       
   641 			if ( is_string($user->$field) || is_numeric($user->$field) ) 
       
   642 				$user->$field = sanitize_user_field($field, $user->$field, $user->ID, $context);
       
   643 		}
       
   644 		$user->filter = $context;
       
   645 	} else {
       
   646 		if ( !isset($user['ID']) )
       
   647 			$user['ID'] = 0;
       
   648 		foreach ( array_keys($user) as $field )
       
   649 			$user[$field] = sanitize_user_field($field, $user[$field], $user['ID'], $context);
       
   650 		$user['filter'] = $context;
       
   651 	}
       
   652 
       
   653 	return $user;
       
   654 }
  1051 }
   655 
  1052 
   656 /**
  1053 /**
   657  * Sanitize user field based on context.
  1054  * Sanitize user field based on context.
   658  *
  1055  *
   659  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
  1056  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
   660  * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
  1057  * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
   661  * when calling filters.
  1058  * when calling filters.
   662  *
  1059  *
   663  * @since 2.3.0
  1060  * @since 2.3.0
   664  * @uses apply_filters() Calls 'edit_$field' and '${field_no_prefix}_edit_pre' passing $value and
  1061  * @uses apply_filters() Calls 'edit_$field' passing $value and $user_id if $context == 'edit'.
   665  *  $user_id if $context == 'edit' and field name prefix == 'user_'.
  1062  *  $field is prefixed with 'user_' if it isn't already.
   666  *
  1063  * @uses apply_filters() Calls 'pre_$field' passing $value if $context == 'db'. $field is prefixed with
   667  * @uses apply_filters() Calls 'edit_user_$field' passing $value and $user_id if $context == 'db'.
  1064  *  'user_' if it isn't already.
   668  * @uses apply_filters() Calls 'pre_$field' passing $value if $context == 'db' and field name prefix == 'user_'.
       
   669  * @uses apply_filters() Calls '${field}_pre' passing $value if $context == 'db' and field name prefix != 'user_'.
       
   670  *
       
   671  * @uses apply_filters() Calls '$field' passing $value, $user_id and $context if $context == anything
  1065  * @uses apply_filters() Calls '$field' passing $value, $user_id and $context if $context == anything
   672  *  other than 'raw', 'edit' and 'db' and field name prefix == 'user_'.
  1066  *  other than 'raw', 'edit' and 'db'. $field is prefixed with 'user_' if it isn't already.
   673  * @uses apply_filters() Calls 'user_$field' passing $value if $context == anything other than 'raw',
       
   674  *  'edit' and 'db' and field name prefix != 'user_'.
       
   675  *
  1067  *
   676  * @param string $field The user Object field name.
  1068  * @param string $field The user Object field name.
   677  * @param mixed $value The user Object value.
  1069  * @param mixed $value The user Object value.
   678  * @param int $user_id user ID.
  1070  * @param int $user_id user ID.
   679  * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
  1071  * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
   689 		return $value;
  1081 		return $value;
   690 
  1082 
   691 	if ( !is_string($value) && !is_numeric($value) )
  1083 	if ( !is_string($value) && !is_numeric($value) )
   692 		return $value;
  1084 		return $value;
   693 
  1085 
   694 	$prefixed = false;
  1086 	$prefixed = false !== strpos( $field, 'user_' );
   695 	if ( false !== strpos($field, 'user_') ) {
       
   696 		$prefixed = true;
       
   697 		$field_no_prefix = str_replace('user_', '', $field);
       
   698 	}
       
   699 
  1087 
   700 	if ( 'edit' == $context ) {
  1088 	if ( 'edit' == $context ) {
   701 		if ( $prefixed ) {
  1089 		if ( $prefixed ) {
   702 			$value = apply_filters("edit_$field", $value, $user_id);
  1090 			$value = apply_filters("edit_{$field}", $value, $user_id);
   703 		} else {
  1091 		} else {
   704 			$value = apply_filters("edit_user_$field", $value, $user_id);
  1092 			$value = apply_filters("edit_user_{$field}", $value, $user_id);
   705 		}
  1093 		}
   706 
  1094 
   707 		if ( 'description' == $field )
  1095 		if ( 'description' == $field )
   708 			$value = esc_html($value);
  1096 			$value = esc_html( $value ); // textarea_escaped?
   709 		else
  1097 		else
   710 			$value = esc_attr($value);
  1098 			$value = esc_attr($value);
   711 	} else if ( 'db' == $context ) {
  1099 	} else if ( 'db' == $context ) {
   712 		if ( $prefixed ) {
  1100 		if ( $prefixed ) {
   713 			$value = apply_filters("pre_$field", $value);
  1101 			$value = apply_filters("pre_{$field}", $value);
   714 		} else {
  1102 		} else {
   715 			$value = apply_filters("pre_user_$field", $value);
  1103 			$value = apply_filters("pre_user_{$field}", $value);
   716 		}
  1104 		}
   717 	} else {
  1105 	} else {
   718 		// Use display filters by default.
  1106 		// Use display filters by default.
   719 		if ( $prefixed )
  1107 		if ( $prefixed )
   720 			$value = apply_filters($field, $value, $user_id, $context);
  1108 			$value = apply_filters($field, $value, $user_id, $context);
   721 		else
  1109 		else
   722 			$value = apply_filters("user_$field", $value, $user_id, $context);
  1110 			$value = apply_filters("user_{$field}", $value, $user_id, $context);
   723 	}
  1111 	}
   724 
  1112 
   725 	if ( 'user_url' == $field )
  1113 	if ( 'user_url' == $field )
   726 		$value = esc_url($value);
  1114 		$value = esc_url($value);
   727 
  1115 
   731 		$value = esc_js($value);
  1119 		$value = esc_js($value);
   732 
  1120 
   733 	return $value;
  1121 	return $value;
   734 }
  1122 }
   735 
  1123 
   736 ?>
  1124 /**
       
  1125  * Update all user caches
       
  1126  *
       
  1127  * @since 3.0.0
       
  1128  *
       
  1129  * @param object $user User object to be cached
       
  1130  */
       
  1131 function update_user_caches($user) {
       
  1132 	wp_cache_add($user->ID, $user, 'users');
       
  1133 	wp_cache_add($user->user_login, $user->ID, 'userlogins');
       
  1134 	wp_cache_add($user->user_email, $user->ID, 'useremail');
       
  1135 	wp_cache_add($user->user_nicename, $user->ID, 'userslugs');
       
  1136 }
       
  1137 
       
  1138 /**
       
  1139  * Clean all user caches
       
  1140  *
       
  1141  * @since 3.0.0
       
  1142  *
       
  1143  * @param WP_User|int $user User object or ID to be cleaned from the cache
       
  1144  */
       
  1145 function clean_user_cache( $user ) {
       
  1146 	if ( is_numeric( $user ) )
       
  1147 		$user = new WP_User( $user );
       
  1148 
       
  1149 	if ( ! $user->exists() )
       
  1150 		return;
       
  1151 
       
  1152 	wp_cache_delete( $user->ID, 'users' );
       
  1153 	wp_cache_delete( $user->user_login, 'userlogins' );
       
  1154 	wp_cache_delete( $user->user_email, 'useremail' );
       
  1155 	wp_cache_delete( $user->user_nicename, 'userslugs' );
       
  1156 }
       
  1157 
       
  1158 /**
       
  1159  * Checks whether the given username exists.
       
  1160  *
       
  1161  * @since 2.0.0
       
  1162  *
       
  1163  * @param string $username Username.
       
  1164  * @return null|int The user's ID on success, and null on failure.
       
  1165  */
       
  1166 function username_exists( $username ) {
       
  1167 	if ( $user = get_user_by('login', $username ) ) {
       
  1168 		return $user->ID;
       
  1169 	} else {
       
  1170 		return null;
       
  1171 	}
       
  1172 }
       
  1173 
       
  1174 /**
       
  1175  * Checks whether the given email exists.
       
  1176  *
       
  1177  * @since 2.1.0
       
  1178  * @uses $wpdb
       
  1179  *
       
  1180  * @param string $email Email.
       
  1181  * @return bool|int The user's ID on success, and false on failure.
       
  1182  */
       
  1183 function email_exists( $email ) {
       
  1184 	if ( $user = get_user_by('email', $email) )
       
  1185 		return $user->ID;
       
  1186 
       
  1187 	return false;
       
  1188 }
       
  1189 
       
  1190 /**
       
  1191  * Checks whether an username is valid.
       
  1192  *
       
  1193  * @since 2.0.1
       
  1194  * @uses apply_filters() Calls 'validate_username' hook on $valid check and $username as parameters
       
  1195  *
       
  1196  * @param string $username Username.
       
  1197  * @return bool Whether username given is valid
       
  1198  */
       
  1199 function validate_username( $username ) {
       
  1200 	$sanitized = sanitize_user( $username, true );
       
  1201 	$valid = ( $sanitized == $username );
       
  1202 	return apply_filters( 'validate_username', $valid, $username );
       
  1203 }
       
  1204 
       
  1205 /**
       
  1206  * Insert an user into the database.
       
  1207  *
       
  1208  * Can update a current user or insert a new user based on whether the user's ID
       
  1209  * is present.
       
  1210  *
       
  1211  * Can be used to update the user's info (see below), set the user's role, and
       
  1212  * set the user's preference on whether they want the rich editor on.
       
  1213  *
       
  1214  * Most of the $userdata array fields have filters associated with the values.
       
  1215  * The exceptions are 'rich_editing', 'role', 'jabber', 'aim', 'yim',
       
  1216  * 'user_registered', and 'ID'. The filters have the prefix 'pre_user_' followed
       
  1217  * by the field name. An example using 'description' would have the filter
       
  1218  * called, 'pre_user_description' that can be hooked into.
       
  1219  *
       
  1220  * The $userdata array can contain the following fields:
       
  1221  * 'ID' - An integer that will be used for updating an existing user.
       
  1222  * 'user_pass' - A string that contains the plain text password for the user.
       
  1223  * 'user_login' - A string that contains the user's username for logging in.
       
  1224  * 'user_nicename' - A string that contains a nicer looking name for the user.
       
  1225  *		The default is the user's username.
       
  1226  * 'user_url' - A string containing the user's URL for the user's web site.
       
  1227  * 'user_email' - A string containing the user's email address.
       
  1228  * 'display_name' - A string that will be shown on the site. Defaults to user's
       
  1229  *		username. It is likely that you will want to change this, for appearance.
       
  1230  * 'nickname' - The user's nickname, defaults to the user's username.
       
  1231  * 'first_name' - The user's first name.
       
  1232  * 'last_name' - The user's last name.
       
  1233  * 'description' - A string containing content about the user.
       
  1234  * 'rich_editing' - A string for whether to enable the rich editor. False
       
  1235  *		if not empty.
       
  1236  * 'user_registered' - The date the user registered. Format is 'Y-m-d H:i:s'.
       
  1237  * 'role' - A string used to set the user's role.
       
  1238  * 'jabber' - User's Jabber account.
       
  1239  * 'aim' - User's AOL IM account.
       
  1240  * 'yim' - User's Yahoo IM account.
       
  1241  *
       
  1242  * @since 2.0.0
       
  1243  * @uses $wpdb WordPress database layer.
       
  1244  * @uses apply_filters() Calls filters for most of the $userdata fields with the prefix 'pre_user'. See note above.
       
  1245  * @uses do_action() Calls 'profile_update' hook when updating giving the user's ID
       
  1246  * @uses do_action() Calls 'user_register' hook when creating a new user giving the user's ID
       
  1247  *
       
  1248  * @param array $userdata An array of user data.
       
  1249  * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not be created.
       
  1250  */
       
  1251 function wp_insert_user($userdata) {
       
  1252 	global $wpdb;
       
  1253 
       
  1254 	extract($userdata, EXTR_SKIP);
       
  1255 
       
  1256 	// Are we updating or creating?
       
  1257 	if ( !empty($ID) ) {
       
  1258 		$ID = (int) $ID;
       
  1259 		$update = true;
       
  1260 		$old_user_data = WP_User::get_data_by( 'id', $ID );
       
  1261 	} else {
       
  1262 		$update = false;
       
  1263 		// Hash the password
       
  1264 		$user_pass = wp_hash_password($user_pass);
       
  1265 	}
       
  1266 
       
  1267 	$user_login = sanitize_user($user_login, true);
       
  1268 	$user_login = apply_filters('pre_user_login', $user_login);
       
  1269 
       
  1270 	//Remove any non-printable chars from the login string to see if we have ended up with an empty username
       
  1271 	$user_login = trim($user_login);
       
  1272 
       
  1273 	if ( empty($user_login) )
       
  1274 		return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') );
       
  1275 
       
  1276 	if ( !$update && username_exists( $user_login ) )
       
  1277 		return new WP_Error('existing_user_login', __('This username is already registered.') );
       
  1278 
       
  1279 	if ( empty($user_nicename) )
       
  1280 		$user_nicename = sanitize_title( $user_login );
       
  1281 	$user_nicename = apply_filters('pre_user_nicename', $user_nicename);
       
  1282 
       
  1283 	if ( empty($user_url) )
       
  1284 		$user_url = '';
       
  1285 	$user_url = apply_filters('pre_user_url', $user_url);
       
  1286 
       
  1287 	if ( empty($user_email) )
       
  1288 		$user_email = '';
       
  1289 	$user_email = apply_filters('pre_user_email', $user_email);
       
  1290 
       
  1291 	if ( !$update && ! defined( 'WP_IMPORTING' ) && email_exists($user_email) )
       
  1292 		return new WP_Error('existing_user_email', __('This email address is already registered.') );
       
  1293 
       
  1294 	if ( empty($display_name) )
       
  1295 		$display_name = $user_login;
       
  1296 	$display_name = apply_filters('pre_user_display_name', $display_name);
       
  1297 
       
  1298 	if ( empty($nickname) )
       
  1299 		$nickname = $user_login;
       
  1300 	$nickname = apply_filters('pre_user_nickname', $nickname);
       
  1301 
       
  1302 	if ( empty($first_name) )
       
  1303 		$first_name = '';
       
  1304 	$first_name = apply_filters('pre_user_first_name', $first_name);
       
  1305 
       
  1306 	if ( empty($last_name) )
       
  1307 		$last_name = '';
       
  1308 	$last_name = apply_filters('pre_user_last_name', $last_name);
       
  1309 
       
  1310 	if ( empty($description) )
       
  1311 		$description = '';
       
  1312 	$description = apply_filters('pre_user_description', $description);
       
  1313 
       
  1314 	if ( empty($rich_editing) )
       
  1315 		$rich_editing = 'true';
       
  1316 
       
  1317 	if ( empty($comment_shortcuts) )
       
  1318 		$comment_shortcuts = 'false';
       
  1319 
       
  1320 	if ( empty($admin_color) )
       
  1321 		$admin_color = 'fresh';
       
  1322 	$admin_color = preg_replace('|[^a-z0-9 _.\-@]|i', '', $admin_color);
       
  1323 
       
  1324 	if ( empty($use_ssl) )
       
  1325 		$use_ssl = 0;
       
  1326 
       
  1327 	if ( empty($user_registered) )
       
  1328 		$user_registered = gmdate('Y-m-d H:i:s');
       
  1329 
       
  1330 	if ( empty($show_admin_bar_front) )
       
  1331 		$show_admin_bar_front = 'true';
       
  1332 
       
  1333 	$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));
       
  1334 
       
  1335 	if ( $user_nicename_check ) {
       
  1336 		$suffix = 2;
       
  1337 		while ($user_nicename_check) {
       
  1338 			$alt_user_nicename = $user_nicename . "-$suffix";
       
  1339 			$user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $alt_user_nicename, $user_login));
       
  1340 			$suffix++;
       
  1341 		}
       
  1342 		$user_nicename = $alt_user_nicename;
       
  1343 	}
       
  1344 
       
  1345 	$data = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' );
       
  1346 	$data = stripslashes_deep( $data );
       
  1347 
       
  1348 	if ( $update ) {
       
  1349 		$wpdb->update( $wpdb->users, $data, compact( 'ID' ) );
       
  1350 		$user_id = (int) $ID;
       
  1351 	} else {
       
  1352 		$wpdb->insert( $wpdb->users, $data + compact( 'user_login' ) );
       
  1353 		$user_id = (int) $wpdb->insert_id;
       
  1354 	}
       
  1355 
       
  1356 	$user = new WP_User( $user_id );
       
  1357 
       
  1358 	foreach ( _get_additional_user_keys( $user ) as $key ) {
       
  1359 		if ( isset( $$key ) )
       
  1360 			update_user_meta( $user_id, $key, $$key );
       
  1361 	}
       
  1362 
       
  1363 	if ( isset($role) )
       
  1364 		$user->set_role($role);
       
  1365 	elseif ( !$update )
       
  1366 		$user->set_role(get_option('default_role'));
       
  1367 
       
  1368 	wp_cache_delete($user_id, 'users');
       
  1369 	wp_cache_delete($user_login, 'userlogins');
       
  1370 
       
  1371 	if ( $update )
       
  1372 		do_action('profile_update', $user_id, $old_user_data);
       
  1373 	else
       
  1374 		do_action('user_register', $user_id);
       
  1375 
       
  1376 	return $user_id;
       
  1377 }
       
  1378 
       
  1379 /**
       
  1380  * Update an user in the database.
       
  1381  *
       
  1382  * It is possible to update a user's password by specifying the 'user_pass'
       
  1383  * value in the $userdata parameter array.
       
  1384  *
       
  1385  * If $userdata does not contain an 'ID' key, then a new user will be created
       
  1386  * and the new user's ID will be returned.
       
  1387  *
       
  1388  * If current user's password is being updated, then the cookies will be
       
  1389  * cleared.
       
  1390  *
       
  1391  * @since 2.0.0
       
  1392  * @see wp_insert_user() For what fields can be set in $userdata
       
  1393  * @uses wp_insert_user() Used to update existing user or add new one if user doesn't exist already
       
  1394  *
       
  1395  * @param array $userdata An array of user data.
       
  1396  * @return int The updated user's ID.
       
  1397  */
       
  1398 function wp_update_user($userdata) {
       
  1399 	$ID = (int) $userdata['ID'];
       
  1400 
       
  1401 	// First, get all of the original fields
       
  1402 	$user_obj = get_userdata( $ID );
       
  1403 
       
  1404 	$user = get_object_vars( $user_obj->data );
       
  1405 
       
  1406 	// Add additional custom fields
       
  1407 	foreach ( _get_additional_user_keys( $user_obj ) as $key ) {
       
  1408 		$user[ $key ] = get_user_meta( $ID, $key, true );
       
  1409 	}
       
  1410 
       
  1411 	// Escape data pulled from DB.
       
  1412 	$user = add_magic_quotes( $user );
       
  1413 
       
  1414 	// If password is changing, hash it now.
       
  1415 	if ( ! empty($userdata['user_pass']) ) {
       
  1416 		$plaintext_pass = $userdata['user_pass'];
       
  1417 		$userdata['user_pass'] = wp_hash_password($userdata['user_pass']);
       
  1418 	}
       
  1419 
       
  1420 	wp_cache_delete($user[ 'user_email' ], 'useremail');
       
  1421 
       
  1422 	// Merge old and new fields with new fields overwriting old ones.
       
  1423 	$userdata = array_merge($user, $userdata);
       
  1424 	$user_id = wp_insert_user($userdata);
       
  1425 
       
  1426 	// Update the cookies if the password changed.
       
  1427 	$current_user = wp_get_current_user();
       
  1428 	if ( $current_user->ID == $ID ) {
       
  1429 		if ( isset($plaintext_pass) ) {
       
  1430 			wp_clear_auth_cookie();
       
  1431 			wp_set_auth_cookie($ID);
       
  1432 		}
       
  1433 	}
       
  1434 
       
  1435 	return $user_id;
       
  1436 }
       
  1437 
       
  1438 /**
       
  1439  * A simpler way of inserting an user into the database.
       
  1440  *
       
  1441  * Creates a new user with just the username, password, and email. For more
       
  1442  * complex user creation use wp_insert_user() to specify more information.
       
  1443  *
       
  1444  * @since 2.0.0
       
  1445  * @see wp_insert_user() More complete way to create a new user
       
  1446  *
       
  1447  * @param string $username The user's username.
       
  1448  * @param string $password The user's password.
       
  1449  * @param string $email The user's email (optional).
       
  1450  * @return int The new user's ID.
       
  1451  */
       
  1452 function wp_create_user($username, $password, $email = '') {
       
  1453 	$user_login = esc_sql( $username );
       
  1454 	$user_email = esc_sql( $email    );
       
  1455 	$user_pass = $password;
       
  1456 
       
  1457 	$userdata = compact('user_login', 'user_email', 'user_pass');
       
  1458 	return wp_insert_user($userdata);
       
  1459 }
       
  1460 
       
  1461 /**
       
  1462  * Return a list of meta keys that wp_insert_user() is supposed to set.
       
  1463  *
       
  1464  * @access private
       
  1465  * @since 3.3.0
       
  1466  *
       
  1467  * @param object $user WP_User instance
       
  1468  * @return array
       
  1469  */
       
  1470 function _get_additional_user_keys( $user ) {
       
  1471 	$keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' );
       
  1472 	return array_merge( $keys, array_keys( _wp_get_user_contactmethods( $user ) ) );
       
  1473 }
       
  1474 
       
  1475 /**
       
  1476  * Set up the default contact methods
       
  1477  *
       
  1478  * @access private
       
  1479  * @since
       
  1480  *
       
  1481  * @param object $user User data object (optional)
       
  1482  * @return array $user_contactmethods Array of contact methods and their labels.
       
  1483  */
       
  1484 function _wp_get_user_contactmethods( $user = null ) {
       
  1485 	$user_contactmethods = array(
       
  1486 		'aim' => __('AIM'),
       
  1487 		'yim' => __('Yahoo IM'),
       
  1488 		'jabber' => __('Jabber / Google Talk')
       
  1489 	);
       
  1490 	return apply_filters( 'user_contactmethods', $user_contactmethods, $user );
       
  1491 }