Changeset 33749 for trunk/src/wp-includes/class-wp-user-query.php
- Timestamp:
- 08/26/2015 04:19:32 AM (10 years ago)
- File:
-
- 1 copied
-
trunk/src/wp-includes/class-wp-user-query.php (copied) (copied from trunk/src/wp-includes/user.php) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-user-query.php
r33746 r33749 1 1 <?php 2 /**3 * WordPress User API4 *5 * @package WordPress6 * @subpackage Users7 */8 9 /**10 * Authenticate user with remember capability.11 *12 * The credentials is an array that has 'user_login', 'user_password', and13 * 'remember' indices. If the credentials is not given, then the log in form14 * will be assumed and used if set.15 *16 * The various authentication cookies will be set by this function and will be17 * set for a longer period depending on if the 'remember' credential is set to18 * true.19 *20 * @since 2.5.021 *22 * @global string $auth_secure_cookie23 *24 * @param array $credentials Optional. User info in order to sign on.25 * @param string|bool $secure_cookie Optional. Whether to use secure cookie.26 * @return WP_User|WP_Error WP_User on success, WP_Error on failure.27 */28 function wp_signon( $credentials = array(), $secure_cookie = '' ) {29 if ( empty($credentials) ) {30 if ( ! empty($_POST['log']) )31 $credentials['user_login'] = $_POST['log'];32 if ( ! empty($_POST['pwd']) )33 $credentials['user_password'] = $_POST['pwd'];34 if ( ! empty($_POST['rememberme']) )35 $credentials['remember'] = $_POST['rememberme'];36 }37 38 if ( !empty($credentials['remember']) )39 $credentials['remember'] = true;40 else41 $credentials['remember'] = false;42 43 /**44 * Fires before the user is authenticated.45 *46 * The variables passed to the callbacks are passed by reference,47 * and can be modified by callback functions.48 *49 * @since 1.5.150 *51 * @todo Decide whether to deprecate the wp_authenticate action.52 *53 * @param string $user_login Username, passed by reference.54 * @param string $user_password User password, passed by reference.55 */56 do_action_ref_array( 'wp_authenticate', array( &$credentials['user_login'], &$credentials['user_password'] ) );57 58 if ( '' === $secure_cookie )59 $secure_cookie = is_ssl();60 61 /**62 * Filter whether to use a secure sign-on cookie.63 *64 * @since 3.1.065 *66 * @param bool $secure_cookie Whether to use a secure sign-on cookie.67 * @param array $credentials {68 * Array of entered sign-on data.69 *70 * @type string $user_login Username.71 * @type string $user_password Password entered.72 * @type bool $remember Whether to 'remember' the user. Increases the time73 * that the cookie will be kept. Default false.74 * }75 */76 $secure_cookie = apply_filters( 'secure_signon_cookie', $secure_cookie, $credentials );77 78 global $auth_secure_cookie; // XXX ugly hack to pass this to wp_authenticate_cookie79 $auth_secure_cookie = $secure_cookie;80 81 add_filter('authenticate', 'wp_authenticate_cookie', 30, 3);82 83 $user = wp_authenticate($credentials['user_login'], $credentials['user_password']);84 85 if ( is_wp_error($user) ) {86 if ( $user->get_error_codes() == array('empty_username', 'empty_password') ) {87 $user = new WP_Error('', '');88 }89 90 return $user;91 }92 93 wp_set_auth_cookie($user->ID, $credentials['remember'], $secure_cookie);94 /**95 * Fires after the user has successfully logged in.96 *97 * @since 1.5.098 *99 * @param string $user_login Username.100 * @param WP_User $user WP_User object of the logged-in user.101 */102 do_action( 'wp_login', $user->user_login, $user );103 return $user;104 }105 106 /**107 * Authenticate the user using the username and password.108 *109 * @since 2.8.0110 *111 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.112 * @param string $username Username for authentication.113 * @param string $password Password for authentication.114 * @return WP_User|WP_Error WP_User on success, WP_Error on failure.115 */116 function wp_authenticate_username_password($user, $username, $password) {117 if ( $user instanceof WP_User ) {118 return $user;119 }120 121 if ( empty($username) || empty($password) ) {122 if ( is_wp_error( $user ) )123 return $user;124 125 $error = new WP_Error();126 127 if ( empty($username) )128 $error->add('empty_username', __('<strong>ERROR</strong>: The username field is empty.'));129 130 if ( empty($password) )131 $error->add('empty_password', __('<strong>ERROR</strong>: The password field is empty.'));132 133 return $error;134 }135 136 $user = get_user_by('login', $username);137 138 if ( !$user )139 return new WP_Error( 'invalid_username', sprintf( __( '<strong>ERROR</strong>: Invalid username. <a href="%s">Lost your password?</a>' ), wp_lostpassword_url() ) );140 141 /**142 * Filter whether the given user can be authenticated with the provided $password.143 *144 * @since 2.5.0145 *146 * @param WP_User|WP_Error $user WP_User or WP_Error object if a previous147 * callback failed authentication.148 * @param string $password Password to check against the user.149 */150 $user = apply_filters( 'wp_authenticate_user', $user, $password );151 if ( is_wp_error($user) )152 return $user;153 154 if ( !wp_check_password($password, $user->user_pass, $user->ID) )155 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>' ),156 $username, wp_lostpassword_url() ) );157 158 return $user;159 }160 161 /**162 * Authenticate the user using the WordPress auth cookie.163 *164 * @since 2.8.0165 *166 * @global string $auth_secure_cookie167 *168 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.169 * @param string $username Username. If not empty, cancels the cookie authentication.170 * @param string $password Password. If not empty, cancels the cookie authentication.171 * @return WP_User|WP_Error WP_User on success, WP_Error on failure.172 */173 function wp_authenticate_cookie($user, $username, $password) {174 if ( $user instanceof WP_User ) {175 return $user;176 }177 178 if ( empty($username) && empty($password) ) {179 $user_id = wp_validate_auth_cookie();180 if ( $user_id )181 return new WP_User($user_id);182 183 global $auth_secure_cookie;184 185 if ( $auth_secure_cookie )186 $auth_cookie = SECURE_AUTH_COOKIE;187 else188 $auth_cookie = AUTH_COOKIE;189 190 if ( !empty($_COOKIE[$auth_cookie]) )191 return new WP_Error('expired_session', __('Please log in again.'));192 193 // If the cookie is not set, be silent.194 }195 196 return $user;197 }198 199 /**200 * For Multisite blogs, check if the authenticated user has been marked as a201 * spammer, or if the user's primary blog has been marked as spam.202 *203 * @since 3.7.0204 *205 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null.206 * @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer.207 */208 function wp_authenticate_spam_check( $user ) {209 if ( $user instanceof WP_User && is_multisite() ) {210 /**211 * Filter whether the user has been marked as a spammer.212 *213 * @since 3.7.0214 *215 * @param bool $spammed Whether the user is considered a spammer.216 * @param WP_User $user User to check against.217 */218 $spammed = apply_filters( 'check_is_user_spammed', is_user_spammy(), $user );219 220 if ( $spammed )221 return new WP_Error( 'spammer_account', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.' ) );222 }223 return $user;224 }225 226 /**227 * Validate the logged-in cookie.228 *229 * Checks the logged-in cookie if the previous auth cookie could not be230 * validated and parsed.231 *232 * This is a callback for the determine_current_user filter, rather than API.233 *234 * @since 3.9.0235 *236 * @param int|bool $user_id The user ID (or false) as received from the237 * determine_current_user filter.238 * @return int|false User ID if validated, false otherwise. If a user ID from239 * an earlier filter callback is received, that value is returned.240 */241 function wp_validate_logged_in_cookie( $user_id ) {242 if ( $user_id ) {243 return $user_id;244 }245 246 if ( is_blog_admin() || is_network_admin() || empty( $_COOKIE[LOGGED_IN_COOKIE] ) ) {247 return false;248 }249 250 return wp_validate_auth_cookie( $_COOKIE[LOGGED_IN_COOKIE], 'logged_in' );251 }252 253 /**254 * Number of posts user has written.255 *256 * @since 3.0.0257 * @since 4.1.0 Added `$post_type` argument.258 * @since 4.3.0 Added `$public_only` argument. Added the ability to pass an array259 * of post types to `$post_type`.260 *261 * @global wpdb $wpdb WordPress database object for queries.262 *263 * @param int $userid User ID.264 * @param array|string $post_type Optional. Single post type or array of post types to count the number of posts for. Default 'post'.265 * @param bool $public_only Optional. Whether to only return counts for public posts. Default false.266 * @return int Number of posts the user has written in this post type.267 */268 function count_user_posts( $userid, $post_type = 'post', $public_only = false ) {269 global $wpdb;270 271 $where = get_posts_by_author_sql( $post_type, true, $userid, $public_only );272 273 $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" );274 275 /**276 * Filter the number of posts a user has written.277 *278 * @since 2.7.0279 * @since 4.1.0 Added `$post_type` argument.280 * @since 4.3.1 Added `$public_only` argument.281 *282 * @param int $count The user's post count.283 * @param int $userid User ID.284 * @param string|array $post_type Single post type or array of post types to count the number of posts for.285 * @param bool $public_only Whether to limit counted posts to public posts.286 */287 return apply_filters( 'get_usernumposts', $count, $userid, $post_type, $public_only );288 }289 290 /**291 * Number of posts written by a list of users.292 *293 * @since 3.0.0294 *295 * @global wpdb $wpdb296 *297 * @param array $users Array of user IDs.298 * @param string|array $post_type Optional. Single post type or array of post types to check. Defaults to 'post'.299 * @param bool $public_only Optional. Only return counts for public posts. Defaults to false.300 * @return array Amount of posts each user has written.301 */302 function count_many_users_posts( $users, $post_type = 'post', $public_only = false ) {303 global $wpdb;304 305 $count = array();306 if ( empty( $users ) || ! is_array( $users ) )307 return $count;308 309 $userlist = implode( ',', array_map( 'absint', $users ) );310 $where = get_posts_by_author_sql( $post_type, true, null, $public_only );311 312 $result = $wpdb->get_results( "SELECT post_author, COUNT(*) FROM $wpdb->posts $where AND post_author IN ($userlist) GROUP BY post_author", ARRAY_N );313 foreach ( $result as $row ) {314 $count[ $row[0] ] = $row[1];315 }316 317 foreach ( $users as $id ) {318 if ( ! isset( $count[ $id ] ) )319 $count[ $id ] = 0;320 }321 322 return $count;323 }324 325 //326 // User option functions327 //328 329 /**330 * Get the current user's ID331 *332 * @since MU333 *334 * @return int The current user's ID335 */336 function get_current_user_id() {337 if ( ! function_exists( 'wp_get_current_user' ) )338 return 0;339 $user = wp_get_current_user();340 return ( isset( $user->ID ) ? (int) $user->ID : 0 );341 }342 343 /**344 * Retrieve user option that can be either per Site or per Network.345 *346 * If the user ID is not given, then the current user will be used instead. If347 * the user ID is given, then the user data will be retrieved. The filter for348 * the result, will also pass the original option name and finally the user data349 * object as the third parameter.350 *351 * The option will first check for the per site name and then the per Network name.352 *353 * @since 2.0.0354 *355 * @global wpdb $wpdb WordPress database object for queries.356 *357 * @param string $option User option name.358 * @param int $user Optional. User ID.359 * @param string $deprecated Use get_option() to check for an option in the options table.360 * @return mixed User option value on success, false on failure.361 */362 function get_user_option( $option, $user = 0, $deprecated = '' ) {363 global $wpdb;364 365 if ( !empty( $deprecated ) )366 _deprecated_argument( __FUNCTION__, '3.0' );367 368 if ( empty( $user ) )369 $user = get_current_user_id();370 371 if ( ! $user = get_userdata( $user ) )372 return false;373 374 $prefix = $wpdb->get_blog_prefix();375 if ( $user->has_prop( $prefix . $option ) ) // Blog specific376 $result = $user->get( $prefix . $option );377 elseif ( $user->has_prop( $option ) ) // User specific and cross-blog378 $result = $user->get( $option );379 else380 $result = false;381 382 /**383 * Filter a specific user option value.384 *385 * The dynamic portion of the hook name, `$option`, refers to the user option name.386 *387 * @since 2.5.0388 *389 * @param mixed $result Value for the user's option.390 * @param string $option Name of the option being retrieved.391 * @param WP_User $user WP_User object of the user whose option is being retrieved.392 */393 return apply_filters( "get_user_option_{$option}", $result, $option, $user );394 }395 396 /**397 * Update user option with global blog capability.398 *399 * User options are just like user metadata except that they have support for400 * global blog options. If the 'global' parameter is false, which it is by default401 * it will prepend the WordPress table prefix to the option name.402 *403 * Deletes the user option if $newvalue is empty.404 *405 * @since 2.0.0406 *407 * @global wpdb $wpdb WordPress database object for queries.408 *409 * @param int $user_id User ID.410 * @param string $option_name User option name.411 * @param mixed $newvalue User option value.412 * @param bool $global Optional. Whether option name is global or blog specific.413 * Default false (blog specific).414 * @return int|bool User meta ID if the option didn't exist, true on successful update,415 * false on failure.416 */417 function update_user_option( $user_id, $option_name, $newvalue, $global = false ) {418 global $wpdb;419 420 if ( !$global )421 $option_name = $wpdb->get_blog_prefix() . $option_name;422 423 return update_user_meta( $user_id, $option_name, $newvalue );424 }425 426 /**427 * Delete user option with global blog capability.428 *429 * User options are just like user metadata except that they have support for430 * global blog options. If the 'global' parameter is false, which it is by default431 * it will prepend the WordPress table prefix to the option name.432 *433 * @since 3.0.0434 *435 * @global wpdb $wpdb WordPress database object for queries.436 *437 * @param int $user_id User ID438 * @param string $option_name User option name.439 * @param bool $global Optional. Whether option name is global or blog specific.440 * Default false (blog specific).441 * @return bool True on success, false on failure.442 */443 function delete_user_option( $user_id, $option_name, $global = false ) {444 global $wpdb;445 446 if ( !$global )447 $option_name = $wpdb->get_blog_prefix() . $option_name;448 return delete_user_meta( $user_id, $option_name );449 }450 451 2 /** 452 3 * WordPress User Query class. 453 4 * 454 5 * @since 3.1.0 6 * @package WordPress 7 * @subpackage Users 455 8 * 456 9 * @see WP_User_Query::prepare_query() for information on accepted arguments. … … 1135 688 } 1136 689 } 1137 1138 /**1139 * Retrieve list of users matching criteria.1140 *1141 * @since 3.1.01142 *1143 * @see WP_User_Query1144 *1145 * @param array $args Optional. Arguments to retrieve users. See {@see WP_User_Query::prepare_query()}1146 * for more information on accepted arguments.1147 * @return array List of users.1148 */1149 function get_users( $args = array() ) {1150 1151 $args = wp_parse_args( $args );1152 $args['count_total'] = false;1153 1154 $user_search = new WP_User_Query($args);1155 1156 return (array) $user_search->get_results();1157 }1158 1159 /**1160 * Get the blogs a user belongs to.1161 *1162 * @since 3.0.01163 *1164 * @global wpdb $wpdb WordPress database object for queries.1165 *1166 * @param int $user_id User ID1167 * @param bool $all Whether to retrieve all blogs, or only blogs that are not1168 * marked as deleted, archived, or spam.1169 * @return array A list of the user's blogs. An empty array if the user doesn't exist1170 * or belongs to no blogs.1171 */1172 function get_blogs_of_user( $user_id, $all = false ) {1173 global $wpdb;1174 1175 $user_id = (int) $user_id;1176 1177 // Logged out users can't have blogs1178 if ( empty( $user_id ) )1179 return array();1180 1181 $keys = get_user_meta( $user_id );1182 if ( empty( $keys ) )1183 return array();1184 1185 if ( ! is_multisite() ) {1186 $blog_id = get_current_blog_id();1187 $blogs = array( $blog_id => new stdClass );1188 $blogs[ $blog_id ]->userblog_id = $blog_id;1189 $blogs[ $blog_id ]->blogname = get_option('blogname');1190 $blogs[ $blog_id ]->domain = '';1191 $blogs[ $blog_id ]->path = '';1192 $blogs[ $blog_id ]->site_id = 1;1193 $blogs[ $blog_id ]->siteurl = get_option('siteurl');1194 $blogs[ $blog_id ]->archived = 0;1195 $blogs[ $blog_id ]->spam = 0;1196 $blogs[ $blog_id ]->deleted = 0;1197 return $blogs;1198 }1199 1200 $blogs = array();1201 1202 if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) {1203 $blog = get_blog_details( 1 );1204 if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {1205 $blogs[ 1 ] = (object) array(1206 'userblog_id' => 1,1207 'blogname' => $blog->blogname,1208 'domain' => $blog->domain,1209 'path' => $blog->path,1210 'site_id' => $blog->site_id,1211 'siteurl' => $blog->siteurl,1212 'archived' => $blog->archived,1213 'mature' => $blog->mature,1214 'spam' => $blog->spam,1215 'deleted' => $blog->deleted,1216 );1217 }1218 unset( $keys[ $wpdb->base_prefix . 'capabilities' ] );1219 }1220 1221 $keys = array_keys( $keys );1222 1223 foreach ( $keys as $key ) {1224 if ( 'capabilities' !== substr( $key, -12 ) )1225 continue;1226 if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix ) )1227 continue;1228 $blog_id = str_replace( array( $wpdb->base_prefix, '_capabilities' ), '', $key );1229 if ( ! is_numeric( $blog_id ) )1230 continue;1231 1232 $blog_id = (int) $blog_id;1233 $blog = get_blog_details( $blog_id );1234 if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {1235 $blogs[ $blog_id ] = (object) array(1236 'userblog_id' => $blog_id,1237 'blogname' => $blog->blogname,1238 'domain' => $blog->domain,1239 'path' => $blog->path,1240 'site_id' => $blog->site_id,1241 'siteurl' => $blog->siteurl,1242 'archived' => $blog->archived,1243 'mature' => $blog->mature,1244 'spam' => $blog->spam,1245 'deleted' => $blog->deleted,1246 );1247 }1248 }1249 1250 /**1251 * Filter the list of blogs a user belongs to.1252 *1253 * @since MU1254 *1255 * @param array $blogs An array of blog objects belonging to the user.1256 * @param int $user_id User ID.1257 * @param bool $all Whether the returned blogs array should contain all blogs, including1258 * those marked 'deleted', 'archived', or 'spam'. Default false.1259 */1260 return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all );1261 }1262 1263 /**1264 * Find out whether a user is a member of a given blog.1265 *1266 * @since MU 1.11267 *1268 * @param int $user_id Optional. The unique ID of the user. Defaults to the current user.1269 * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site.1270 * @return bool1271 */1272 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) {1273 $user_id = (int) $user_id;1274 $blog_id = (int) $blog_id;1275 1276 if ( empty( $user_id ) )1277 $user_id = get_current_user_id();1278 1279 if ( empty( $blog_id ) )1280 $blog_id = get_current_blog_id();1281 1282 $blogs = get_blogs_of_user( $user_id );1283 return array_key_exists( $blog_id, $blogs );1284 }1285 1286 /**1287 * Add meta data field to a user.1288 *1289 * Post meta data is called "Custom Fields" on the Administration Screens.1290 *1291 * @since 3.0.01292 * @link https://codex.wordpress.org/Function_Reference/add_user_meta1293 *1294 * @param int $user_id User ID.1295 * @param string $meta_key Metadata name.1296 * @param mixed $meta_value Metadata value.1297 * @param bool $unique Optional, default is false. Whether the same key should not be added.1298 * @return int|false Meta ID on success, false on failure.1299 */1300 function add_user_meta($user_id, $meta_key, $meta_value, $unique = false) {1301 return add_metadata('user', $user_id, $meta_key, $meta_value, $unique);1302 }1303 1304 /**1305 * Remove metadata matching criteria from a user.1306 *1307 * You can match based on the key, or key and value. Removing based on key and1308 * value, will keep from removing duplicate metadata with the same key. It also1309 * allows removing all metadata matching key, if needed.1310 *1311 * @since 3.0.01312 * @link https://codex.wordpress.org/Function_Reference/delete_user_meta1313 *1314 * @param int $user_id User ID1315 * @param string $meta_key Metadata name.1316 * @param mixed $meta_value Optional. Metadata value.1317 * @return bool True on success, false on failure.1318 */1319 function delete_user_meta($user_id, $meta_key, $meta_value = '') {1320 return delete_metadata('user', $user_id, $meta_key, $meta_value);1321 }1322 1323 /**1324 * Retrieve user meta field for a user.1325 *1326 * @since 3.0.01327 * @link https://codex.wordpress.org/Function_Reference/get_user_meta1328 *1329 * @param int $user_id User ID.1330 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.1331 * @param bool $single Whether to return a single value.1332 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true.1333 */1334 function get_user_meta($user_id, $key = '', $single = false) {1335 return get_metadata('user', $user_id, $key, $single);1336 }1337 1338 /**1339 * Update user meta field based on user ID.1340 *1341 * Use the $prev_value parameter to differentiate between meta fields with the1342 * same key and user ID.1343 *1344 * If the meta field for the user does not exist, it will be added.1345 *1346 * @since 3.0.01347 * @link https://codex.wordpress.org/Function_Reference/update_user_meta1348 *1349 * @param int $user_id User ID.1350 * @param string $meta_key Metadata key.1351 * @param mixed $meta_value Metadata value.1352 * @param mixed $prev_value Optional. Previous value to check before removing.1353 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.1354 */1355 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') {1356 return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value);1357 }1358 1359 /**1360 * Count number of users who have each of the user roles.1361 *1362 * Assumes there are neither duplicated nor orphaned capabilities meta_values.1363 * Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query()1364 * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users.1365 * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257.1366 *1367 * @since 3.0.01368 *1369 * @global wpdb $wpdb1370 *1371 * @param string $strategy 'time' or 'memory'1372 * @return array Includes a grand total and an array of counts indexed by role strings.1373 */1374 function count_users($strategy = 'time') {1375 global $wpdb;1376 1377 // Initialize1378 $id = get_current_blog_id();1379 $blog_prefix = $wpdb->get_blog_prefix($id);1380 $result = array();1381 1382 if ( 'time' == $strategy ) {1383 $avail_roles = wp_roles()->get_names();1384 1385 // Build a CPU-intensive query that will return concise information.1386 $select_count = array();1387 foreach ( $avail_roles as $this_role => $name ) {1388 $select_count[] = $wpdb->prepare( "COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%');1389 }1390 $select_count = implode(', ', $select_count);1391 1392 // Add the meta_value index to the selection list, then run the query.1393 $row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N );1394 1395 // Run the previous loop again to associate results with role names.1396 $col = 0;1397 $role_counts = array();1398 foreach ( $avail_roles as $this_role => $name ) {1399 $count = (int) $row[$col++];1400 if ($count > 0) {1401 $role_counts[$this_role] = $count;1402 }1403 }1404 1405 // Get the meta_value index from the end of the result set.1406 $total_users = (int) $row[$col];1407 1408 $result['total_users'] = $total_users;1409 $result['avail_roles'] =& $role_counts;1410 } else {1411 $avail_roles = array();1412 1413 $users_of_blog = $wpdb->get_col( "SELECT meta_value FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'" );1414 1415 foreach ( $users_of_blog as $caps_meta ) {1416 $b_roles = maybe_unserialize($caps_meta);1417 if ( ! is_array( $b_roles ) )1418 continue;1419 foreach ( $b_roles as $b_role => $val ) {1420 if ( isset($avail_roles[$b_role]) ) {1421 $avail_roles[$b_role]++;1422 } else {1423 $avail_roles[$b_role] = 1;1424 }1425 }1426 }1427 1428 $result['total_users'] = count( $users_of_blog );1429 $result['avail_roles'] =& $avail_roles;1430 }1431 1432 return $result;1433 }1434 1435 //1436 // Private helper functions1437 //1438 1439 /**1440 * Set up global user vars.1441 *1442 * Used by wp_set_current_user() for back compat. Might be deprecated in the future.1443 *1444 * @since 2.0.41445 *1446 * @global string $user_login The user username for logging in1447 * @global object $userdata User data.1448 * @global int $user_level The level of the user1449 * @global int $user_ID The ID of the user1450 * @global string $user_email The email address of the user1451 * @global string $user_url The url in the user's profile1452 * @global string $user_identity The display name of the user1453 *1454 * @param int $for_user_id Optional. User ID to set up global data.1455 */1456 function setup_userdata($for_user_id = '') {1457 global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_identity;1458 1459 if ( '' == $for_user_id )1460 $for_user_id = get_current_user_id();1461 $user = get_userdata( $for_user_id );1462 1463 if ( ! $user ) {1464 $user_ID = 0;1465 $user_level = 0;1466 $userdata = null;1467 $user_login = $user_email = $user_url = $user_identity = '';1468 return;1469 }1470 1471 $user_ID = (int) $user->ID;1472 $user_level = (int) $user->user_level;1473 $userdata = $user;1474 $user_login = $user->user_login;1475 $user_email = $user->user_email;1476 $user_url = $user->user_url;1477 $user_identity = $user->display_name;1478 }1479 1480 /**1481 * Create dropdown HTML content of users.1482 *1483 * The content can either be displayed, which it is by default or retrieved by1484 * setting the 'echo' argument. The 'include' and 'exclude' arguments do not1485 * need to be used; all users will be displayed in that case. Only one can be1486 * used, either 'include' or 'exclude', but not both.1487 *1488 * The available arguments are as follows:1489 *1490 * @since 2.3.01491 *1492 * @global wpdb $wpdb WordPress database object for queries.1493 * @global int $blog_id1494 *1495 * @param array|string $args {1496 * Optional. Array or string of arguments to generate a drop-down of users.1497 * {@see WP_User_Query::prepare_query() for additional available arguments.1498 *1499 * @type string $show_option_all Text to show as the drop-down default (all).1500 * Default empty.1501 * @type string $show_option_none Text to show as the drop-down default when no1502 * users were found. Default empty.1503 * @type int|string $option_none_value Value to use for $show_option_non when no users1504 * were found. Default -1.1505 * @type string $hide_if_only_one_author Whether to skip generating the drop-down1506 * if only one user was found. Default empty.1507 * @type string $orderby Field to order found users by. Accepts user fields.1508 * Default 'display_name'.1509 * @type string $order Whether to order users in ascending or descending1510 * order. Accepts 'ASC' (ascending) or 'DESC' (descending).1511 * Default 'ASC'.1512 * @type array|string $include Array or comma-separated list of user IDs to include.1513 * Default empty.1514 * @type array|string $exclude Array or comma-separated list of user IDs to exclude.1515 * Default empty.1516 * @type bool|int $multi Whether to skip the ID attribute on the 'select' element.1517 * Accepts 1|true or 0|false. Default 0|false.1518 * @type string $show User table column to display. If the selected item is empty1519 * then the 'user_login' will be displayed in parentheses.1520 * Accepts user fields. Default 'display_name'.1521 * @type int|bool $echo Whether to echo or return the drop-down. Accepts 1|true (echo)1522 * or 0|false (return). Default 1|true.1523 * @type int $selected Which user ID should be selected. Default 0.1524 * @type bool $include_selected Whether to always include the selected user ID in the drop-1525 * down. Default false.1526 * @type string $name Name attribute of select element. Default 'user'.1527 * @type string $id ID attribute of the select element. Default is the value of $name.1528 * @type string $class Class attribute of the select element. Default empty.1529 * @type int $blog_id ID of blog (Multisite only). Default is ID of the current blog.1530 * @type string $who Which type of users to query. Accepts only an empty string or1531 * 'authors'. Default empty.1532 * }1533 * @return string String of HTML content.1534 */1535 function wp_dropdown_users( $args = '' ) {1536 $defaults = array(1537 'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',1538 'orderby' => 'display_name', 'order' => 'ASC',1539 'include' => '', 'exclude' => '', 'multi' => 0,1540 'show' => 'display_name', 'echo' => 1,1541 'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',1542 'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false,1543 'option_none_value' => -11544 );1545 1546 $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0;1547 1548 $r = wp_parse_args( $args, $defaults );1549 $show = $r['show'];1550 $show_option_all = $r['show_option_all'];1551 $show_option_none = $r['show_option_none'];1552 $option_none_value = $r['option_none_value'];1553 1554 $query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who' ) );1555 $query_args['fields'] = array( 'ID', 'user_login', $show );1556 $users = get_users( $query_args );1557 1558 $output = '';1559 if ( ! empty( $users ) && ( empty( $r['hide_if_only_one_author'] ) || count( $users ) > 1 ) ) {1560 $name = esc_attr( $r['name'] );1561 if ( $r['multi'] && ! $r['id'] ) {1562 $id = '';1563 } else {1564 $id = $r['id'] ? " id='" . esc_attr( $r['id'] ) . "'" : " id='$name'";1565 }1566 $output = "<select name='{$name}'{$id} class='" . $r['class'] . "'>\n";1567 1568 if ( $show_option_all ) {1569 $output .= "\t<option value='0'>$show_option_all</option>\n";1570 }1571 1572 if ( $show_option_none ) {1573 $_selected = selected( $option_none_value, $r['selected'], false );1574 $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$_selected>$show_option_none</option>\n";1575 }1576 1577 $found_selected = false;1578 foreach ( (array) $users as $user ) {1579 $user->ID = (int) $user->ID;1580 $_selected = selected( $user->ID, $r['selected'], false );1581 if ( $_selected ) {1582 $found_selected = true;1583 }1584 $display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')';1585 $output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n";1586 }1587 1588 if ( $r['include_selected'] && ! $found_selected && ( $r['selected'] > 0 ) ) {1589 $user = get_userdata( $r['selected'] );1590 $_selected = selected( $user->ID, $r['selected'], false );1591 $display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')';1592 $output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n";1593 }1594 1595 $output .= "</select>";1596 }1597 1598 /**1599 * Filter the wp_dropdown_users() HTML output.1600 *1601 * @since 2.3.01602 *1603 * @param string $output HTML output generated by wp_dropdown_users().1604 */1605 $html = apply_filters( 'wp_dropdown_users', $output );1606 1607 if ( $r['echo'] ) {1608 echo $html;1609 }1610 return $html;1611 }1612 1613 /**1614 * Sanitize user field based on context.1615 *1616 * Possible context values are: 'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The1617 * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'1618 * when calling filters.1619 *1620 * @since 2.3.01621 *1622 * @param string $field The user Object field name.1623 * @param mixed $value The user Object value.1624 * @param int $user_id User ID.1625 * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',1626 * 'attribute' and 'js'.1627 * @return mixed Sanitized value.1628 */1629 function sanitize_user_field($field, $value, $user_id, $context) {1630 $int_fields = array('ID');1631 if ( in_array($field, $int_fields) )1632 $value = (int) $value;1633 1634 if ( 'raw' == $context )1635 return $value;1636 1637 if ( !is_string($value) && !is_numeric($value) )1638 return $value;1639 1640 $prefixed = false !== strpos( $field, 'user_' );1641 1642 if ( 'edit' == $context ) {1643 if ( $prefixed ) {1644 1645 /** This filter is documented in wp-includes/post.php */1646 $value = apply_filters( "edit_{$field}", $value, $user_id );1647 } else {1648 1649 /**1650 * Filter a user field value in the 'edit' context.1651 *1652 * The dynamic portion of the hook name, `$field`, refers to the prefixed user1653 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.1654 *1655 * @since 2.9.01656 *1657 * @param mixed $value Value of the prefixed user field.1658 * @param int $user_id User ID.1659 */1660 $value = apply_filters( "edit_user_{$field}", $value, $user_id );1661 }1662 1663 if ( 'description' == $field )1664 $value = esc_html( $value ); // textarea_escaped?1665 else1666 $value = esc_attr($value);1667 } elseif ( 'db' == $context ) {1668 if ( $prefixed ) {1669 /** This filter is documented in wp-includes/post.php */1670 $value = apply_filters( "pre_{$field}", $value );1671 } else {1672 1673 /**1674 * Filter the value of a user field in the 'db' context.1675 *1676 * The dynamic portion of the hook name, `$field`, refers to the prefixed user1677 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.1678 *1679 * @since 2.9.01680 *1681 * @param mixed $value Value of the prefixed user field.1682 */1683 $value = apply_filters( "pre_user_{$field}", $value );1684 }1685 } else {1686 // Use display filters by default.1687 if ( $prefixed ) {1688 1689 /** This filter is documented in wp-includes/post.php */1690 $value = apply_filters( $field, $value, $user_id, $context );1691 } else {1692 1693 /**1694 * Filter the value of a user field in a standard context.1695 *1696 * The dynamic portion of the hook name, `$field`, refers to the prefixed user1697 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc.1698 *1699 * @since 2.9.01700 *1701 * @param mixed $value The user object value to sanitize.1702 * @param int $user_id User ID.1703 * @param string $context The context to filter within.1704 */1705 $value = apply_filters( "user_{$field}", $value, $user_id, $context );1706 }1707 }1708 1709 if ( 'user_url' == $field )1710 $value = esc_url($value);1711 1712 if ( 'attribute' == $context ) {1713 $value = esc_attr( $value );1714 } elseif ( 'js' == $context ) {1715 $value = esc_js( $value );1716 }1717 return $value;1718 }1719 1720 /**1721 * Update all user caches1722 *1723 * @since 3.0.01724 *1725 * @param object $user User object to be cached1726 */1727 function update_user_caches($user) {1728 wp_cache_add($user->ID, $user, 'users');1729 wp_cache_add($user->user_login, $user->ID, 'userlogins');1730 wp_cache_add($user->user_email, $user->ID, 'useremail');1731 wp_cache_add($user->user_nicename, $user->ID, 'userslugs');1732 }1733 1734 /**1735 * Clean all user caches1736 *1737 * @since 3.0.01738 *1739 * @param WP_User|int $user User object or ID to be cleaned from the cache1740 */1741 function clean_user_cache( $user ) {1742 if ( is_numeric( $user ) )1743 $user = new WP_User( $user );1744 1745 if ( ! $user->exists() )1746 return;1747 1748 wp_cache_delete( $user->ID, 'users' );1749 wp_cache_delete( $user->user_login, 'userlogins' );1750 wp_cache_delete( $user->user_email, 'useremail' );1751 wp_cache_delete( $user->user_nicename, 'userslugs' );1752 }1753 1754 /**1755 * Checks whether the given username exists.1756 *1757 * @since 2.0.01758 *1759 * @param string $username Username.1760 * @return int|false The user's ID on success, and false on failure.1761 */1762 function username_exists( $username ) {1763 if ( $user = get_user_by( 'login', $username ) ) {1764 return $user->ID;1765 }1766 return false;1767 }1768 1769 /**1770 * Checks whether the given email exists.1771 *1772 * @since 2.1.01773 *1774 * @param string $email Email.1775 * @return int|false The user's ID on success, and false on failure.1776 */1777 function email_exists( $email ) {1778 if ( $user = get_user_by( 'email', $email) ) {1779 return $user->ID;1780 }1781 return false;1782 }1783 1784 /**1785 * Checks whether a username is valid.1786 *1787 * @since 2.0.11788 *1789 * @param string $username Username.1790 * @return bool Whether username given is valid1791 */1792 function validate_username( $username ) {1793 $sanitized = sanitize_user( $username, true );1794 $valid = ( $sanitized == $username );1795 /**1796 * Filter whether the provided username is valid or not.1797 *1798 * @since 2.0.11799 *1800 * @param bool $valid Whether given username is valid.1801 * @param string $username Username to check.1802 */1803 return apply_filters( 'validate_username', $valid, $username );1804 }1805 1806 /**1807 * Insert a user into the database.1808 *1809 * Most of the `$userdata` array fields have filters associated with the values. Exceptions are1810 * 'ID', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl',1811 * 'user_registered', and 'role'. The filters have the prefix 'pre_user_' followed by the field1812 * name. An example using 'description' would have the filter called, 'pre_user_description' that1813 * can be hooked into.1814 *1815 * @since 2.0.01816 * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact1817 * methods for new installs. See wp_get_user_contact_methods().1818 *1819 * @global wpdb $wpdb WordPress database object for queries.1820 *1821 * @param array|object|WP_User $userdata {1822 * An array, object, or WP_User object of user data arguments.1823 *1824 * @type int $ID User ID. If supplied, the user will be updated.1825 * @type string $user_pass The plain-text user password.1826 * @type string $user_login The user's login username.1827 * @type string $user_nicename The URL-friendly user name.1828 * @type string $user_url The user URL.1829 * @type string $user_email The user email address.1830 * @type string $display_name The user's display name.1831 * Default is the the user's username.1832 * @type string $nickname The user's nickname.1833 * Default is the the user's username.1834 * @type string $first_name The user's first name. For new users, will be used1835 * to build the first part of the user's display name1836 * if `$display_name` is not specified.1837 * @type string $last_name The user's last name. For new users, will be used1838 * to build the second part of the user's display name1839 * if `$display_name` is not specified.1840 * @type string $description The user's biographical description.1841 * @type string|bool $rich_editing Whether to enable the rich-editor for the user.1842 * False if not empty.1843 * @type string|bool $comment_shortcuts Whether to enable comment moderation keyboard1844 * shortcuts for the user. Default false.1845 * @type string $admin_color Admin color scheme for the user. Default 'fresh'.1846 * @type bool $use_ssl Whether the user should always access the admin over1847 * https. Default false.1848 * @type string $user_registered Date the user registered. Format is 'Y-m-d H:i:s'.1849 * @type string|bool $show_admin_bar_front Whether to display the Admin Bar for the user on the1850 * site's frontend. Default true.1851 * @type string $role User's role.1852 * }1853 * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not1854 * be created.1855 */1856 function wp_insert_user( $userdata ) {1857 global $wpdb;1858 1859 if ( $userdata instanceof stdClass ) {1860 $userdata = get_object_vars( $userdata );1861 } elseif ( $userdata instanceof WP_User ) {1862 $userdata = $userdata->to_array();1863 }1864 // Are we updating or creating?1865 if ( ! empty( $userdata['ID'] ) ) {1866 $ID = (int) $userdata['ID'];1867 $update = true;1868 $old_user_data = WP_User::get_data_by( 'id', $ID );1869 // hashed in wp_update_user(), plaintext if called directly1870 $user_pass = $userdata['user_pass'];1871 } else {1872 $update = false;1873 // Hash the password1874 $user_pass = wp_hash_password( $userdata['user_pass'] );1875 }1876 1877 $sanitized_user_login = sanitize_user( $userdata['user_login'], true );1878 1879 /**1880 * Filter a username after it has been sanitized.1881 *1882 * This filter is called before the user is created or updated.1883 *1884 * @since 2.0.31885 *1886 * @param string $sanitized_user_login Username after it has been sanitized.1887 */1888 $pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login );1889 1890 //Remove any non-printable chars from the login string to see if we have ended up with an empty username1891 $user_login = trim( $pre_user_login );1892 1893 if ( empty( $user_login ) ) {1894 return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') );1895 }1896 if ( ! $update && username_exists( $user_login ) ) {1897 return new WP_Error( 'existing_user_login', __( 'Sorry, that username already exists!' ) );1898 }1899 1900 // If a nicename is provided, remove unsafe user characters before1901 // using it. Otherwise build a nicename from the user_login.1902 if ( ! empty( $userdata['user_nicename'] ) ) {1903 $user_nicename = sanitize_user( $userdata['user_nicename'], true );1904 } else {1905 $user_nicename = $user_login;1906 }1907 1908 $user_nicename = sanitize_title( $user_nicename );1909 1910 // Store values to save in user meta.1911 $meta = array();1912 1913 /**1914 * Filter a user's nicename before the user is created or updated.1915 *1916 * @since 2.0.31917 *1918 * @param string $user_nicename The user's nicename.1919 */1920 $user_nicename = apply_filters( 'pre_user_nicename', $user_nicename );1921 1922 $raw_user_url = empty( $userdata['user_url'] ) ? '' : $userdata['user_url'];1923 1924 /**1925 * Filter a user's URL before the user is created or updated.1926 *1927 * @since 2.0.31928 *1929 * @param string $raw_user_url The user's URL.1930 */1931 $user_url = apply_filters( 'pre_user_url', $raw_user_url );1932 1933 $raw_user_email = empty( $userdata['user_email'] ) ? '' : $userdata['user_email'];1934 1935 /**1936 * Filter a user's email before the user is created or updated.1937 *1938 * @since 2.0.31939 *1940 * @param string $raw_user_email The user's email.1941 */1942 $user_email = apply_filters( 'pre_user_email', $raw_user_email );1943 1944 /*1945 * If there is no update, just check for `email_exists`. If there is an update,1946 * check if current email and new email are the same, or not, and check `email_exists`1947 * accordingly.1948 */1949 if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) )1950 && ! defined( 'WP_IMPORTING' )1951 && email_exists( $user_email )1952 ) {1953 return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) );1954 }1955 $nickname = empty( $userdata['nickname'] ) ? $user_login : $userdata['nickname'];1956 1957 /**1958 * Filter a user's nickname before the user is created or updated.1959 *1960 * @since 2.0.31961 *1962 * @param string $nickname The user's nickname.1963 */1964 $meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname );1965 1966 $first_name = empty( $userdata['first_name'] ) ? '' : $userdata['first_name'];1967 1968 /**1969 * Filter a user's first name before the user is created or updated.1970 *1971 * @since 2.0.31972 *1973 * @param string $first_name The user's first name.1974 */1975 $meta['first_name'] = apply_filters( 'pre_user_first_name', $first_name );1976 1977 $last_name = empty( $userdata['last_name'] ) ? '' : $userdata['last_name'];1978 1979 /**1980 * Filter a user's last name before the user is created or updated.1981 *1982 * @since 2.0.31983 *1984 * @param string $last_name The user's last name.1985 */1986 $meta['last_name'] = apply_filters( 'pre_user_last_name', $last_name );1987 1988 if ( empty( $userdata['display_name'] ) ) {1989 if ( $update ) {1990 $display_name = $user_login;1991 } elseif ( $meta['first_name'] && $meta['last_name'] ) {1992 /* translators: 1: first name, 2: last name */1993 $display_name = sprintf( _x( '%1$s %2$s', 'Display name based on first name and last name' ), $meta['first_name'], $meta['last_name'] );1994 } elseif ( $meta['first_name'] ) {1995 $display_name = $meta['first_name'];1996 } elseif ( $meta['last_name'] ) {1997 $display_name = $meta['last_name'];1998 } else {1999 $display_name = $user_login;2000 }2001 } else {2002 $display_name = $userdata['display_name'];2003 }2004 2005 /**2006 * Filter a user's display name before the user is created or updated.2007 *2008 * @since 2.0.32009 *2010 * @param string $display_name The user's display name.2011 */2012 $display_name = apply_filters( 'pre_user_display_name', $display_name );2013 2014 $description = empty( $userdata['description'] ) ? '' : $userdata['description'];2015 2016 /**2017 * Filter a user's description before the user is created or updated.2018 *2019 * @since 2.0.32020 *2021 * @param string $description The user's description.2022 */2023 $meta['description'] = apply_filters( 'pre_user_description', $description );2024 2025 $meta['rich_editing'] = empty( $userdata['rich_editing'] ) ? 'true' : $userdata['rich_editing'];2026 2027 $meta['comment_shortcuts'] = empty( $userdata['comment_shortcuts'] ) || 'false' === $userdata['comment_shortcuts'] ? 'false' : 'true';2028 2029 $admin_color = empty( $userdata['admin_color'] ) ? 'fresh' : $userdata['admin_color'];2030 $meta['admin_color'] = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $admin_color );2031 2032 $meta['use_ssl'] = empty( $userdata['use_ssl'] ) ? 0 : $userdata['use_ssl'];2033 2034 $user_registered = empty( $userdata['user_registered'] ) ? gmdate( 'Y-m-d H:i:s' ) : $userdata['user_registered'];2035 2036 $meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front'];2037 2038 $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));2039 2040 if ( $user_nicename_check ) {2041 $suffix = 2;2042 while ($user_nicename_check) {2043 $alt_user_nicename = $user_nicename . "-$suffix";2044 $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));2045 $suffix++;2046 }2047 $user_nicename = $alt_user_nicename;2048 }2049 2050 $compacted = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' );2051 $data = wp_unslash( $compacted );2052 2053 if ( $update ) {2054 if ( $user_email !== $old_user_data->user_email ) {2055 $data['user_activation_key'] = '';2056 }2057 $wpdb->update( $wpdb->users, $data, compact( 'ID' ) );2058 $user_id = (int) $ID;2059 } else {2060 $wpdb->insert( $wpdb->users, $data + compact( 'user_login' ) );2061 $user_id = (int) $wpdb->insert_id;2062 }2063 2064 $user = new WP_User( $user_id );2065 2066 /**2067 * Filter a user's meta values and keys before the user is created or updated.2068 *2069 * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`.2070 *2071 * @since 4.4.02072 *2073 * @param array $meta {2074 * Default meta values and keys for the user.2075 *2076 * @type string $nickname The user's nickname. Default is the the user's username.2077 * @type string $first_name The user's first name.2078 * @type string $last_name The user's last name.2079 * @type string $description The user's description.2080 * @type bool $rich_editing Whether to enable the rich-editor for the user. False if not empty.2081 * @type bool $comment_shortcuts Whether to enable keyboard shortcuts for the user. Default false.2082 * @type string $admin_color The color scheme for a user's admin screen. Default 'fresh'.2083 * @type int|bool $use_ssl Whether to force SSL on the user's admin area. 0|false if SSL is2084 * not forced.2085 * @type bool $show_admin_bar_front Whether to show the admin bar on the front end for the user.2086 * Default true.2087 * }2088 * @param WP_User $user User object.2089 */2090 $meta = apply_filters( 'insert_user_meta', $meta, $user );2091 2092 // Update user meta.2093 foreach ( $meta as $key => $value ) {2094 update_user_meta( $user_id, $key, $value );2095 }2096 2097 foreach ( wp_get_user_contact_methods( $user ) as $key => $value ) {2098 if ( isset( $userdata[ $key ] ) ) {2099 update_user_meta( $user_id, $key, $userdata[ $key ] );2100 }2101 }2102 2103 if ( isset( $userdata['role'] ) ) {2104 $user->set_role( $userdata['role'] );2105 } elseif ( ! $update ) {2106 $user->set_role(get_option('default_role'));2107 }2108 wp_cache_delete( $user_id, 'users' );2109 wp_cache_delete( $user_login, 'userlogins' );2110 2111 if ( $update ) {2112 /**2113 * Fires immediately after an existing user is updated.2114 *2115 * @since 2.0.02116 *2117 * @param int $user_id User ID.2118 * @param object $old_user_data Object containing user's data prior to update.2119 */2120 do_action( 'profile_update', $user_id, $old_user_data );2121 } else {2122 /**2123 * Fires immediately after a new user is registered.2124 *2125 * @since 1.5.02126 *2127 * @param int $user_id User ID.2128 */2129 do_action( 'user_register', $user_id );2130 }2131 2132 return $user_id;2133 }2134 2135 /**2136 * Update a user in the database.2137 *2138 * It is possible to update a user's password by specifying the 'user_pass'2139 * value in the $userdata parameter array.2140 *2141 * If current user's password is being updated, then the cookies will be2142 * cleared.2143 *2144 * @since 2.0.02145 *2146 * @see wp_insert_user() For what fields can be set in $userdata.2147 *2148 * @param mixed $userdata An array of user data or a user object of type stdClass or WP_User.2149 * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated.2150 */2151 function wp_update_user($userdata) {2152 if ( $userdata instanceof stdClass ) {2153 $userdata = get_object_vars( $userdata );2154 } elseif ( $userdata instanceof WP_User ) {2155 $userdata = $userdata->to_array();2156 }2157 2158 $ID = isset( $userdata['ID'] ) ? (int) $userdata['ID'] : 0;2159 if ( ! $ID ) {2160 return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );2161 }2162 2163 // First, get all of the original fields2164 $user_obj = get_userdata( $ID );2165 if ( ! $user_obj ) {2166 return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );2167 }2168 2169 $user = $user_obj->to_array();2170 2171 // Add additional custom fields2172 foreach ( _get_additional_user_keys( $user_obj ) as $key ) {2173 $user[ $key ] = get_user_meta( $ID, $key, true );2174 }2175 2176 // Escape data pulled from DB.2177 $user = add_magic_quotes( $user );2178 2179 if ( ! empty($userdata['user_pass']) ) {2180 // If password is changing, hash it now2181 $plaintext_pass = $userdata['user_pass'];2182 $userdata['user_pass'] = wp_hash_password( $userdata['user_pass'] );2183 2184 /**2185 * Filter whether to send the password change email.2186 *2187 * @since 4.3.02188 *2189 * @see wp_insert_user() For `$user` and `$userdata` fields.2190 *2191 * @param bool $send Whether to send the email.2192 * @param array $user The original user array.2193 * @param array $userdata The updated user array.2194 *2195 */2196 $send_password_change_email = apply_filters( 'send_password_change_email', true, $user, $userdata );2197 }2198 2199 if ( isset( $userdata['user_email'] ) && $user['user_email'] !== $userdata['user_email'] ) {2200 /**2201 * Filter whether to send the email change email.2202 *2203 * @since 4.3.02204 *2205 * @see wp_insert_user() For `$user` and `$userdata` fields.2206 *2207 * @param bool $send Whether to send the email.2208 * @param array $user The original user array.2209 * @param array $userdata The updated user array.2210 *2211 */2212 $send_email_change_email = apply_filters( 'send_email_change_email', true, $user, $userdata );2213 }2214 2215 wp_cache_delete( $user['user_email'], 'useremail' );2216 2217 // Merge old and new fields with new fields overwriting old ones.2218 $userdata = array_merge( $user, $userdata );2219 $user_id = wp_insert_user( $userdata );2220 2221 if ( ! is_wp_error( $user_id ) ) {2222 2223 $blog_name = wp_specialchars_decode( get_option( 'blogname' ) );2224 2225 if ( ! empty( $send_password_change_email ) ) {2226 2227 /* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */2228 $pass_change_text = __( 'Hi ###USERNAME###,2229 2230 This notice confirms that your password was changed on ###SITENAME###.2231 2232 If you did not change your password, please contact the Site Administrator at2233 ###ADMIN_EMAIL###2234 2235 This email has been sent to ###EMAIL###2236 2237 Regards,2238 All at ###SITENAME###2239 ###SITEURL###' );2240 2241 $pass_change_email = array(2242 'to' => $user['user_email'],2243 'subject' => __( '[%s] Notice of Password Change' ),2244 'message' => $pass_change_text,2245 'headers' => '',2246 );2247 2248 /**2249 * Filter the contents of the email sent when the user's password is changed.2250 *2251 * @since 4.3.02252 *2253 * @param array $pass_change_email {2254 * Used to build wp_mail().2255 * @type string $to The intended recipients. Add emails in a comma separated string.2256 * @type string $subject The subject of the email.2257 * @type string $message The content of the email.2258 * The following strings have a special meaning and will get replaced dynamically:2259 * - ###USERNAME### The current user's username.2260 * - ###ADMIN_EMAIL### The admin email in case this was unexpected.2261 * - ###EMAIL### The old email.2262 * - ###SITENAME### The name of the site.2263 * - ###SITEURL### The URL to the site.2264 * @type string $headers Headers. Add headers in a newline (\r\n) separated string.2265 * }2266 * @param array $user The original user array.2267 * @param array $userdata The updated user array.2268 *2269 */2270 $pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );2271 2272 $pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] );2273 $pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] );2274 $pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] );2275 $pass_change_email['message'] = str_replace( '###SITENAME###', get_option( 'blogname' ), $pass_change_email['message'] );2276 $pass_change_email['message'] = str_replace( '###SITEURL###', get_option( 'siteurl' ), $pass_change_email['message'] );2277 2278 wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] );2279 }2280 2281 if ( ! empty( $send_email_change_email ) ) {2282 /* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */2283 $email_change_text = __( 'Hi ###USERNAME###,2284 2285 This notice confirms that your email was changed on ###SITENAME###.2286 2287 If you did not change your email, please contact the Site Administrator at2288 ###ADMIN_EMAIL###2289 2290 This email has been sent to ###EMAIL###2291 2292 Regards,2293 All at ###SITENAME###2294 ###SITEURL###' );2295 2296 $email_change_email = array(2297 'to' => $user['user_email'],2298 'subject' => __( '[%s] Notice of Email Change' ),2299 'message' => $email_change_text,2300 'headers' => '',2301 );2302 2303 /**2304 * Filter the contents of the email sent when the user's email is changed.2305 *2306 * @since 4.3.02307 *2308 * @param array $email_change_email {2309 * Used to build wp_mail().2310 * @type string $to The intended recipients.2311 * @type string $subject The subject of the email.2312 * @type string $message The content of the email.2313 * The following strings have a special meaning and will get replaced dynamically:2314 * - ###USERNAME### The current user's username.2315 * - ###ADMIN_EMAIL### The admin email in case this was unexpected.2316 * - ###EMAIL### The old email.2317 * - ###SITENAME### The name of the site.2318 * - ###SITEURL### The URL to the site.2319 * @type string $headers Headers.2320 * }2321 * @param array $user The original user array.2322 * @param array $userdata The updated user array.2323 */2324 $email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );2325 2326 $email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] );2327 $email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] );2328 $email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] );2329 $email_change_email['message'] = str_replace( '###SITENAME###', get_option( 'blogname' ), $email_change_email['message'] );2330 $email_change_email['message'] = str_replace( '###SITEURL###', get_option( 'siteurl' ), $email_change_email['message'] );2331 2332 wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] );2333 }2334 }2335 2336 // Update the cookies if the password changed.2337 $current_user = wp_get_current_user();2338 if ( $current_user->ID == $ID ) {2339 if ( isset($plaintext_pass) ) {2340 wp_clear_auth_cookie();2341 2342 // Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.2343 // If it's greater than this, then we know the user checked 'Remember Me' when they logged in.2344 $logged_in_cookie = wp_parse_auth_cookie( '', 'logged_in' );2345 /** This filter is documented in wp-includes/pluggable.php */2346 $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $ID, false );2347 $remember = ( ( $logged_in_cookie['expiration'] - time() ) > $default_cookie_life );2348 2349 wp_set_auth_cookie( $ID, $remember );2350 }2351 }2352 2353 return $user_id;2354 }2355 2356 /**2357 * A simpler way of inserting a user into the database.2358 *2359 * Creates a new user with just the username, password, and email. For more2360 * complex user creation use {@see wp_insert_user()} to specify more information.2361 *2362 * @since 2.0.02363 * @see wp_insert_user() More complete way to create a new user2364 *2365 * @param string $username The user's username.2366 * @param string $password The user's password.2367 * @param string $email Optional. The user's email. Default empty.2368 * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not2369 * be created.2370 */2371 function wp_create_user($username, $password, $email = '') {2372 $user_login = wp_slash( $username );2373 $user_email = wp_slash( $email );2374 $user_pass = $password;2375 2376 $userdata = compact('user_login', 'user_email', 'user_pass');2377 return wp_insert_user($userdata);2378 }2379 2380 /**2381 * Returns a list of meta keys to be (maybe) populated in wp_update_user().2382 *2383 * The list of keys returned via this function are dependent on the presence2384 * of those keys in the user meta data to be set.2385 *2386 * @since 3.3.02387 * @access private2388 *2389 * @param WP_User $user WP_User instance.2390 * @return array List of user keys to be populated in wp_update_user().2391 */2392 function _get_additional_user_keys( $user ) {2393 $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' );2394 return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) );2395 }2396 2397 /**2398 * Set up the user contact methods.2399 *2400 * Default contact methods were removed in 3.6. A filter dictates contact methods.2401 *2402 * @since 3.7.02403 *2404 * @param WP_User $user Optional. WP_User object.2405 * @return array Array of contact methods and their labels.2406 */2407 function wp_get_user_contact_methods( $user = null ) {2408 $methods = array();2409 if ( get_site_option( 'initial_db_version' ) < 23588 ) {2410 $methods = array(2411 'aim' => __( 'AIM' ),2412 'yim' => __( 'Yahoo IM' ),2413 'jabber' => __( 'Jabber / Google Talk' )2414 );2415 }2416 2417 /**2418 * Filter the user contact methods.2419 *2420 * @since 2.9.02421 *2422 * @param array $methods Array of contact methods and their labels.2423 * @param WP_User $user WP_User object.2424 */2425 return apply_filters( 'user_contactmethods', $methods, $user );2426 }2427 2428 /**2429 * The old private function for setting up user contact methods.2430 *2431 * @since 2.9.02432 * @access private2433 */2434 function _wp_get_user_contactmethods( $user = null ) {2435 return wp_get_user_contact_methods( $user );2436 }2437 2438 /**2439 * Gets the text suggesting how to create strong passwords.2440 *2441 * @since 4.1.02442 *2443 * @return string The password hint text.2444 */2445 function wp_get_password_hint() {2446 $hint = __( 'Hint: The password should be at least twelve characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ & ).' );2447 2448 /**2449 * Filter the text describing the site's password complexity policy.2450 *2451 * @since 4.1.02452 *2453 * @param string $hint The password hint text.2454 */2455 return apply_filters( 'password_hint', $hint );2456 }2457 2458 /**2459 * Retrieves a user row based on password reset key and login2460 *2461 * A key is considered 'expired' if it exactly matches the value of the2462 * user_activation_key field, rather than being matched after going through the2463 * hashing process. This field is now hashed; old values are no longer accepted2464 * but have a different WP_Error code so good user feedback can be provided.2465 *2466 * @since 3.1.02467 *2468 * @global wpdb $wpdb WordPress database object for queries.2469 * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.2470 *2471 * @param string $key Hash to validate sending user's password.2472 * @param string $login The user login.2473 * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.2474 */2475 function check_password_reset_key($key, $login) {2476 global $wpdb, $wp_hasher;2477 2478 $key = preg_replace('/[^a-z0-9]/i', '', $key);2479 2480 if ( empty( $key ) || !is_string( $key ) )2481 return new WP_Error('invalid_key', __('Invalid key'));2482 2483 if ( empty($login) || !is_string($login) )2484 return new WP_Error('invalid_key', __('Invalid key'));2485 2486 $row = $wpdb->get_row( $wpdb->prepare( "SELECT ID, user_activation_key FROM $wpdb->users WHERE user_login = %s", $login ) );2487 if ( ! $row )2488 return new WP_Error('invalid_key', __('Invalid key'));2489 2490 if ( empty( $wp_hasher ) ) {2491 require_once ABSPATH . WPINC . '/class-phpass.php';2492 $wp_hasher = new PasswordHash( 8, true );2493 }2494 2495 /**2496 * Filter the expiration time of password reset keys.2497 *2498 * @since 4.3.02499 *2500 * @param int $expiration The expiration time in seconds.2501 */2502 $expiration_duration = apply_filters( 'password_reset_expiration', DAY_IN_SECONDS );2503 2504 if ( false !== strpos( $row->user_activation_key, ':' ) ) {2505 list( $pass_request_time, $pass_key ) = explode( ':', $row->user_activation_key, 2 );2506 $expiration_time = $pass_request_time + $expiration_duration;2507 } else {2508 $pass_key = $row->user_activation_key;2509 $expiration_time = false;2510 }2511 2512 $hash_is_correct = $wp_hasher->CheckPassword( $key, $pass_key );2513 2514 if ( $hash_is_correct && $expiration_time && time() < $expiration_time ) {2515 return get_userdata( $row->ID );2516 } elseif ( $hash_is_correct && $expiration_time ) {2517 // Key has an expiration time that's passed2518 return new WP_Error( 'expired_key', __( 'Invalid key' ) );2519 }2520 2521 if ( hash_equals( $row->user_activation_key, $key ) || ( $hash_is_correct && ! $expiration_time ) ) {2522 $return = new WP_Error( 'expired_key', __( 'Invalid key' ) );2523 $user_id = $row->ID;2524 2525 /**2526 * Filter the return value of check_password_reset_key() when an2527 * old-style key is used.2528 *2529 * @since 3.7.0 Previously plain-text keys were stored in the database.2530 * @since 4.3.0 Previously key hashes were stored without an expiration time.2531 *2532 * @param WP_Error $return A WP_Error object denoting an expired key.2533 * Return a WP_User object to validate the key.2534 * @param int $user_id The matched user ID.2535 */2536 return apply_filters( 'password_reset_key_expired', $return, $user_id );2537 }2538 2539 return new WP_Error( 'invalid_key', __( 'Invalid key' ) );2540 }2541 2542 /**2543 * Handles resetting the user's password.2544 *2545 * @since 2.5.02546 *2547 * @param object $user The user2548 * @param string $new_pass New password for the user in plaintext2549 */2550 function reset_password( $user, $new_pass ) {2551 /**2552 * Fires before the user's password is reset.2553 *2554 * @since 1.5.02555 *2556 * @param object $user The user.2557 * @param string $new_pass New user password.2558 */2559 do_action( 'password_reset', $user, $new_pass );2560 2561 wp_set_password( $new_pass, $user->ID );2562 update_user_option( $user->ID, 'default_password_nag', false, true );2563 2564 wp_password_change_notification( $user );2565 }2566 2567 /**2568 * Handles registering a new user.2569 *2570 * @since 2.5.02571 *2572 * @param string $user_login User's username for logging in2573 * @param string $user_email User's email address to send password and add2574 * @return int|WP_Error Either user's ID or error on failure.2575 */2576 function register_new_user( $user_login, $user_email ) {2577 $errors = new WP_Error();2578 2579 $sanitized_user_login = sanitize_user( $user_login );2580 /**2581 * Filter the email address of a user being registered.2582 *2583 * @since 2.1.02584 *2585 * @param string $user_email The email address of the new user.2586 */2587 $user_email = apply_filters( 'user_registration_email', $user_email );2588 2589 // Check the username2590 if ( $sanitized_user_login == '' ) {2591 $errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );2592 } elseif ( ! validate_username( $user_login ) ) {2593 $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );2594 $sanitized_user_login = '';2595 } elseif ( username_exists( $sanitized_user_login ) ) {2596 $errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ) );2597 }2598 2599 // Check the e-mail address2600 if ( $user_email == '' ) {2601 $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your e-mail address.' ) );2602 } elseif ( ! is_email( $user_email ) ) {2603 $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn’t correct.' ) );2604 $user_email = '';2605 } elseif ( email_exists( $user_email ) ) {2606 $errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) );2607 }2608 2609 /**2610 * Fires when submitting registration form data, before the user is created.2611 *2612 * @since 2.1.02613 *2614 * @param string $sanitized_user_login The submitted username after being sanitized.2615 * @param string $user_email The submitted email.2616 * @param WP_Error $errors Contains any errors with submitted username and email,2617 * e.g., an empty field, an invalid username or email,2618 * or an existing username or email.2619 */2620 do_action( 'register_post', $sanitized_user_login, $user_email, $errors );2621 2622 /**2623 * Filter the errors encountered when a new user is being registered.2624 *2625 * The filtered WP_Error object may, for example, contain errors for an invalid2626 * or existing username or email address. A WP_Error object should always returned,2627 * but may or may not contain errors.2628 *2629 * If any errors are present in $errors, this will abort the user's registration.2630 *2631 * @since 2.1.02632 *2633 * @param WP_Error $errors A WP_Error object containing any errors encountered2634 * during registration.2635 * @param string $sanitized_user_login User's username after it has been sanitized.2636 * @param string $user_email User's email.2637 */2638 $errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );2639 2640 if ( $errors->get_error_code() )2641 return $errors;2642 2643 $user_pass = wp_generate_password( 12, false );2644 $user_id = wp_create_user( $sanitized_user_login, $user_pass, $user_email );2645 if ( ! $user_id || is_wp_error( $user_id ) ) {2646 $errors->add( 'registerfail', sprintf( __( '<strong>ERROR</strong>: Couldn’t register you… please contact the <a href="mailto:%s">webmaster</a> !' ), get_option( 'admin_email' ) ) );2647 return $errors;2648 }2649 2650 update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag.2651 2652 wp_new_user_notification( $user_id, 'both' );2653 2654 return $user_id;2655 }2656 2657 /**2658 * Retrieve the current session token from the logged_in cookie.2659 *2660 * @since 4.0.02661 *2662 * @return string Token.2663 */2664 function wp_get_session_token() {2665 $cookie = wp_parse_auth_cookie( '', 'logged_in' );2666 return ! empty( $cookie['token'] ) ? $cookie['token'] : '';2667 }2668 2669 /**2670 * Retrieve a list of sessions for the current user.2671 *2672 * @since 4.0.02673 * @return array Array of sessions.2674 */2675 function wp_get_all_sessions() {2676 $manager = WP_Session_Tokens::get_instance( get_current_user_id() );2677 return $manager->get_all();2678 }2679 2680 /**2681 * Remove the current session token from the database.2682 *2683 * @since 4.0.02684 */2685 function wp_destroy_current_session() {2686 $token = wp_get_session_token();2687 if ( $token ) {2688 $manager = WP_Session_Tokens::get_instance( get_current_user_id() );2689 $manager->destroy( $token );2690 }2691 }2692 2693 /**2694 * Remove all but the current session token for the current user for the database.2695 *2696 * @since 4.0.02697 */2698 function wp_destroy_other_sessions() {2699 $token = wp_get_session_token();2700 if ( $token ) {2701 $manager = WP_Session_Tokens::get_instance( get_current_user_id() );2702 $manager->destroy_others( $token );2703 }2704 }2705 2706 /**2707 * Remove all session tokens for the current user from the database.2708 *2709 * @since 4.0.02710 */2711 function wp_destroy_all_sessions() {2712 $manager = WP_Session_Tokens::get_instance( get_current_user_id() );2713 $manager->destroy_all();2714 }
Note: See TracChangeset
for help on using the changeset viewer.