changeset 7 | cf61fcea0001 |
parent 5 | 5e2f62d02dcd |
child 9 | 177826044cd9 |
6:490d5cc509ed | 7:cf61fcea0001 |
---|---|
1 <?php |
1 <?php |
2 /** |
2 /** |
3 * WordPress User API |
3 * Core User API |
4 * |
4 * |
5 * @package WordPress |
5 * @package WordPress |
6 * @subpackage Users |
6 * @subpackage Users |
7 */ |
7 */ |
8 |
8 |
9 /** |
9 /** |
10 * Authenticate user with remember capability. |
10 * Authenticates and logs a user in with 'remember' capability. |
11 * |
11 * |
12 * The credentials is an array that has 'user_login', 'user_password', and |
12 * The credentials is an array that has 'user_login', 'user_password', and |
13 * 'remember' indices. If the credentials is not given, then the log in form |
13 * 'remember' indices. If the credentials is not given, then the log in form |
14 * will be assumed and used if set. |
14 * will be assumed and used if set. |
15 * |
15 * |
16 * The various authentication cookies will be set by this function and will be |
16 * The various authentication cookies will be set by this function and will be |
17 * set for a longer period depending on if the 'remember' credential is set to |
17 * set for a longer period depending on if the 'remember' credential is set to |
18 * true. |
18 * true. |
19 * |
19 * |
20 * Note: wp_signon() doesn't handle setting the current user. This means that if the |
|
21 * function is called before the {@see 'init'} hook is fired, is_user_logged_in() will |
|
22 * evaluate as false until that point. If is_user_logged_in() is needed in conjunction |
|
23 * with wp_signon(), wp_set_current_user() should be called explicitly. |
|
24 * |
|
20 * @since 2.5.0 |
25 * @since 2.5.0 |
26 * |
|
27 * @global string $auth_secure_cookie |
|
21 * |
28 * |
22 * @param array $credentials Optional. User info in order to sign on. |
29 * @param array $credentials Optional. User info in order to sign on. |
23 * @param string|bool $secure_cookie Optional. Whether to use secure cookie. |
30 * @param string|bool $secure_cookie Optional. Whether to use secure cookie. |
24 * @return WP_User|WP_Error WP_User on success, WP_Error on failure. |
31 * @return WP_User|WP_Error WP_User on success, WP_Error on failure. |
25 */ |
32 */ |
26 function wp_signon( $credentials = array(), $secure_cookie = '' ) { |
33 function wp_signon( $credentials = array(), $secure_cookie = '' ) { |
27 if ( empty($credentials) ) { |
34 if ( empty($credentials) ) { |
35 $credentials = array(); // Back-compat for plugins passing an empty string. |
|
36 |
|
28 if ( ! empty($_POST['log']) ) |
37 if ( ! empty($_POST['log']) ) |
29 $credentials['user_login'] = $_POST['log']; |
38 $credentials['user_login'] = $_POST['log']; |
30 if ( ! empty($_POST['pwd']) ) |
39 if ( ! empty($_POST['pwd']) ) |
31 $credentials['user_password'] = $_POST['pwd']; |
40 $credentials['user_password'] = $_POST['pwd']; |
32 if ( ! empty($_POST['rememberme']) ) |
41 if ( ! empty($_POST['rememberme']) ) |
46 * |
55 * |
47 * @since 1.5.1 |
56 * @since 1.5.1 |
48 * |
57 * |
49 * @todo Decide whether to deprecate the wp_authenticate action. |
58 * @todo Decide whether to deprecate the wp_authenticate action. |
50 * |
59 * |
51 * @param string $user_login Username, passed by reference. |
60 * @param string $user_login Username (passed by reference). |
52 * @param string $user_password User password, passed by reference. |
61 * @param string $user_password User password (passed by reference). |
53 */ |
62 */ |
54 do_action_ref_array( 'wp_authenticate', array( &$credentials['user_login'], &$credentials['user_password'] ) ); |
63 do_action_ref_array( 'wp_authenticate', array( &$credentials['user_login'], &$credentials['user_password'] ) ); |
55 |
64 |
56 if ( '' === $secure_cookie ) |
65 if ( '' === $secure_cookie ) |
57 $secure_cookie = is_ssl(); |
66 $secure_cookie = is_ssl(); |
58 |
67 |
59 /** |
68 /** |
60 * Filter whether to use a secure sign-on cookie. |
69 * Filters whether to use a secure sign-on cookie. |
61 * |
70 * |
62 * @since 3.1.0 |
71 * @since 3.1.0 |
63 * |
72 * |
64 * @param bool $secure_cookie Whether to use a secure sign-on cookie. |
73 * @param bool $secure_cookie Whether to use a secure sign-on cookie. |
65 * @param array $credentials { |
74 * @param array $credentials { |
100 do_action( 'wp_login', $user->user_login, $user ); |
109 do_action( 'wp_login', $user->user_login, $user ); |
101 return $user; |
110 return $user; |
102 } |
111 } |
103 |
112 |
104 /** |
113 /** |
105 * Authenticate the user using the username and password. |
114 * Authenticate a user, confirming the username and password are valid. |
106 * |
115 * |
107 * @since 2.8.0 |
116 * @since 2.8.0 |
108 * |
117 * |
109 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. |
118 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. |
110 * @param string $username Username for authentication. |
119 * @param string $username Username for authentication. |
131 return $error; |
140 return $error; |
132 } |
141 } |
133 |
142 |
134 $user = get_user_by('login', $username); |
143 $user = get_user_by('login', $username); |
135 |
144 |
136 if ( !$user ) |
145 if ( !$user ) { |
137 return new WP_Error( 'invalid_username', sprintf( __( '<strong>ERROR</strong>: Invalid username. <a href="%s">Lost your password?</a>' ), wp_lostpassword_url() ) ); |
146 return new WP_Error( 'invalid_username', |
138 |
147 __( '<strong>ERROR</strong>: Invalid username.' ) . |
139 /** |
148 ' <a href="' . wp_lostpassword_url() . '">' . |
140 * Filter whether the given user can be authenticated with the provided $password. |
149 __( 'Lost your password?' ) . |
150 '</a>' |
|
151 ); |
|
152 } |
|
153 |
|
154 /** |
|
155 * Filters whether the given user can be authenticated with the provided $password. |
|
141 * |
156 * |
142 * @since 2.5.0 |
157 * @since 2.5.0 |
143 * |
158 * |
144 * @param WP_User|WP_Error $user WP_User or WP_Error object if a previous |
159 * @param WP_User|WP_Error $user WP_User or WP_Error object if a previous |
145 * callback failed authentication. |
160 * callback failed authentication. |
147 */ |
162 */ |
148 $user = apply_filters( 'wp_authenticate_user', $user, $password ); |
163 $user = apply_filters( 'wp_authenticate_user', $user, $password ); |
149 if ( is_wp_error($user) ) |
164 if ( is_wp_error($user) ) |
150 return $user; |
165 return $user; |
151 |
166 |
152 if ( !wp_check_password($password, $user->user_pass, $user->ID) ) |
167 if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) { |
153 return new WP_Error( 'incorrect_password', sprintf( __( '<strong>ERROR</strong>: The password you entered for the username <strong>%1$s</strong> is incorrect. <a href="%2$s">Lost your password?</a>' ), |
168 return new WP_Error( 'incorrect_password', |
154 $username, wp_lostpassword_url() ) ); |
169 sprintf( |
170 /* translators: %s: user name */ |
|
171 __( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ), |
|
172 '<strong>' . $username . '</strong>' |
|
173 ) . |
|
174 ' <a href="' . wp_lostpassword_url() . '">' . |
|
175 __( 'Lost your password?' ) . |
|
176 '</a>' |
|
177 ); |
|
178 } |
|
155 |
179 |
156 return $user; |
180 return $user; |
157 } |
181 } |
158 |
182 |
159 /** |
183 /** |
184 * Authenticates a user using the email and password. |
|
185 * |
|
186 * @since 4.5.0 |
|
187 * |
|
188 * @param WP_User|WP_Error|null $user WP_User or WP_Error object if a previous |
|
189 * callback failed authentication. |
|
190 * @param string $email Email address for authentication. |
|
191 * @param string $password Password for authentication. |
|
192 * @return WP_User|WP_Error WP_User on success, WP_Error on failure. |
|
193 */ |
|
194 function wp_authenticate_email_password( $user, $email, $password ) { |
|
195 if ( $user instanceof WP_User ) { |
|
196 return $user; |
|
197 } |
|
198 |
|
199 if ( empty( $email ) || empty( $password ) ) { |
|
200 if ( is_wp_error( $user ) ) { |
|
201 return $user; |
|
202 } |
|
203 |
|
204 $error = new WP_Error(); |
|
205 |
|
206 if ( empty( $email ) ) { |
|
207 $error->add( 'empty_username', __( '<strong>ERROR</strong>: The email field is empty.' ) ); // Uses 'empty_username' for back-compat with wp_signon() |
|
208 } |
|
209 |
|
210 if ( empty( $password ) ) { |
|
211 $error->add( 'empty_password', __( '<strong>ERROR</strong>: The password field is empty.' ) ); |
|
212 } |
|
213 |
|
214 return $error; |
|
215 } |
|
216 |
|
217 if ( ! is_email( $email ) ) { |
|
218 return $user; |
|
219 } |
|
220 |
|
221 $user = get_user_by( 'email', $email ); |
|
222 |
|
223 if ( ! $user ) { |
|
224 return new WP_Error( 'invalid_email', |
|
225 __( '<strong>ERROR</strong>: Invalid email address.' ) . |
|
226 ' <a href="' . wp_lostpassword_url() . '">' . |
|
227 __( 'Lost your password?' ) . |
|
228 '</a>' |
|
229 ); |
|
230 } |
|
231 |
|
232 /** This filter is documented in wp-includes/user.php */ |
|
233 $user = apply_filters( 'wp_authenticate_user', $user, $password ); |
|
234 |
|
235 if ( is_wp_error( $user ) ) { |
|
236 return $user; |
|
237 } |
|
238 |
|
239 if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) { |
|
240 return new WP_Error( 'incorrect_password', |
|
241 sprintf( |
|
242 /* translators: %s: email address */ |
|
243 __( '<strong>ERROR</strong>: The password you entered for the email address %s is incorrect.' ), |
|
244 '<strong>' . $email . '</strong>' |
|
245 ) . |
|
246 ' <a href="' . wp_lostpassword_url() . '">' . |
|
247 __( 'Lost your password?' ) . |
|
248 '</a>' |
|
249 ); |
|
250 } |
|
251 |
|
252 return $user; |
|
253 } |
|
254 |
|
255 /** |
|
160 * Authenticate the user using the WordPress auth cookie. |
256 * Authenticate the user using the WordPress auth cookie. |
161 * |
257 * |
162 * @since 2.8.0 |
258 * @since 2.8.0 |
259 * |
|
260 * @global string $auth_secure_cookie |
|
163 * |
261 * |
164 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. |
262 * @param WP_User|WP_Error|null $user WP_User or WP_Error object from a previous callback. Default null. |
165 * @param string $username Username. If not empty, cancels the cookie authentication. |
263 * @param string $username Username. If not empty, cancels the cookie authentication. |
166 * @param string $password Password. If not empty, cancels the cookie authentication. |
264 * @param string $password Password. If not empty, cancels the cookie authentication. |
167 * @return WP_User|WP_Error WP_User on success, WP_Error on failure. |
265 * @return WP_User|WP_Error WP_User on success, WP_Error on failure. |
202 * @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer. |
300 * @return WP_User|WP_Error WP_User on success, WP_Error if the user is considered a spammer. |
203 */ |
301 */ |
204 function wp_authenticate_spam_check( $user ) { |
302 function wp_authenticate_spam_check( $user ) { |
205 if ( $user instanceof WP_User && is_multisite() ) { |
303 if ( $user instanceof WP_User && is_multisite() ) { |
206 /** |
304 /** |
207 * Filter whether the user has been marked as a spammer. |
305 * Filters whether the user has been marked as a spammer. |
208 * |
306 * |
209 * @since 3.7.0 |
307 * @since 3.7.0 |
210 * |
308 * |
211 * @param bool $spammed Whether the user is considered a spammer. |
309 * @param bool $spammed Whether the user is considered a spammer. |
212 * @param WP_User $user User to check against. |
310 * @param WP_User $user User to check against. |
213 */ |
311 */ |
214 $spammed = apply_filters( 'check_is_user_spammed', is_user_spammy(), $user ); |
312 $spammed = apply_filters( 'check_is_user_spammed', is_user_spammy( $user ), $user ); |
215 |
313 |
216 if ( $spammed ) |
314 if ( $spammed ) |
217 return new WP_Error( 'spammer_account', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.' ) ); |
315 return new WP_Error( 'spammer_account', __( '<strong>ERROR</strong>: Your account has been marked as a spammer.' ) ); |
218 } |
316 } |
219 return $user; |
317 return $user; |
220 } |
318 } |
221 |
319 |
222 /** |
320 /** |
223 * Validate the logged-in cookie. |
321 * Validates the logged-in cookie. |
224 * |
322 * |
225 * Checks the logged-in cookie if the previous auth cookie could not be |
323 * Checks the logged-in cookie if the previous auth cookie could not be |
226 * validated and parsed. |
324 * validated and parsed. |
227 * |
325 * |
228 * This is a callback for the determine_current_user filter, rather than API. |
326 * This is a callback for the {@see 'determine_current_user'} filter, rather than API. |
229 * |
327 * |
230 * @since 3.9.0 |
328 * @since 3.9.0 |
231 * |
329 * |
232 * @param int|bool $user_id The user ID (or false) as received from the |
330 * @param int|bool $user_id The user ID (or false) as received from the |
233 * determine_current_user filter. |
331 * determine_current_user filter. |
234 * @return int|bool User ID if validated, false otherwise. If a user ID from |
332 * @return int|false User ID if validated, false otherwise. If a user ID from |
235 * an earlier filter callback is received, that value is returned. |
333 * an earlier filter callback is received, that value is returned. |
236 */ |
334 */ |
237 function wp_validate_logged_in_cookie( $user_id ) { |
335 function wp_validate_logged_in_cookie( $user_id ) { |
238 if ( $user_id ) { |
336 if ( $user_id ) { |
239 return $user_id; |
337 return $user_id; |
240 } |
338 } |
249 /** |
347 /** |
250 * Number of posts user has written. |
348 * Number of posts user has written. |
251 * |
349 * |
252 * @since 3.0.0 |
350 * @since 3.0.0 |
253 * @since 4.1.0 Added `$post_type` argument. |
351 * @since 4.1.0 Added `$post_type` argument. |
254 * |
352 * @since 4.3.0 Added `$public_only` argument. Added the ability to pass an array |
255 * @global wpdb $wpdb WordPress database object for queries. |
353 * of post types to `$post_type`. |
256 * |
354 * |
257 * @param int $userid User ID. |
355 * @global wpdb $wpdb WordPress database abstraction object. |
258 * @param string $post_type Optional. Post type to count the number of posts for. Default 'post'. |
356 * |
259 * @return int Number of posts the user has written in this post type. |
357 * @param int $userid User ID. |
260 */ |
358 * @param array|string $post_type Optional. Single post type or array of post types to count the number of posts for. Default 'post'. |
261 function count_user_posts( $userid, $post_type = 'post' ) { |
359 * @param bool $public_only Optional. Whether to only return counts for public posts. Default false. |
360 * @return string Number of posts the user has written in this post type. |
|
361 */ |
|
362 function count_user_posts( $userid, $post_type = 'post', $public_only = false ) { |
|
262 global $wpdb; |
363 global $wpdb; |
263 |
364 |
264 $where = get_posts_by_author_sql( $post_type, true, $userid ); |
365 $where = get_posts_by_author_sql( $post_type, true, $userid, $public_only ); |
265 |
366 |
266 $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" ); |
367 $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" ); |
267 |
368 |
268 /** |
369 /** |
269 * Filter the number of posts a user has written. |
370 * Filters the number of posts a user has written. |
270 * |
371 * |
271 * @since 2.7.0 |
372 * @since 2.7.0 |
272 * @since 4.1.0 Added `$post_type` argument. |
373 * @since 4.1.0 Added `$post_type` argument. |
273 * |
374 * @since 4.3.1 Added `$public_only` argument. |
274 * @param int $count The user's post count. |
375 * |
275 * @param int $userid User ID. |
376 * @param int $count The user's post count. |
276 * @param string $post_type Post type to count the number of posts for. |
377 * @param int $userid User ID. |
277 */ |
378 * @param string|array $post_type Single post type or array of post types to count the number of posts for. |
278 return apply_filters( 'get_usernumposts', $count, $userid, $post_type ); |
379 * @param bool $public_only Whether to limit counted posts to public posts. |
380 */ |
|
381 return apply_filters( 'get_usernumposts', $count, $userid, $post_type, $public_only ); |
|
279 } |
382 } |
280 |
383 |
281 /** |
384 /** |
282 * Number of posts written by a list of users. |
385 * Number of posts written by a list of users. |
283 * |
386 * |
284 * @since 3.0.0 |
387 * @since 3.0.0 |
285 * |
388 * |
286 * @param array $users Array of user IDs. |
389 * @global wpdb $wpdb WordPress database abstraction object. |
287 * @param string $post_type Optional. Post type to check. Defaults to post. |
390 * |
288 * @param bool $public_only Optional. Only return counts for public posts. Defaults to false. |
391 * @param array $users Array of user IDs. |
392 * @param string|array $post_type Optional. Single post type or array of post types to check. Defaults to 'post'. |
|
393 * @param bool $public_only Optional. Only return counts for public posts. Defaults to false. |
|
289 * @return array Amount of posts each user has written. |
394 * @return array Amount of posts each user has written. |
290 */ |
395 */ |
291 function count_many_users_posts( $users, $post_type = 'post', $public_only = false ) { |
396 function count_many_users_posts( $users, $post_type = 'post', $public_only = false ) { |
292 global $wpdb; |
397 global $wpdb; |
293 |
398 |
316 // |
421 // |
317 |
422 |
318 /** |
423 /** |
319 * Get the current user's ID |
424 * Get the current user's ID |
320 * |
425 * |
321 * @since MU |
426 * @since MU (3.0.0) |
322 * |
427 * |
323 * @return int The current user's ID |
428 * @return int The current user's ID, or 0 if no user is logged in. |
324 */ |
429 */ |
325 function get_current_user_id() { |
430 function get_current_user_id() { |
326 if ( ! function_exists( 'wp_get_current_user' ) ) |
431 if ( ! function_exists( 'wp_get_current_user' ) ) |
327 return 0; |
432 return 0; |
328 $user = wp_get_current_user(); |
433 $user = wp_get_current_user(); |
339 * |
444 * |
340 * The option will first check for the per site name and then the per Network name. |
445 * The option will first check for the per site name and then the per Network name. |
341 * |
446 * |
342 * @since 2.0.0 |
447 * @since 2.0.0 |
343 * |
448 * |
344 * @global wpdb $wpdb WordPress database object for queries. |
449 * @global wpdb $wpdb WordPress database abstraction object. |
345 * |
450 * |
346 * @param string $option User option name. |
451 * @param string $option User option name. |
347 * @param int $user Optional. User ID. |
452 * @param int $user Optional. User ID. |
348 * @param string $deprecated Use get_option() to check for an option in the options table. |
453 * @param string $deprecated Use get_option() to check for an option in the options table. |
349 * @return mixed User option value on success, false on failure. |
454 * @return mixed User option value on success, false on failure. |
350 */ |
455 */ |
351 function get_user_option( $option, $user = 0, $deprecated = '' ) { |
456 function get_user_option( $option, $user = 0, $deprecated = '' ) { |
352 global $wpdb; |
457 global $wpdb; |
353 |
458 |
354 if ( !empty( $deprecated ) ) |
459 if ( !empty( $deprecated ) ) |
355 _deprecated_argument( __FUNCTION__, '3.0' ); |
460 _deprecated_argument( __FUNCTION__, '3.0.0' ); |
356 |
461 |
357 if ( empty( $user ) ) |
462 if ( empty( $user ) ) |
358 $user = get_current_user_id(); |
463 $user = get_current_user_id(); |
359 |
464 |
360 if ( ! $user = get_userdata( $user ) ) |
465 if ( ! $user = get_userdata( $user ) ) |
367 $result = $user->get( $option ); |
472 $result = $user->get( $option ); |
368 else |
473 else |
369 $result = false; |
474 $result = false; |
370 |
475 |
371 /** |
476 /** |
372 * Filter a specific user option value. |
477 * Filters a specific user option value. |
373 * |
478 * |
374 * The dynamic portion of the hook name, `$option`, refers to the user option name. |
479 * The dynamic portion of the hook name, `$option`, refers to the user option name. |
375 * |
480 * |
376 * @since 2.5.0 |
481 * @since 2.5.0 |
377 * |
482 * |
391 * |
496 * |
392 * Deletes the user option if $newvalue is empty. |
497 * Deletes the user option if $newvalue is empty. |
393 * |
498 * |
394 * @since 2.0.0 |
499 * @since 2.0.0 |
395 * |
500 * |
396 * @global wpdb $wpdb WordPress database object for queries. |
501 * @global wpdb $wpdb WordPress database abstraction object. |
397 * |
502 * |
398 * @param int $user_id User ID. |
503 * @param int $user_id User ID. |
399 * @param string $option_name User option name. |
504 * @param string $option_name User option name. |
400 * @param mixed $newvalue User option value. |
505 * @param mixed $newvalue User option value. |
401 * @param bool $global Optional. Whether option name is global or blog specific. |
506 * @param bool $global Optional. Whether option name is global or blog specific. |
419 * global blog options. If the 'global' parameter is false, which it is by default |
524 * global blog options. If the 'global' parameter is false, which it is by default |
420 * it will prepend the WordPress table prefix to the option name. |
525 * it will prepend the WordPress table prefix to the option name. |
421 * |
526 * |
422 * @since 3.0.0 |
527 * @since 3.0.0 |
423 * |
528 * |
424 * @global wpdb $wpdb WordPress database object for queries. |
529 * @global wpdb $wpdb WordPress database abstraction object. |
425 * |
530 * |
426 * @param int $user_id User ID |
531 * @param int $user_id User ID |
427 * @param string $option_name User option name. |
532 * @param string $option_name User option name. |
428 * @param bool $global Optional. Whether option name is global or blog specific. |
533 * @param bool $global Optional. Whether option name is global or blog specific. |
429 * Default false (blog specific). |
534 * Default false (blog specific). |
436 $option_name = $wpdb->get_blog_prefix() . $option_name; |
541 $option_name = $wpdb->get_blog_prefix() . $option_name; |
437 return delete_user_meta( $user_id, $option_name ); |
542 return delete_user_meta( $user_id, $option_name ); |
438 } |
543 } |
439 |
544 |
440 /** |
545 /** |
441 * WordPress User Query class. |
546 * Retrieve list of users matching criteria. |
442 * |
547 * |
443 * @since 3.1.0 |
548 * @since 3.1.0 |
444 * |
549 * |
445 * @see WP_User_Query::prepare_query() for information on accepted arguments. |
|
446 */ |
|
447 class WP_User_Query { |
|
448 |
|
449 /** |
|
450 * Query vars, after parsing |
|
451 * |
|
452 * @since 3.5.0 |
|
453 * @access public |
|
454 * @var array |
|
455 */ |
|
456 public $query_vars = array(); |
|
457 |
|
458 /** |
|
459 * List of found user ids |
|
460 * |
|
461 * @since 3.1.0 |
|
462 * @access private |
|
463 * @var array |
|
464 */ |
|
465 private $results; |
|
466 |
|
467 /** |
|
468 * Total number of found users for the current query |
|
469 * |
|
470 * @since 3.1.0 |
|
471 * @access private |
|
472 * @var int |
|
473 */ |
|
474 private $total_users = 0; |
|
475 |
|
476 /** |
|
477 * Metadata query container. |
|
478 * |
|
479 * @since 4.2.0 |
|
480 * @access public |
|
481 * @var object WP_Meta_Query |
|
482 */ |
|
483 public $meta_query = false; |
|
484 |
|
485 private $compat_fields = array( 'results', 'total_users' ); |
|
486 |
|
487 // SQL clauses |
|
488 public $query_fields; |
|
489 public $query_from; |
|
490 public $query_where; |
|
491 public $query_orderby; |
|
492 public $query_limit; |
|
493 |
|
494 /** |
|
495 * PHP5 constructor. |
|
496 * |
|
497 * @since 3.1.0 |
|
498 * |
|
499 * @param null|string|array $args Optional. The query variables. |
|
500 */ |
|
501 public function __construct( $query = null ) { |
|
502 if ( ! empty( $query ) ) { |
|
503 $this->prepare_query( $query ); |
|
504 $this->query(); |
|
505 } |
|
506 } |
|
507 |
|
508 /** |
|
509 * Prepare the query variables. |
|
510 * |
|
511 * @since 3.1.0 |
|
512 * @since 4.2.0 Added 'meta_value_num' support for `$orderby` parameter. Added multi-dimensional array syntax |
|
513 * for `$orderby` parameter. |
|
514 * @access public |
|
515 * |
|
516 * @param string|array $query { |
|
517 * Optional. Array or string of Query parameters. |
|
518 * |
|
519 * @type int $blog_id The site ID. Default is the global blog id. |
|
520 * @type string $role Role name. Default empty. |
|
521 * @type string $meta_key User meta key. Default empty. |
|
522 * @type string $meta_value User meta value. Default empty. |
|
523 * @type string $meta_compare Comparison operator to test the `$meta_value`. Accepts '=', '!=', |
|
524 * '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', |
|
525 * 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS', 'REGEXP', 'NOT REGEXP', |
|
526 * or 'RLIKE'. Default '='. |
|
527 * @type array $include An array of user IDs to include. Default empty array. |
|
528 * @type array $exclude An array of user IDs to exclude. Default empty array. |
|
529 * @type string $search Search keyword. Searches for possible string matches on columns. |
|
530 * When `$search_columns` is left empty, it tries to determine which |
|
531 * column to search in based on search string. Default empty. |
|
532 * @type array $search_columns Array of column names to be searched. Accepts 'ID', 'login', |
|
533 * 'nicename', 'email', 'url'. Default empty array. |
|
534 * @type string|array $orderby Field(s) to sort the retrieved users by. May be a single value, |
|
535 * an array of values, or a multi-dimensional array with fields as keys |
|
536 * and orders ('ASC' or 'DESC') as values. Accepted values are'ID', |
|
537 * 'display_name' (or 'name'), 'user_login' (or 'login'), |
|
538 * 'user_nicename' (or 'nicename'), 'user_email' (or 'email'), |
|
539 * 'user_url' (or 'url'), 'user_registered' (or 'registered'), |
|
540 * 'post_count', 'meta_value', 'meta_value_num', the value of |
|
541 * `$meta_key`, or an array key of `$meta_query`. To use 'meta_value' |
|
542 * or 'meta_value_num', `$meta_key` must be also be defined. |
|
543 * Default 'user_login'. |
|
544 * @type string $order Designates ascending or descending order of users. Order values |
|
545 * passed as part of an `$orderby` array take precedence over this |
|
546 * parameter. Accepts 'ASC', 'DESC'. Default 'ASC'. |
|
547 * @type int $offset Number of users to offset in retrieved results. Can be used in |
|
548 * conjunction with pagination. Default 0. |
|
549 * @type int $number Number of users to limit the query for. Can be used in conjunction |
|
550 * with pagination. Value -1 (all) is not supported. |
|
551 * Default empty (all users). |
|
552 * @type bool $count_total Whether to count the total number of users found. If pagination is not |
|
553 * needed, setting this to false can improve performance. Default true. |
|
554 * @type string|array $fields Which fields to return. Single or all fields (string), or array |
|
555 * of fields. Accepts 'ID', 'display_name', 'login', 'nicename', 'email', |
|
556 * 'url', 'registered'. Use 'all' for all fields and 'all_with_meta' to |
|
557 * include meta fields. Default 'all'. |
|
558 * @type string $who Type of users to query. Accepts 'authors'. Default empty (all users). |
|
559 * } |
|
560 */ |
|
561 public function prepare_query( $query = array() ) { |
|
562 global $wpdb; |
|
563 |
|
564 if ( empty( $this->query_vars ) || ! empty( $query ) ) { |
|
565 $this->query_limit = null; |
|
566 $this->query_vars = wp_parse_args( $query, array( |
|
567 'blog_id' => $GLOBALS['blog_id'], |
|
568 'role' => '', |
|
569 'meta_key' => '', |
|
570 'meta_value' => '', |
|
571 'meta_compare' => '', |
|
572 'include' => array(), |
|
573 'exclude' => array(), |
|
574 'search' => '', |
|
575 'search_columns' => array(), |
|
576 'orderby' => 'login', |
|
577 'order' => 'ASC', |
|
578 'offset' => '', |
|
579 'number' => '', |
|
580 'count_total' => true, |
|
581 'fields' => 'all', |
|
582 'who' => '' |
|
583 ) ); |
|
584 } |
|
585 |
|
586 /** |
|
587 * Fires before the WP_User_Query has been parsed. |
|
588 * |
|
589 * The passed WP_User_Query object contains the query variables, not |
|
590 * yet passed into SQL. |
|
591 * |
|
592 * @since 4.0.0 |
|
593 * |
|
594 * @param WP_User_Query $this The current WP_User_Query instance, |
|
595 * passed by reference. |
|
596 */ |
|
597 do_action( 'pre_get_users', $this ); |
|
598 |
|
599 $qv =& $this->query_vars; |
|
600 |
|
601 if ( is_array( $qv['fields'] ) ) { |
|
602 $qv['fields'] = array_unique( $qv['fields'] ); |
|
603 |
|
604 $this->query_fields = array(); |
|
605 foreach ( $qv['fields'] as $field ) { |
|
606 $field = 'ID' === $field ? 'ID' : sanitize_key( $field ); |
|
607 $this->query_fields[] = "$wpdb->users.$field"; |
|
608 } |
|
609 $this->query_fields = implode( ',', $this->query_fields ); |
|
610 } elseif ( 'all' == $qv['fields'] ) { |
|
611 $this->query_fields = "$wpdb->users.*"; |
|
612 } else { |
|
613 $this->query_fields = "$wpdb->users.ID"; |
|
614 } |
|
615 |
|
616 if ( isset( $qv['count_total'] ) && $qv['count_total'] ) |
|
617 $this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields; |
|
618 |
|
619 $this->query_from = "FROM $wpdb->users"; |
|
620 $this->query_where = "WHERE 1=1"; |
|
621 |
|
622 // Parse and sanitize 'include', for use by 'orderby' as well as 'include' below. |
|
623 if ( ! empty( $qv['include'] ) ) { |
|
624 $include = wp_parse_id_list( $qv['include'] ); |
|
625 } else { |
|
626 $include = false; |
|
627 } |
|
628 |
|
629 $blog_id = 0; |
|
630 if ( isset( $qv['blog_id'] ) ) { |
|
631 $blog_id = absint( $qv['blog_id'] ); |
|
632 } |
|
633 |
|
634 if ( isset( $qv['who'] ) && 'authors' == $qv['who'] && $blog_id ) { |
|
635 $qv['meta_key'] = $wpdb->get_blog_prefix( $blog_id ) . 'user_level'; |
|
636 $qv['meta_value'] = 0; |
|
637 $qv['meta_compare'] = '!='; |
|
638 $qv['blog_id'] = $blog_id = 0; // Prevent extra meta query |
|
639 } |
|
640 |
|
641 // Meta query. |
|
642 $this->meta_query = new WP_Meta_Query(); |
|
643 $this->meta_query->parse_query_vars( $qv ); |
|
644 |
|
645 $role = ''; |
|
646 if ( isset( $qv['role'] ) ) { |
|
647 $role = trim( $qv['role'] ); |
|
648 } |
|
649 |
|
650 if ( $blog_id && ( $role || is_multisite() ) ) { |
|
651 $cap_meta_query = array(); |
|
652 $cap_meta_query['key'] = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities'; |
|
653 |
|
654 if ( $role ) { |
|
655 $cap_meta_query['value'] = '"' . $role . '"'; |
|
656 $cap_meta_query['compare'] = 'like'; |
|
657 } |
|
658 |
|
659 if ( empty( $this->meta_query->queries ) ) { |
|
660 $this->meta_query->queries = array( $cap_meta_query ); |
|
661 } elseif ( ! in_array( $cap_meta_query, $this->meta_query->queries, true ) ) { |
|
662 // Append the cap query to the original queries and reparse the query. |
|
663 $this->meta_query->queries = array( |
|
664 'relation' => 'AND', |
|
665 array( $this->meta_query->queries, $cap_meta_query ), |
|
666 ); |
|
667 } |
|
668 |
|
669 $this->meta_query->parse_query_vars( $this->meta_query->queries ); |
|
670 } |
|
671 |
|
672 if ( ! empty( $this->meta_query->queries ) ) { |
|
673 $clauses = $this->meta_query->get_sql( 'user', $wpdb->users, 'ID', $this ); |
|
674 $this->query_from .= $clauses['join']; |
|
675 $this->query_where .= $clauses['where']; |
|
676 |
|
677 if ( 'OR' == $this->meta_query->relation ) { |
|
678 $this->query_fields = 'DISTINCT ' . $this->query_fields; |
|
679 } |
|
680 } |
|
681 |
|
682 // sorting |
|
683 $qv['order'] = isset( $qv['order'] ) ? strtoupper( $qv['order'] ) : ''; |
|
684 $order = $this->parse_order( $qv['order'] ); |
|
685 |
|
686 if ( empty( $qv['orderby'] ) ) { |
|
687 // Default order is by 'user_login'. |
|
688 $ordersby = array( 'user_login' => $order ); |
|
689 } else if ( is_array( $qv['orderby'] ) ) { |
|
690 $ordersby = $qv['orderby']; |
|
691 } else { |
|
692 // 'orderby' values may be a comma- or space-separated list. |
|
693 $ordersby = preg_split( '/[,\s]+/', $qv['orderby'] ); |
|
694 } |
|
695 |
|
696 $orderby_array = array(); |
|
697 foreach ( $ordersby as $_key => $_value ) { |
|
698 if ( ! $_value ) { |
|
699 continue; |
|
700 } |
|
701 |
|
702 if ( is_int( $_key ) ) { |
|
703 // Integer key means this is a flat array of 'orderby' fields. |
|
704 $_orderby = $_value; |
|
705 $_order = $order; |
|
706 } else { |
|
707 // Non-integer key means this the key is the field and the value is ASC/DESC. |
|
708 $_orderby = $_key; |
|
709 $_order = $_value; |
|
710 } |
|
711 |
|
712 $parsed = $this->parse_orderby( $_orderby ); |
|
713 |
|
714 if ( ! $parsed ) { |
|
715 continue; |
|
716 } |
|
717 |
|
718 $orderby_array[] = $parsed . ' ' . $this->parse_order( $_order ); |
|
719 } |
|
720 |
|
721 // If no valid clauses were found, order by user_login. |
|
722 if ( empty( $orderby_array ) ) { |
|
723 $orderby_array[] = "user_login $order"; |
|
724 } |
|
725 |
|
726 $this->query_orderby = 'ORDER BY ' . implode( ', ', $orderby_array ); |
|
727 |
|
728 // limit |
|
729 if ( isset( $qv['number'] ) && $qv['number'] ) { |
|
730 if ( $qv['offset'] ) |
|
731 $this->query_limit = $wpdb->prepare("LIMIT %d, %d", $qv['offset'], $qv['number']); |
|
732 else |
|
733 $this->query_limit = $wpdb->prepare("LIMIT %d", $qv['number']); |
|
734 } |
|
735 |
|
736 $search = ''; |
|
737 if ( isset( $qv['search'] ) ) |
|
738 $search = trim( $qv['search'] ); |
|
739 |
|
740 if ( $search ) { |
|
741 $leading_wild = ( ltrim($search, '*') != $search ); |
|
742 $trailing_wild = ( rtrim($search, '*') != $search ); |
|
743 if ( $leading_wild && $trailing_wild ) |
|
744 $wild = 'both'; |
|
745 elseif ( $leading_wild ) |
|
746 $wild = 'leading'; |
|
747 elseif ( $trailing_wild ) |
|
748 $wild = 'trailing'; |
|
749 else |
|
750 $wild = false; |
|
751 if ( $wild ) |
|
752 $search = trim($search, '*'); |
|
753 |
|
754 $search_columns = array(); |
|
755 if ( $qv['search_columns'] ) |
|
756 $search_columns = array_intersect( $qv['search_columns'], array( 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename' ) ); |
|
757 if ( ! $search_columns ) { |
|
758 if ( false !== strpos( $search, '@') ) |
|
759 $search_columns = array('user_email'); |
|
760 elseif ( is_numeric($search) ) |
|
761 $search_columns = array('user_login', 'ID'); |
|
762 elseif ( preg_match('|^https?://|', $search) && ! ( is_multisite() && wp_is_large_network( 'users' ) ) ) |
|
763 $search_columns = array('user_url'); |
|
764 else |
|
765 $search_columns = array('user_login', 'user_nicename'); |
|
766 } |
|
767 |
|
768 /** |
|
769 * Filter the columns to search in a WP_User_Query search. |
|
770 * |
|
771 * The default columns depend on the search term, and include 'user_email', |
|
772 * 'user_login', 'ID', 'user_url', and 'user_nicename'. |
|
773 * |
|
774 * @since 3.6.0 |
|
775 * |
|
776 * @param array $search_columns Array of column names to be searched. |
|
777 * @param string $search Text being searched. |
|
778 * @param WP_User_Query $this The current WP_User_Query instance. |
|
779 */ |
|
780 $search_columns = apply_filters( 'user_search_columns', $search_columns, $search, $this ); |
|
781 |
|
782 $this->query_where .= $this->get_search_sql( $search, $search_columns, $wild ); |
|
783 } |
|
784 |
|
785 if ( ! empty( $include ) ) { |
|
786 // Sanitized earlier. |
|
787 $ids = implode( ',', $include ); |
|
788 $this->query_where .= " AND $wpdb->users.ID IN ($ids)"; |
|
789 } elseif ( ! empty( $qv['exclude'] ) ) { |
|
790 $ids = implode( ',', wp_parse_id_list( $qv['exclude'] ) ); |
|
791 $this->query_where .= " AND $wpdb->users.ID NOT IN ($ids)"; |
|
792 } |
|
793 |
|
794 // Date queries are allowed for the user_registered field. |
|
795 if ( ! empty( $qv['date_query'] ) && is_array( $qv['date_query'] ) ) { |
|
796 $date_query = new WP_Date_Query( $qv['date_query'], 'user_registered' ); |
|
797 $this->query_where .= $date_query->get_sql(); |
|
798 } |
|
799 |
|
800 /** |
|
801 * Fires after the WP_User_Query has been parsed, and before |
|
802 * the query is executed. |
|
803 * |
|
804 * The passed WP_User_Query object contains SQL parts formed |
|
805 * from parsing the given query. |
|
806 * |
|
807 * @since 3.1.0 |
|
808 * |
|
809 * @param WP_User_Query $this The current WP_User_Query instance, |
|
810 * passed by reference. |
|
811 */ |
|
812 do_action_ref_array( 'pre_user_query', array( &$this ) ); |
|
813 } |
|
814 |
|
815 /** |
|
816 * Execute the query, with the current variables. |
|
817 * |
|
818 * @since 3.1.0 |
|
819 * |
|
820 * @global wpdb $wpdb WordPress database object for queries. |
|
821 */ |
|
822 public function query() { |
|
823 global $wpdb; |
|
824 |
|
825 $qv =& $this->query_vars; |
|
826 |
|
827 $query = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit"; |
|
828 |
|
829 if ( is_array( $qv['fields'] ) || 'all' == $qv['fields'] ) { |
|
830 $this->results = $wpdb->get_results( $query ); |
|
831 } else { |
|
832 $this->results = $wpdb->get_col( $query ); |
|
833 } |
|
834 |
|
835 /** |
|
836 * Filter SELECT FOUND_ROWS() query for the current WP_User_Query instance. |
|
837 * |
|
838 * @since 3.2.0 |
|
839 * |
|
840 * @global wpdb $wpdb WordPress database abstraction object. |
|
841 * |
|
842 * @param string $sql The SELECT FOUND_ROWS() query for the current WP_User_Query. |
|
843 */ |
|
844 if ( isset( $qv['count_total'] ) && $qv['count_total'] ) |
|
845 $this->total_users = $wpdb->get_var( apply_filters( 'found_users_query', 'SELECT FOUND_ROWS()' ) ); |
|
846 |
|
847 if ( !$this->results ) |
|
848 return; |
|
849 |
|
850 if ( 'all_with_meta' == $qv['fields'] ) { |
|
851 cache_users( $this->results ); |
|
852 |
|
853 $r = array(); |
|
854 foreach ( $this->results as $userid ) |
|
855 $r[ $userid ] = new WP_User( $userid, '', $qv['blog_id'] ); |
|
856 |
|
857 $this->results = $r; |
|
858 } elseif ( 'all' == $qv['fields'] ) { |
|
859 foreach ( $this->results as $key => $user ) { |
|
860 $this->results[ $key ] = new WP_User( $user, '', $qv['blog_id'] ); |
|
861 } |
|
862 } |
|
863 } |
|
864 |
|
865 /** |
|
866 * Retrieve query variable. |
|
867 * |
|
868 * @since 3.5.0 |
|
869 * @access public |
|
870 * |
|
871 * @param string $query_var Query variable key. |
|
872 * @return mixed |
|
873 */ |
|
874 public function get( $query_var ) { |
|
875 if ( isset( $this->query_vars[$query_var] ) ) |
|
876 return $this->query_vars[$query_var]; |
|
877 |
|
878 return null; |
|
879 } |
|
880 |
|
881 /** |
|
882 * Set query variable. |
|
883 * |
|
884 * @since 3.5.0 |
|
885 * @access public |
|
886 * |
|
887 * @param string $query_var Query variable key. |
|
888 * @param mixed $value Query variable value. |
|
889 */ |
|
890 public function set( $query_var, $value ) { |
|
891 $this->query_vars[$query_var] = $value; |
|
892 } |
|
893 |
|
894 /** |
|
895 * Used internally to generate an SQL string for searching across multiple columns |
|
896 * |
|
897 * @access protected |
|
898 * @since 3.1.0 |
|
899 * |
|
900 * @param string $string |
|
901 * @param array $cols |
|
902 * @param bool $wild Whether to allow wildcard searches. Default is false for Network Admin, true for |
|
903 * single site. Single site allows leading and trailing wildcards, Network Admin only trailing. |
|
904 * @return string |
|
905 */ |
|
906 protected function get_search_sql( $string, $cols, $wild = false ) { |
|
907 global $wpdb; |
|
908 |
|
909 $searches = array(); |
|
910 $leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : ''; |
|
911 $trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : ''; |
|
912 $like = $leading_wild . $wpdb->esc_like( $string ) . $trailing_wild; |
|
913 |
|
914 foreach ( $cols as $col ) { |
|
915 if ( 'ID' == $col ) { |
|
916 $searches[] = $wpdb->prepare( "$col = %s", $string ); |
|
917 } else { |
|
918 $searches[] = $wpdb->prepare( "$col LIKE %s", $like ); |
|
919 } |
|
920 } |
|
921 |
|
922 return ' AND (' . implode(' OR ', $searches) . ')'; |
|
923 } |
|
924 |
|
925 /** |
|
926 * Return the list of users. |
|
927 * |
|
928 * @since 3.1.0 |
|
929 * @access public |
|
930 * |
|
931 * @return array Array of results. |
|
932 */ |
|
933 public function get_results() { |
|
934 return $this->results; |
|
935 } |
|
936 |
|
937 /** |
|
938 * Return the total number of users for the current query. |
|
939 * |
|
940 * @since 3.1.0 |
|
941 * @access public |
|
942 * |
|
943 * @return int Number of total users. |
|
944 */ |
|
945 public function get_total() { |
|
946 return $this->total_users; |
|
947 } |
|
948 |
|
949 /** |
|
950 * Parse and sanitize 'orderby' keys passed to the user query. |
|
951 * |
|
952 * @since 4.2.0 |
|
953 * @access protected |
|
954 * |
|
955 * @global wpdb $wpdb WordPress database abstraction object. |
|
956 * |
|
957 * @param string $orderby Alias for the field to order by. |
|
958 * @return string|bool Value to used in the ORDER clause, if `$orderby` is valid. False otherwise. |
|
959 */ |
|
960 protected function parse_orderby( $orderby ) { |
|
961 global $wpdb; |
|
962 |
|
963 $meta_query_clauses = $this->meta_query->get_clauses(); |
|
964 |
|
965 $_orderby = ''; |
|
966 if ( in_array( $orderby, array( 'login', 'nicename', 'email', 'url', 'registered' ) ) ) { |
|
967 $_orderby = 'user_' . $orderby; |
|
968 } elseif ( in_array( $orderby, array( 'user_login', 'user_nicename', 'user_email', 'user_url', 'user_registered' ) ) ) { |
|
969 $_orderby = $orderby; |
|
970 } elseif ( 'name' == $orderby || 'display_name' == $orderby ) { |
|
971 $_orderby = 'display_name'; |
|
972 } elseif ( 'post_count' == $orderby ) { |
|
973 // todo: avoid the JOIN |
|
974 $where = get_posts_by_author_sql( 'post' ); |
|
975 $this->query_from .= " LEFT OUTER JOIN ( |
|
976 SELECT post_author, COUNT(*) as post_count |
|
977 FROM $wpdb->posts |
|
978 $where |
|
979 GROUP BY post_author |
|
980 ) p ON ({$wpdb->users}.ID = p.post_author) |
|
981 "; |
|
982 $_orderby = 'post_count'; |
|
983 } elseif ( 'ID' == $orderby || 'id' == $orderby ) { |
|
984 $_orderby = 'ID'; |
|
985 } elseif ( 'meta_value' == $orderby || $this->get( 'meta_key' ) == $orderby ) { |
|
986 $_orderby = "$wpdb->usermeta.meta_value"; |
|
987 } elseif ( 'meta_value_num' == $orderby ) { |
|
988 $_orderby = "$wpdb->usermeta.meta_value+0"; |
|
989 } elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) { |
|
990 $include = wp_parse_id_list( $this->query_vars['include'] ); |
|
991 $include_sql = implode( ',', $include ); |
|
992 $_orderby = "FIELD( $wpdb->users.ID, $include_sql )"; |
|
993 } elseif ( isset( $meta_query_clauses[ $orderby ] ) ) { |
|
994 $meta_clause = $meta_query_clauses[ $orderby ]; |
|
995 $_orderby = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) ); |
|
996 } |
|
997 |
|
998 return $_orderby; |
|
999 } |
|
1000 |
|
1001 /** |
|
1002 * Parse an 'order' query variable and cast it to ASC or DESC as necessary. |
|
1003 * |
|
1004 * @since 4.2.0 |
|
1005 * @access protected |
|
1006 * |
|
1007 * @param string $order The 'order' query variable. |
|
1008 * @return string The sanitized 'order' query variable. |
|
1009 */ |
|
1010 protected function parse_order( $order ) { |
|
1011 if ( ! is_string( $order ) || empty( $order ) ) { |
|
1012 return 'DESC'; |
|
1013 } |
|
1014 |
|
1015 if ( 'ASC' === strtoupper( $order ) ) { |
|
1016 return 'ASC'; |
|
1017 } else { |
|
1018 return 'DESC'; |
|
1019 } |
|
1020 } |
|
1021 |
|
1022 /** |
|
1023 * Make private properties readable for backwards compatibility. |
|
1024 * |
|
1025 * @since 4.0.0 |
|
1026 * @access public |
|
1027 * |
|
1028 * @param string $name Property to get. |
|
1029 * @return mixed Property. |
|
1030 */ |
|
1031 public function __get( $name ) { |
|
1032 if ( in_array( $name, $this->compat_fields ) ) { |
|
1033 return $this->$name; |
|
1034 } |
|
1035 } |
|
1036 |
|
1037 /** |
|
1038 * Make private properties settable for backwards compatibility. |
|
1039 * |
|
1040 * @since 4.0.0 |
|
1041 * @access public |
|
1042 * |
|
1043 * @param string $name Property to check if set. |
|
1044 * @param mixed $value Property value. |
|
1045 * @return mixed Newly-set property. |
|
1046 */ |
|
1047 public function __set( $name, $value ) { |
|
1048 if ( in_array( $name, $this->compat_fields ) ) { |
|
1049 return $this->$name = $value; |
|
1050 } |
|
1051 } |
|
1052 |
|
1053 /** |
|
1054 * Make private properties checkable for backwards compatibility. |
|
1055 * |
|
1056 * @since 4.0.0 |
|
1057 * @access public |
|
1058 * |
|
1059 * @param string $name Property to check if set. |
|
1060 * @return bool Whether the property is set. |
|
1061 */ |
|
1062 public function __isset( $name ) { |
|
1063 if ( in_array( $name, $this->compat_fields ) ) { |
|
1064 return isset( $this->$name ); |
|
1065 } |
|
1066 } |
|
1067 |
|
1068 /** |
|
1069 * Make private properties un-settable for backwards compatibility. |
|
1070 * |
|
1071 * @since 4.0.0 |
|
1072 * @access public |
|
1073 * |
|
1074 * @param string $name Property to unset. |
|
1075 */ |
|
1076 public function __unset( $name ) { |
|
1077 if ( in_array( $name, $this->compat_fields ) ) { |
|
1078 unset( $this->$name ); |
|
1079 } |
|
1080 } |
|
1081 |
|
1082 /** |
|
1083 * Make private/protected methods readable for backwards compatibility. |
|
1084 * |
|
1085 * @since 4.0.0 |
|
1086 * @access public |
|
1087 * |
|
1088 * @param callable $name Method to call. |
|
1089 * @param array $arguments Arguments to pass when calling. |
|
1090 * @return mixed|bool Return value of the callback, false otherwise. |
|
1091 */ |
|
1092 public function __call( $name, $arguments ) { |
|
1093 if ( 'get_search_sql' === $name ) { |
|
1094 return call_user_func_array( array( $this, $name ), $arguments ); |
|
1095 } |
|
1096 return false; |
|
1097 } |
|
1098 } |
|
1099 |
|
1100 /** |
|
1101 * Retrieve list of users matching criteria. |
|
1102 * |
|
1103 * @since 3.1.0 |
|
1104 * |
|
1105 * @see WP_User_Query |
550 * @see WP_User_Query |
1106 * |
551 * |
1107 * @param array $args Optional. Arguments to retrieve users. See {@see WP_User_Query::prepare_query()} |
552 * @param array $args Optional. Arguments to retrieve users. See WP_User_Query::prepare_query(). |
1108 * for more information on accepted arguments. |
553 * for more information on accepted arguments. |
1109 * @return array List of users. |
554 * @return array List of users. |
1110 */ |
555 */ |
1111 function get_users( $args = array() ) { |
556 function get_users( $args = array() ) { |
1112 |
557 |
1117 |
562 |
1118 return (array) $user_search->get_results(); |
563 return (array) $user_search->get_results(); |
1119 } |
564 } |
1120 |
565 |
1121 /** |
566 /** |
1122 * Get the blogs a user belongs to. |
567 * Get the sites a user belongs to. |
1123 * |
568 * |
1124 * @since 3.0.0 |
569 * @since 3.0.0 |
1125 * |
570 * @since 4.7.0 Converted to use get_sites(). |
1126 * @global wpdb $wpdb WordPress database object for queries. |
571 * |
572 * @global wpdb $wpdb WordPress database abstraction object. |
|
1127 * |
573 * |
1128 * @param int $user_id User ID |
574 * @param int $user_id User ID |
1129 * @param bool $all Whether to retrieve all blogs, or only blogs that are not |
575 * @param bool $all Whether to retrieve all sites, or only sites that are not |
1130 * marked as deleted, archived, or spam. |
576 * marked as deleted, archived, or spam. |
1131 * @return array A list of the user's blogs. An empty array if the user doesn't exist |
577 * @return array A list of the user's sites. An empty array if the user doesn't exist |
1132 * or belongs to no blogs. |
578 * or belongs to no sites. |
1133 */ |
579 */ |
1134 function get_blogs_of_user( $user_id, $all = false ) { |
580 function get_blogs_of_user( $user_id, $all = false ) { |
1135 global $wpdb; |
581 global $wpdb; |
1136 |
582 |
1137 $user_id = (int) $user_id; |
583 $user_id = (int) $user_id; |
1138 |
584 |
1139 // Logged out users can't have blogs |
585 // Logged out users can't have sites |
1140 if ( empty( $user_id ) ) |
586 if ( empty( $user_id ) ) |
1141 return array(); |
587 return array(); |
588 |
|
589 /** |
|
590 * Filters the list of a user's sites before it is populated. |
|
591 * |
|
592 * Passing a non-null value to the filter will effectively short circuit |
|
593 * get_blogs_of_user(), returning that value instead. |
|
594 * |
|
595 * @since 4.6.0 |
|
596 * |
|
597 * @param null|array $sites An array of site objects of which the user is a member. |
|
598 * @param int $user_id User ID. |
|
599 * @param bool $all Whether the returned array should contain all sites, including |
|
600 * those marked 'deleted', 'archived', or 'spam'. Default false. |
|
601 */ |
|
602 $sites = apply_filters( 'pre_get_blogs_of_user', null, $user_id, $all ); |
|
603 |
|
604 if ( null !== $sites ) { |
|
605 return $sites; |
|
606 } |
|
1142 |
607 |
1143 $keys = get_user_meta( $user_id ); |
608 $keys = get_user_meta( $user_id ); |
1144 if ( empty( $keys ) ) |
609 if ( empty( $keys ) ) |
1145 return array(); |
610 return array(); |
1146 |
611 |
1147 if ( ! is_multisite() ) { |
612 if ( ! is_multisite() ) { |
1148 $blog_id = get_current_blog_id(); |
613 $site_id = get_current_blog_id(); |
1149 $blogs = array( $blog_id => new stdClass ); |
614 $sites = array( $site_id => new stdClass ); |
1150 $blogs[ $blog_id ]->userblog_id = $blog_id; |
615 $sites[ $site_id ]->userblog_id = $site_id; |
1151 $blogs[ $blog_id ]->blogname = get_option('blogname'); |
616 $sites[ $site_id ]->blogname = get_option('blogname'); |
1152 $blogs[ $blog_id ]->domain = ''; |
617 $sites[ $site_id ]->domain = ''; |
1153 $blogs[ $blog_id ]->path = ''; |
618 $sites[ $site_id ]->path = ''; |
1154 $blogs[ $blog_id ]->site_id = 1; |
619 $sites[ $site_id ]->site_id = 1; |
1155 $blogs[ $blog_id ]->siteurl = get_option('siteurl'); |
620 $sites[ $site_id ]->siteurl = get_option('siteurl'); |
1156 $blogs[ $blog_id ]->archived = 0; |
621 $sites[ $site_id ]->archived = 0; |
1157 $blogs[ $blog_id ]->spam = 0; |
622 $sites[ $site_id ]->spam = 0; |
1158 $blogs[ $blog_id ]->deleted = 0; |
623 $sites[ $site_id ]->deleted = 0; |
1159 return $blogs; |
624 return $sites; |
1160 } |
625 } |
1161 |
626 |
1162 $blogs = array(); |
627 $site_ids = array(); |
1163 |
628 |
1164 if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) { |
629 if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) { |
1165 $blog = get_blog_details( 1 ); |
630 $site_ids[] = 1; |
1166 if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) { |
|
1167 $blogs[ 1 ] = (object) array( |
|
1168 'userblog_id' => 1, |
|
1169 'blogname' => $blog->blogname, |
|
1170 'domain' => $blog->domain, |
|
1171 'path' => $blog->path, |
|
1172 'site_id' => $blog->site_id, |
|
1173 'siteurl' => $blog->siteurl, |
|
1174 'archived' => 0, |
|
1175 'spam' => 0, |
|
1176 'deleted' => 0 |
|
1177 ); |
|
1178 } |
|
1179 unset( $keys[ $wpdb->base_prefix . 'capabilities' ] ); |
631 unset( $keys[ $wpdb->base_prefix . 'capabilities' ] ); |
1180 } |
632 } |
1181 |
633 |
1182 $keys = array_keys( $keys ); |
634 $keys = array_keys( $keys ); |
1183 |
635 |
1184 foreach ( $keys as $key ) { |
636 foreach ( $keys as $key ) { |
1185 if ( 'capabilities' !== substr( $key, -12 ) ) |
637 if ( 'capabilities' !== substr( $key, -12 ) ) |
1186 continue; |
638 continue; |
1187 if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix ) ) |
639 if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix ) ) |
1188 continue; |
640 continue; |
1189 $blog_id = str_replace( array( $wpdb->base_prefix, '_capabilities' ), '', $key ); |
641 $site_id = str_replace( array( $wpdb->base_prefix, '_capabilities' ), '', $key ); |
1190 if ( ! is_numeric( $blog_id ) ) |
642 if ( ! is_numeric( $site_id ) ) |
1191 continue; |
643 continue; |
1192 |
644 |
1193 $blog_id = (int) $blog_id; |
645 $site_ids[] = (int) $site_id; |
1194 $blog = get_blog_details( $blog_id ); |
646 } |
1195 if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) { |
647 |
1196 $blogs[ $blog_id ] = (object) array( |
648 $sites = array(); |
1197 'userblog_id' => $blog_id, |
649 |
1198 'blogname' => $blog->blogname, |
650 if ( ! empty( $site_ids ) ) { |
1199 'domain' => $blog->domain, |
651 $args = array( |
1200 'path' => $blog->path, |
652 'number' => '', |
1201 'site_id' => $blog->site_id, |
653 'site__in' => $site_ids, |
1202 'siteurl' => $blog->siteurl, |
654 ); |
1203 'archived' => 0, |
655 if ( ! $all ) { |
1204 'spam' => 0, |
656 $args['archived'] = 0; |
1205 'deleted' => 0 |
657 $args['spam'] = 0; |
658 $args['deleted'] = 0; |
|
659 } |
|
660 |
|
661 $_sites = get_sites( $args ); |
|
662 |
|
663 foreach ( $_sites as $site ) { |
|
664 $sites[ $site->id ] = (object) array( |
|
665 'userblog_id' => $site->id, |
|
666 'blogname' => $site->blogname, |
|
667 'domain' => $site->domain, |
|
668 'path' => $site->path, |
|
669 'site_id' => $site->network_id, |
|
670 'siteurl' => $site->siteurl, |
|
671 'archived' => $site->archived, |
|
672 'mature' => $site->mature, |
|
673 'spam' => $site->spam, |
|
674 'deleted' => $site->deleted, |
|
1206 ); |
675 ); |
1207 } |
676 } |
1208 } |
677 } |
1209 |
678 |
1210 /** |
679 /** |
1211 * Filter the list of blogs a user belongs to. |
680 * Filters the list of sites a user belongs to. |
1212 * |
681 * |
1213 * @since MU |
682 * @since MU (3.0.0) |
1214 * |
683 * |
1215 * @param array $blogs An array of blog objects belonging to the user. |
684 * @param array $sites An array of site objects belonging to the user. |
1216 * @param int $user_id User ID. |
685 * @param int $user_id User ID. |
1217 * @param bool $all Whether the returned blogs array should contain all blogs, including |
686 * @param bool $all Whether the returned sites array should contain all sites, including |
1218 * those marked 'deleted', 'archived', or 'spam'. Default false. |
687 * those marked 'deleted', 'archived', or 'spam'. Default false. |
1219 */ |
688 */ |
1220 return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all ); |
689 return apply_filters( 'get_blogs_of_user', $sites, $user_id, $all ); |
1221 } |
690 } |
1222 |
691 |
1223 /** |
692 /** |
1224 * Find out whether a user is a member of a given blog. |
693 * Find out whether a user is a member of a given blog. |
1225 * |
694 * |
1226 * @since MU 1.1 |
695 * @since MU (3.0.0) |
696 * |
|
697 * @global wpdb $wpdb WordPress database abstraction object. |
|
1227 * |
698 * |
1228 * @param int $user_id Optional. The unique ID of the user. Defaults to the current user. |
699 * @param int $user_id Optional. The unique ID of the user. Defaults to the current user. |
1229 * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site. |
700 * @param int $blog_id Optional. ID of the blog to check. Defaults to the current site. |
1230 * @return bool |
701 * @return bool |
1231 */ |
702 */ |
1232 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) { |
703 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) { |
704 global $wpdb; |
|
705 |
|
1233 $user_id = (int) $user_id; |
706 $user_id = (int) $user_id; |
1234 $blog_id = (int) $blog_id; |
707 $blog_id = (int) $blog_id; |
1235 |
708 |
1236 if ( empty( $user_id ) ) |
709 if ( empty( $user_id ) ) { |
1237 $user_id = get_current_user_id(); |
710 $user_id = get_current_user_id(); |
1238 |
711 } |
1239 if ( empty( $blog_id ) ) |
712 |
713 // Technically not needed, but does save calls to get_site and get_user_meta |
|
714 // in the event that the function is called when a user isn't logged in |
|
715 if ( empty( $user_id ) ) { |
|
716 return false; |
|
717 } else { |
|
718 $user = get_userdata( $user_id ); |
|
719 if ( ! $user instanceof WP_User ) { |
|
720 return false; |
|
721 } |
|
722 } |
|
723 |
|
724 if ( ! is_multisite() ) { |
|
725 return true; |
|
726 } |
|
727 |
|
728 if ( empty( $blog_id ) ) { |
|
1240 $blog_id = get_current_blog_id(); |
729 $blog_id = get_current_blog_id(); |
1241 |
730 } |
1242 $blogs = get_blogs_of_user( $user_id ); |
731 |
1243 return array_key_exists( $blog_id, $blogs ); |
732 $blog = get_site( $blog_id ); |
1244 } |
733 |
1245 |
734 if ( ! $blog || ! isset( $blog->domain ) || $blog->archived || $blog->spam || $blog->deleted ) { |
1246 /** |
735 return false; |
1247 * Add meta data field to a user. |
736 } |
1248 * |
737 |
1249 * Post meta data is called "Custom Fields" on the Administration Screens. |
738 $keys = get_user_meta( $user_id ); |
739 if ( empty( $keys ) ) { |
|
740 return false; |
|
741 } |
|
742 |
|
743 // no underscore before capabilities in $base_capabilities_key |
|
744 $base_capabilities_key = $wpdb->base_prefix . 'capabilities'; |
|
745 $site_capabilities_key = $wpdb->base_prefix . $blog_id . '_capabilities'; |
|
746 |
|
747 if ( isset( $keys[ $base_capabilities_key ] ) && $blog_id == 1 ) { |
|
748 return true; |
|
749 } |
|
750 |
|
751 if ( isset( $keys[ $site_capabilities_key ] ) ) { |
|
752 return true; |
|
753 } |
|
754 |
|
755 return false; |
|
756 } |
|
757 |
|
758 /** |
|
759 * Adds meta data to a user. |
|
1250 * |
760 * |
1251 * @since 3.0.0 |
761 * @since 3.0.0 |
1252 * @link https://codex.wordpress.org/Function_Reference/add_user_meta |
762 * |
1253 * |
763 * @param int $user_id User ID. |
1254 * @param int $user_id User ID. |
764 * @param string $meta_key Metadata name. |
1255 * @param string $meta_key Metadata name. |
765 * @param mixed $meta_value Metadata value. |
1256 * @param mixed $meta_value Metadata value. |
766 * @param bool $unique Optional. Whether the same key should not be added. Default false. |
1257 * @param bool $unique Optional, default is false. Whether the same key should not be added. |
767 * @return int|false Meta ID on success, false on failure. |
1258 * @return int|bool Meta ID on success, false on failure. |
|
1259 */ |
768 */ |
1260 function add_user_meta($user_id, $meta_key, $meta_value, $unique = false) { |
769 function add_user_meta($user_id, $meta_key, $meta_value, $unique = false) { |
1261 return add_metadata('user', $user_id, $meta_key, $meta_value, $unique); |
770 return add_metadata('user', $user_id, $meta_key, $meta_value, $unique); |
1262 } |
771 } |
1263 |
772 |
1269 * allows removing all metadata matching key, if needed. |
778 * allows removing all metadata matching key, if needed. |
1270 * |
779 * |
1271 * @since 3.0.0 |
780 * @since 3.0.0 |
1272 * @link https://codex.wordpress.org/Function_Reference/delete_user_meta |
781 * @link https://codex.wordpress.org/Function_Reference/delete_user_meta |
1273 * |
782 * |
1274 * @param int $user_id user ID |
783 * @param int $user_id User ID |
1275 * @param string $meta_key Metadata name. |
784 * @param string $meta_key Metadata name. |
1276 * @param mixed $meta_value Optional. Metadata value. |
785 * @param mixed $meta_value Optional. Metadata value. |
1277 * @return bool True on success, false on failure. |
786 * @return bool True on success, false on failure. |
1278 */ |
787 */ |
1279 function delete_user_meta($user_id, $meta_key, $meta_value = '') { |
788 function delete_user_meta($user_id, $meta_key, $meta_value = '') { |
1280 return delete_metadata('user', $user_id, $meta_key, $meta_value); |
789 return delete_metadata('user', $user_id, $meta_key, $meta_value); |
1281 } |
790 } |
1284 * Retrieve user meta field for a user. |
793 * Retrieve user meta field for a user. |
1285 * |
794 * |
1286 * @since 3.0.0 |
795 * @since 3.0.0 |
1287 * @link https://codex.wordpress.org/Function_Reference/get_user_meta |
796 * @link https://codex.wordpress.org/Function_Reference/get_user_meta |
1288 * |
797 * |
1289 * @param int $user_id User ID. |
798 * @param int $user_id User ID. |
1290 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys. |
799 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys. |
1291 * @param bool $single Whether to return a single value. |
800 * @param bool $single Whether to return a single value. |
1292 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single |
801 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single is true. |
1293 * is true. |
|
1294 */ |
802 */ |
1295 function get_user_meta($user_id, $key = '', $single = false) { |
803 function get_user_meta($user_id, $key = '', $single = false) { |
1296 return get_metadata('user', $user_id, $key, $single); |
804 return get_metadata('user', $user_id, $key, $single); |
1297 } |
805 } |
1298 |
806 |
1305 * If the meta field for the user does not exist, it will be added. |
813 * If the meta field for the user does not exist, it will be added. |
1306 * |
814 * |
1307 * @since 3.0.0 |
815 * @since 3.0.0 |
1308 * @link https://codex.wordpress.org/Function_Reference/update_user_meta |
816 * @link https://codex.wordpress.org/Function_Reference/update_user_meta |
1309 * |
817 * |
1310 * @param int $user_id User ID. |
818 * @param int $user_id User ID. |
1311 * @param string $meta_key Metadata key. |
819 * @param string $meta_key Metadata key. |
1312 * @param mixed $meta_value Metadata value. |
820 * @param mixed $meta_value Metadata value. |
1313 * @param mixed $prev_value Optional. Previous value to check before removing. |
821 * @param mixed $prev_value Optional. Previous value to check before removing. |
1314 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure. |
822 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure. |
1315 */ |
823 */ |
1316 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') { |
824 function update_user_meta($user_id, $meta_key, $meta_value, $prev_value = '') { |
1317 return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value); |
825 return update_metadata('user', $user_id, $meta_key, $meta_value, $prev_value); |
1318 } |
826 } |
1324 * Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query() |
832 * Assumes role names are unique phrases. Same assumption made by WP_User_Query::prepare_query() |
1325 * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users. |
833 * Using $strategy = 'time' this is CPU-intensive and should handle around 10^7 users. |
1326 * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257. |
834 * Using $strategy = 'memory' this is memory-intensive and should handle around 10^5 users, but see WP Bug #12257. |
1327 * |
835 * |
1328 * @since 3.0.0 |
836 * @since 3.0.0 |
1329 * @param string $strategy 'time' or 'memory' |
837 * @since 4.4.0 The number of users with no role is now included in the `none` element. |
838 * @since 4.9.0 The `$site_id` parameter was added to support multisite. |
|
839 * |
|
840 * @global wpdb $wpdb WordPress database abstraction object. |
|
841 * |
|
842 * @param string $strategy Optional. The computational strategy to use when counting the users. |
|
843 * Accepts either 'time' or 'memory'. Default 'time'. |
|
844 * @param int|null $site_id Optional. The site ID to count users for. Defaults to the current site. |
|
1330 * @return array Includes a grand total and an array of counts indexed by role strings. |
845 * @return array Includes a grand total and an array of counts indexed by role strings. |
1331 */ |
846 */ |
1332 function count_users($strategy = 'time') { |
847 function count_users( $strategy = 'time', $site_id = null ) { |
1333 global $wpdb, $wp_roles; |
848 global $wpdb; |
1334 |
849 |
1335 // Initialize |
850 // Initialize |
1336 $id = get_current_blog_id(); |
851 if ( ! $site_id ) { |
1337 $blog_prefix = $wpdb->get_blog_prefix($id); |
852 $site_id = get_current_blog_id(); |
853 } |
|
854 $blog_prefix = $wpdb->get_blog_prefix( $site_id ); |
|
1338 $result = array(); |
855 $result = array(); |
1339 |
856 |
1340 if ( 'time' == $strategy ) { |
857 if ( 'time' == $strategy ) { |
1341 global $wp_roles; |
858 if ( is_multisite() && $site_id != get_current_blog_id() ) { |
1342 |
859 switch_to_blog( $site_id ); |
1343 if ( ! isset( $wp_roles ) ) |
860 $avail_roles = wp_roles()->get_names(); |
1344 $wp_roles = new WP_Roles(); |
861 restore_current_blog(); |
1345 |
862 } else { |
1346 $avail_roles = $wp_roles->get_names(); |
863 $avail_roles = wp_roles()->get_names(); |
864 } |
|
1347 |
865 |
1348 // Build a CPU-intensive query that will return concise information. |
866 // Build a CPU-intensive query that will return concise information. |
1349 $select_count = array(); |
867 $select_count = array(); |
1350 foreach ( $avail_roles as $this_role => $name ) { |
868 foreach ( $avail_roles as $this_role => $name ) { |
1351 $select_count[] = $wpdb->prepare( "COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%'); |
869 $select_count[] = $wpdb->prepare( "COUNT(NULLIF(`meta_value` LIKE %s, false))", '%' . $wpdb->esc_like( '"' . $this_role . '"' ) . '%'); |
1352 } |
870 } |
871 $select_count[] = "COUNT(NULLIF(`meta_value` = 'a:0:{}', false))"; |
|
1353 $select_count = implode(', ', $select_count); |
872 $select_count = implode(', ', $select_count); |
1354 |
873 |
1355 // Add the meta_value index to the selection list, then run the query. |
874 // Add the meta_value index to the selection list, then run the query. |
1356 $row = $wpdb->get_row( "SELECT $select_count, COUNT(*) FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'", ARRAY_N ); |
875 $row = $wpdb->get_row( " |
876 SELECT {$select_count}, COUNT(*) |
|
877 FROM {$wpdb->usermeta} |
|
878 INNER JOIN {$wpdb->users} ON user_id = ID |
|
879 WHERE meta_key = '{$blog_prefix}capabilities' |
|
880 ", ARRAY_N ); |
|
1357 |
881 |
1358 // Run the previous loop again to associate results with role names. |
882 // Run the previous loop again to associate results with role names. |
1359 $col = 0; |
883 $col = 0; |
1360 $role_counts = array(); |
884 $role_counts = array(); |
1361 foreach ( $avail_roles as $this_role => $name ) { |
885 foreach ( $avail_roles as $this_role => $name ) { |
1363 if ($count > 0) { |
887 if ($count > 0) { |
1364 $role_counts[$this_role] = $count; |
888 $role_counts[$this_role] = $count; |
1365 } |
889 } |
1366 } |
890 } |
1367 |
891 |
892 $role_counts['none'] = (int) $row[$col++]; |
|
893 |
|
1368 // Get the meta_value index from the end of the result set. |
894 // Get the meta_value index from the end of the result set. |
1369 $total_users = (int) $row[$col]; |
895 $total_users = (int) $row[$col]; |
1370 |
896 |
1371 $result['total_users'] = $total_users; |
897 $result['total_users'] = $total_users; |
1372 $result['avail_roles'] =& $role_counts; |
898 $result['avail_roles'] =& $role_counts; |
1373 } else { |
899 } else { |
1374 $avail_roles = array(); |
900 $avail_roles = array( |
1375 |
901 'none' => 0, |
1376 $users_of_blog = $wpdb->get_col( "SELECT meta_value FROM $wpdb->usermeta WHERE meta_key = '{$blog_prefix}capabilities'" ); |
902 ); |
903 |
|
904 $users_of_blog = $wpdb->get_col( " |
|
905 SELECT meta_value |
|
906 FROM {$wpdb->usermeta} |
|
907 INNER JOIN {$wpdb->users} ON user_id = ID |
|
908 WHERE meta_key = '{$blog_prefix}capabilities' |
|
909 " ); |
|
1377 |
910 |
1378 foreach ( $users_of_blog as $caps_meta ) { |
911 foreach ( $users_of_blog as $caps_meta ) { |
1379 $b_roles = maybe_unserialize($caps_meta); |
912 $b_roles = maybe_unserialize($caps_meta); |
1380 if ( ! is_array( $b_roles ) ) |
913 if ( ! is_array( $b_roles ) ) |
1381 continue; |
914 continue; |
915 if ( empty( $b_roles ) ) { |
|
916 $avail_roles['none']++; |
|
917 } |
|
1382 foreach ( $b_roles as $b_role => $val ) { |
918 foreach ( $b_roles as $b_role => $val ) { |
1383 if ( isset($avail_roles[$b_role]) ) { |
919 if ( isset($avail_roles[$b_role]) ) { |
1384 $avail_roles[$b_role]++; |
920 $avail_roles[$b_role]++; |
1385 } else { |
921 } else { |
1386 $avail_roles[$b_role] = 1; |
922 $avail_roles[$b_role] = 1; |
1403 * Set up global user vars. |
939 * Set up global user vars. |
1404 * |
940 * |
1405 * Used by wp_set_current_user() for back compat. Might be deprecated in the future. |
941 * Used by wp_set_current_user() for back compat. Might be deprecated in the future. |
1406 * |
942 * |
1407 * @since 2.0.4 |
943 * @since 2.0.4 |
1408 * @global string $userdata User description. |
944 * |
1409 * @global string $user_login The user username for logging in |
945 * @global string $user_login The user username for logging in |
1410 * @global int $user_level The level of the user |
946 * @global WP_User $userdata User data. |
1411 * @global int $user_ID The ID of the user |
947 * @global int $user_level The level of the user |
1412 * @global string $user_email The email address of the user |
948 * @global int $user_ID The ID of the user |
1413 * @global string $user_url The url in the user's profile |
949 * @global string $user_email The email address of the user |
1414 * @global string $user_identity The display name of the user |
950 * @global string $user_url The url in the user's profile |
951 * @global string $user_identity The display name of the user |
|
1415 * |
952 * |
1416 * @param int $for_user_id Optional. User ID to set up global data. |
953 * @param int $for_user_id Optional. User ID to set up global data. |
1417 */ |
954 */ |
1418 function setup_userdata($for_user_id = '') { |
955 function setup_userdata($for_user_id = '') { |
1419 global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_identity; |
956 global $user_login, $userdata, $user_level, $user_ID, $user_email, $user_url, $user_identity; |
1448 * used, either 'include' or 'exclude', but not both. |
985 * used, either 'include' or 'exclude', but not both. |
1449 * |
986 * |
1450 * The available arguments are as follows: |
987 * The available arguments are as follows: |
1451 * |
988 * |
1452 * @since 2.3.0 |
989 * @since 2.3.0 |
1453 * |
990 * @since 4.5.0 Added the 'display_name_with_login' value for 'show'. |
1454 * @global wpdb $wpdb WordPress database object for queries. |
991 * @since 4.7.0 Added the `$role`, `$role__in`, and `$role__not_in` parameters. |
1455 * |
992 * |
1456 * @param array|string $args { |
993 * @param array|string $args { |
1457 * Optional. Array or string of arguments to generate a drop-down of users. |
994 * Optional. Array or string of arguments to generate a drop-down of users. |
1458 * {@see WP_User_Query::prepare_query() for additional available arguments. |
995 * See WP_User_Query::prepare_query() for additional available arguments. |
1459 * |
996 * |
1460 * @type string $show_option_all Text to show as the drop-down default (all). |
997 * @type string $show_option_all Text to show as the drop-down default (all). |
1461 * Default empty. |
998 * Default empty. |
1462 * @type string $show_option_none Text to show as the drop-down default when no |
999 * @type string $show_option_none Text to show as the drop-down default when no |
1463 * users were found. Default empty. |
1000 * users were found. Default empty. |
1474 * Default empty. |
1011 * Default empty. |
1475 * @type array|string $exclude Array or comma-separated list of user IDs to exclude. |
1012 * @type array|string $exclude Array or comma-separated list of user IDs to exclude. |
1476 * Default empty. |
1013 * Default empty. |
1477 * @type bool|int $multi Whether to skip the ID attribute on the 'select' element. |
1014 * @type bool|int $multi Whether to skip the ID attribute on the 'select' element. |
1478 * Accepts 1|true or 0|false. Default 0|false. |
1015 * Accepts 1|true or 0|false. Default 0|false. |
1479 * @type string $show User table column to display. If the selected item is empty |
1016 * @type string $show User data to display. If the selected item is empty |
1480 * then the 'user_login' will be displayed in parentheses. |
1017 * then the 'user_login' will be displayed in parentheses. |
1481 * Accepts user fields. Default 'display_name'. |
1018 * Accepts any user field, or 'display_name_with_login' to show |
1019 * the display name with user_login in parentheses. |
|
1020 * Default 'display_name'. |
|
1482 * @type int|bool $echo Whether to echo or return the drop-down. Accepts 1|true (echo) |
1021 * @type int|bool $echo Whether to echo or return the drop-down. Accepts 1|true (echo) |
1483 * or 0|false (return). Default 1|true. |
1022 * or 0|false (return). Default 1|true. |
1484 * @type int $selected Which user ID should be selected. Default 0. |
1023 * @type int $selected Which user ID should be selected. Default 0. |
1485 * @type bool $include_selected Whether to always include the selected user ID in the drop- |
1024 * @type bool $include_selected Whether to always include the selected user ID in the drop- |
1486 * down. Default false. |
1025 * down. Default false. |
1488 * @type string $id ID attribute of the select element. Default is the value of $name. |
1027 * @type string $id ID attribute of the select element. Default is the value of $name. |
1489 * @type string $class Class attribute of the select element. Default empty. |
1028 * @type string $class Class attribute of the select element. Default empty. |
1490 * @type int $blog_id ID of blog (Multisite only). Default is ID of the current blog. |
1029 * @type int $blog_id ID of blog (Multisite only). Default is ID of the current blog. |
1491 * @type string $who Which type of users to query. Accepts only an empty string or |
1030 * @type string $who Which type of users to query. Accepts only an empty string or |
1492 * 'authors'. Default empty. |
1031 * 'authors'. Default empty. |
1032 * @type string|array $role An array or a comma-separated list of role names that users must |
|
1033 * match to be included in results. Note that this is an inclusive |
|
1034 * list: users must match *each* role. Default empty. |
|
1035 * @type array $role__in An array of role names. Matched users must have at least one of |
|
1036 * these roles. Default empty array. |
|
1037 * @type array $role__not_in An array of role names to exclude. Users matching one or more of |
|
1038 * these roles will not be included in results. Default empty array. |
|
1493 * } |
1039 * } |
1494 * @return string|null Null on display. String of HTML content on retrieve. |
1040 * @return string String of HTML content. |
1495 */ |
1041 */ |
1496 function wp_dropdown_users( $args = '' ) { |
1042 function wp_dropdown_users( $args = '' ) { |
1497 $defaults = array( |
1043 $defaults = array( |
1498 'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '', |
1044 'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '', |
1499 'orderby' => 'display_name', 'order' => 'ASC', |
1045 'orderby' => 'display_name', 'order' => 'ASC', |
1500 'include' => '', 'exclude' => '', 'multi' => 0, |
1046 'include' => '', 'exclude' => '', 'multi' => 0, |
1501 'show' => 'display_name', 'echo' => 1, |
1047 'show' => 'display_name', 'echo' => 1, |
1502 'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '', |
1048 'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '', |
1503 'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false, |
1049 'blog_id' => get_current_blog_id(), 'who' => '', 'include_selected' => false, |
1504 'option_none_value' => -1 |
1050 'option_none_value' => -1, |
1051 'role' => '', |
|
1052 'role__in' => array(), |
|
1053 'role__not_in' => array(), |
|
1505 ); |
1054 ); |
1506 |
1055 |
1507 $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0; |
1056 $defaults['selected'] = is_author() ? get_query_var( 'author' ) : 0; |
1508 |
1057 |
1509 $r = wp_parse_args( $args, $defaults ); |
1058 $r = wp_parse_args( $args, $defaults ); |
1510 $show = $r['show']; |
1059 |
1060 $query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who', 'role', 'role__in', 'role__not_in' ) ); |
|
1061 |
|
1062 $fields = array( 'ID', 'user_login' ); |
|
1063 |
|
1064 $show = ! empty( $r['show'] ) ? $r['show'] : 'display_name'; |
|
1065 if ( 'display_name_with_login' === $show ) { |
|
1066 $fields[] = 'display_name'; |
|
1067 } else { |
|
1068 $fields[] = $show; |
|
1069 } |
|
1070 |
|
1071 $query_args['fields'] = $fields; |
|
1072 |
|
1511 $show_option_all = $r['show_option_all']; |
1073 $show_option_all = $r['show_option_all']; |
1512 $show_option_none = $r['show_option_none']; |
1074 $show_option_none = $r['show_option_none']; |
1513 $option_none_value = $r['option_none_value']; |
1075 $option_none_value = $r['option_none_value']; |
1514 |
1076 |
1515 $query_args = wp_array_slice_assoc( $r, array( 'blog_id', 'include', 'exclude', 'orderby', 'order', 'who' ) ); |
1077 /** |
1516 $query_args['fields'] = array( 'ID', 'user_login', $show ); |
1078 * Filters the query arguments for the list of users in the dropdown. |
1079 * |
|
1080 * @since 4.4.0 |
|
1081 * |
|
1082 * @param array $query_args The query arguments for get_users(). |
|
1083 * @param array $r The arguments passed to wp_dropdown_users() combined with the defaults. |
|
1084 */ |
|
1085 $query_args = apply_filters( 'wp_dropdown_users_args', $query_args, $r ); |
|
1086 |
|
1517 $users = get_users( $query_args ); |
1087 $users = get_users( $query_args ); |
1518 |
1088 |
1519 $output = ''; |
1089 $output = ''; |
1520 if ( ! empty( $users ) && ( empty( $r['hide_if_only_one_author'] ) || count( $users ) > 1 ) ) { |
1090 if ( ! empty( $users ) && ( empty( $r['hide_if_only_one_author'] ) || count( $users ) > 1 ) ) { |
1521 $name = esc_attr( $r['name'] ); |
1091 $name = esc_attr( $r['name'] ); |
1533 if ( $show_option_none ) { |
1103 if ( $show_option_none ) { |
1534 $_selected = selected( $option_none_value, $r['selected'], false ); |
1104 $_selected = selected( $option_none_value, $r['selected'], false ); |
1535 $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$_selected>$show_option_none</option>\n"; |
1105 $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$_selected>$show_option_none</option>\n"; |
1536 } |
1106 } |
1537 |
1107 |
1538 $found_selected = false; |
1108 if ( $r['include_selected'] && ( $r['selected'] > 0 ) ) { |
1109 $found_selected = false; |
|
1110 $r['selected'] = (int) $r['selected']; |
|
1111 foreach ( (array) $users as $user ) { |
|
1112 $user->ID = (int) $user->ID; |
|
1113 if ( $user->ID === $r['selected'] ) { |
|
1114 $found_selected = true; |
|
1115 } |
|
1116 } |
|
1117 |
|
1118 if ( ! $found_selected ) { |
|
1119 $users[] = get_userdata( $r['selected'] ); |
|
1120 } |
|
1121 } |
|
1122 |
|
1539 foreach ( (array) $users as $user ) { |
1123 foreach ( (array) $users as $user ) { |
1540 $user->ID = (int) $user->ID; |
1124 if ( 'display_name_with_login' === $show ) { |
1125 /* translators: 1: display name, 2: user_login */ |
|
1126 $display = sprintf( _x( '%1$s (%2$s)', 'user dropdown' ), $user->display_name, $user->user_login ); |
|
1127 } elseif ( ! empty( $user->$show ) ) { |
|
1128 $display = $user->$show; |
|
1129 } else { |
|
1130 $display = '(' . $user->user_login . ')'; |
|
1131 } |
|
1132 |
|
1541 $_selected = selected( $user->ID, $r['selected'], false ); |
1133 $_selected = selected( $user->ID, $r['selected'], false ); |
1542 if ( $_selected ) { |
|
1543 $found_selected = true; |
|
1544 } |
|
1545 $display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')'; |
|
1546 $output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n"; |
1134 $output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n"; |
1547 } |
1135 } |
1548 |
1136 |
1549 if ( $r['include_selected'] && ! $found_selected && ( $r['selected'] > 0 ) ) { |
|
1550 $user = get_userdata( $r['selected'] ); |
|
1551 $_selected = selected( $user->ID, $r['selected'], false ); |
|
1552 $display = ! empty( $user->$show ) ? $user->$show : '('. $user->user_login . ')'; |
|
1553 $output .= "\t<option value='$user->ID'$_selected>" . esc_html( $display ) . "</option>\n"; |
|
1554 } |
|
1555 |
|
1556 $output .= "</select>"; |
1137 $output .= "</select>"; |
1557 } |
1138 } |
1558 |
1139 |
1559 /** |
1140 /** |
1560 * Filter the wp_dropdown_users() HTML output. |
1141 * Filters the wp_dropdown_users() HTML output. |
1561 * |
1142 * |
1562 * @since 2.3.0 |
1143 * @since 2.3.0 |
1563 * |
1144 * |
1564 * @param string $output HTML output generated by wp_dropdown_users(). |
1145 * @param string $output HTML output generated by wp_dropdown_users(). |
1565 */ |
1146 */ |
1578 * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display' |
1159 * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display' |
1579 * when calling filters. |
1160 * when calling filters. |
1580 * |
1161 * |
1581 * @since 2.3.0 |
1162 * @since 2.3.0 |
1582 * |
1163 * |
1583 * @param string $field The user Object field name. |
1164 * @param string $field The user Object field name. |
1584 * @param mixed $value The user Object value. |
1165 * @param mixed $value The user Object value. |
1585 * @param int $user_id user ID. |
1166 * @param int $user_id User ID. |
1586 * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display', |
1167 * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display', |
1587 * 'attribute' and 'js'. |
1168 * 'attribute' and 'js'. |
1588 * @return mixed Sanitized value. |
1169 * @return mixed Sanitized value. |
1589 */ |
1170 */ |
1590 function sanitize_user_field($field, $value, $user_id, $context) { |
1171 function sanitize_user_field($field, $value, $user_id, $context) { |
1591 $int_fields = array('ID'); |
1172 $int_fields = array('ID'); |
1592 if ( in_array($field, $int_fields) ) |
1173 if ( in_array($field, $int_fields) ) |
1606 /** This filter is documented in wp-includes/post.php */ |
1187 /** This filter is documented in wp-includes/post.php */ |
1607 $value = apply_filters( "edit_{$field}", $value, $user_id ); |
1188 $value = apply_filters( "edit_{$field}", $value, $user_id ); |
1608 } else { |
1189 } else { |
1609 |
1190 |
1610 /** |
1191 /** |
1611 * Filter a user field value in the 'edit' context. |
1192 * Filters a user field value in the 'edit' context. |
1612 * |
1193 * |
1613 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1194 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1614 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1195 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1615 * |
1196 * |
1616 * @since 2.9.0 |
1197 * @since 2.9.0 |
1630 /** This filter is documented in wp-includes/post.php */ |
1211 /** This filter is documented in wp-includes/post.php */ |
1631 $value = apply_filters( "pre_{$field}", $value ); |
1212 $value = apply_filters( "pre_{$field}", $value ); |
1632 } else { |
1213 } else { |
1633 |
1214 |
1634 /** |
1215 /** |
1635 * Filter the value of a user field in the 'db' context. |
1216 * Filters the value of a user field in the 'db' context. |
1636 * |
1217 * |
1637 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1218 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1638 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1219 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1639 * |
1220 * |
1640 * @since 2.9.0 |
1221 * @since 2.9.0 |
1646 } else { |
1227 } else { |
1647 // Use display filters by default. |
1228 // Use display filters by default. |
1648 if ( $prefixed ) { |
1229 if ( $prefixed ) { |
1649 |
1230 |
1650 /** This filter is documented in wp-includes/post.php */ |
1231 /** This filter is documented in wp-includes/post.php */ |
1651 $value = apply_filters( $field, $value, $user_id, $context ); |
1232 $value = apply_filters( "{$field}", $value, $user_id, $context ); |
1652 } else { |
1233 } else { |
1653 |
1234 |
1654 /** |
1235 /** |
1655 * Filter the value of a user field in a standard context. |
1236 * Filters the value of a user field in a standard context. |
1656 * |
1237 * |
1657 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1238 * The dynamic portion of the hook name, `$field`, refers to the prefixed user |
1658 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1239 * field being filtered, such as 'user_login', 'user_email', 'first_name', etc. |
1659 * |
1240 * |
1660 * @since 2.9.0 |
1241 * @since 2.9.0 |
1681 /** |
1262 /** |
1682 * Update all user caches |
1263 * Update all user caches |
1683 * |
1264 * |
1684 * @since 3.0.0 |
1265 * @since 3.0.0 |
1685 * |
1266 * |
1686 * @param object $user User object to be cached |
1267 * @param WP_User $user User object to be cached |
1687 */ |
1268 * @return bool|null Returns false on failure. |
1688 function update_user_caches($user) { |
1269 */ |
1270 function update_user_caches( $user ) { |
|
1271 if ( $user instanceof WP_User ) { |
|
1272 if ( ! $user->exists() ) { |
|
1273 return false; |
|
1274 } |
|
1275 |
|
1276 $user = $user->data; |
|
1277 } |
|
1278 |
|
1689 wp_cache_add($user->ID, $user, 'users'); |
1279 wp_cache_add($user->ID, $user, 'users'); |
1690 wp_cache_add($user->user_login, $user->ID, 'userlogins'); |
1280 wp_cache_add($user->user_login, $user->ID, 'userlogins'); |
1691 wp_cache_add($user->user_email, $user->ID, 'useremail'); |
1281 wp_cache_add($user->user_email, $user->ID, 'useremail'); |
1692 wp_cache_add($user->user_nicename, $user->ID, 'userslugs'); |
1282 wp_cache_add($user->user_nicename, $user->ID, 'userslugs'); |
1693 } |
1283 } |
1694 |
1284 |
1695 /** |
1285 /** |
1696 * Clean all user caches |
1286 * Clean all user caches |
1697 * |
1287 * |
1698 * @since 3.0.0 |
1288 * @since 3.0.0 |
1289 * @since 4.4.0 'clean_user_cache' action was added. |
|
1699 * |
1290 * |
1700 * @param WP_User|int $user User object or ID to be cleaned from the cache |
1291 * @param WP_User|int $user User object or ID to be cleaned from the cache |
1701 */ |
1292 */ |
1702 function clean_user_cache( $user ) { |
1293 function clean_user_cache( $user ) { |
1703 if ( is_numeric( $user ) ) |
1294 if ( is_numeric( $user ) ) |
1708 |
1299 |
1709 wp_cache_delete( $user->ID, 'users' ); |
1300 wp_cache_delete( $user->ID, 'users' ); |
1710 wp_cache_delete( $user->user_login, 'userlogins' ); |
1301 wp_cache_delete( $user->user_login, 'userlogins' ); |
1711 wp_cache_delete( $user->user_email, 'useremail' ); |
1302 wp_cache_delete( $user->user_email, 'useremail' ); |
1712 wp_cache_delete( $user->user_nicename, 'userslugs' ); |
1303 wp_cache_delete( $user->user_nicename, 'userslugs' ); |
1304 |
|
1305 /** |
|
1306 * Fires immediately after the given user's cache is cleaned. |
|
1307 * |
|
1308 * @since 4.4.0 |
|
1309 * |
|
1310 * @param int $user_id User ID. |
|
1311 * @param WP_User $user User object. |
|
1312 */ |
|
1313 do_action( 'clean_user_cache', $user->ID, $user ); |
|
1713 } |
1314 } |
1714 |
1315 |
1715 /** |
1316 /** |
1716 * Checks whether the given username exists. |
1317 * Checks whether the given username exists. |
1717 * |
1318 * |
1718 * @since 2.0.0 |
1319 * @since 2.0.0 |
1719 * |
1320 * |
1720 * @param string $username Username. |
1321 * @param string $username Username. |
1721 * @return null|int The user's ID on success, and null on failure. |
1322 * @return int|false The user's ID on success, and false on failure. |
1722 */ |
1323 */ |
1723 function username_exists( $username ) { |
1324 function username_exists( $username ) { |
1724 if ( $user = get_user_by('login', $username ) ) { |
1325 if ( $user = get_user_by( 'login', $username ) ) { |
1326 $user_id = $user->ID; |
|
1327 } else { |
|
1328 $user_id = false; |
|
1329 } |
|
1330 |
|
1331 /** |
|
1332 * Filters whether the given username exists or not. |
|
1333 * |
|
1334 * @since 4.9.0 |
|
1335 * |
|
1336 * @param int|false $user_id The user's ID on success, and false on failure. |
|
1337 * @param string $username Username to check. |
|
1338 */ |
|
1339 return apply_filters( 'username_exists', $user_id, $username ); |
|
1340 } |
|
1341 |
|
1342 /** |
|
1343 * Checks whether the given email exists. |
|
1344 * |
|
1345 * @since 2.1.0 |
|
1346 * |
|
1347 * @param string $email Email. |
|
1348 * @return int|false The user's ID on success, and false on failure. |
|
1349 */ |
|
1350 function email_exists( $email ) { |
|
1351 if ( $user = get_user_by( 'email', $email) ) { |
|
1725 return $user->ID; |
1352 return $user->ID; |
1726 } else { |
1353 } |
1727 return null; |
|
1728 } |
|
1729 } |
|
1730 |
|
1731 /** |
|
1732 * Checks whether the given email exists. |
|
1733 * |
|
1734 * @since 2.1.0 |
|
1735 * |
|
1736 * @param string $email Email. |
|
1737 * @return bool|int The user's ID on success, and false on failure. |
|
1738 */ |
|
1739 function email_exists( $email ) { |
|
1740 if ( $user = get_user_by('email', $email) ) |
|
1741 return $user->ID; |
|
1742 |
|
1743 return false; |
1354 return false; |
1744 } |
1355 } |
1745 |
1356 |
1746 /** |
1357 /** |
1747 * Checks whether a username is valid. |
1358 * Checks whether a username is valid. |
1748 * |
1359 * |
1749 * @since 2.0.1 |
1360 * @since 2.0.1 |
1361 * @since 4.4.0 Empty sanitized usernames are now considered invalid |
|
1750 * |
1362 * |
1751 * @param string $username Username. |
1363 * @param string $username Username. |
1752 * @return bool Whether username given is valid |
1364 * @return bool Whether username given is valid |
1753 */ |
1365 */ |
1754 function validate_username( $username ) { |
1366 function validate_username( $username ) { |
1755 $sanitized = sanitize_user( $username, true ); |
1367 $sanitized = sanitize_user( $username, true ); |
1756 $valid = ( $sanitized == $username ); |
1368 $valid = ( $sanitized == $username && ! empty( $sanitized ) ); |
1757 /** |
1369 |
1758 * Filter whether the provided username is valid or not. |
1370 /** |
1371 * Filters whether the provided username is valid or not. |
|
1759 * |
1372 * |
1760 * @since 2.0.1 |
1373 * @since 2.0.1 |
1761 * |
1374 * |
1762 * @param bool $valid Whether given username is valid. |
1375 * @param bool $valid Whether given username is valid. |
1763 * @param string $username Username to check. |
1376 * @param string $username Username to check. |
1766 } |
1379 } |
1767 |
1380 |
1768 /** |
1381 /** |
1769 * Insert a user into the database. |
1382 * Insert a user into the database. |
1770 * |
1383 * |
1771 * Most of the $userdata array fields have filters associated with the values. |
1384 * Most of the `$userdata` array fields have filters associated with the values. Exceptions are |
1772 * The exceptions are 'rich_editing', 'role', 'jabber', 'aim', 'yim', |
1385 * 'ID', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl', |
1773 * 'user_registered', and 'ID'. The filters have the prefix 'pre_user_' followed |
1386 * 'user_registered', and 'role'. The filters have the prefix 'pre_user_' followed by the field |
1774 * by the field name. An example using 'description' would have the filter |
1387 * name. An example using 'description' would have the filter called, 'pre_user_description' that |
1775 * called, 'pre_user_description' that can be hooked into. |
1388 * can be hooked into. |
1776 * |
1389 * |
1777 * @since 2.0.0 |
1390 * @since 2.0.0 |
1778 * |
1391 * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact |
1779 * @global wpdb $wpdb WordPress database object for queries. |
1392 * methods for new installations. See wp_get_user_contact_methods(). |
1780 * |
1393 * @since 4.7.0 The user's locale can be passed to `$userdata`. |
1781 * @param array $userdata { |
1394 * |
1395 * @global wpdb $wpdb WordPress database abstraction object. |
|
1396 * |
|
1397 * @param array|object|WP_User $userdata { |
|
1782 * An array, object, or WP_User object of user data arguments. |
1398 * An array, object, or WP_User object of user data arguments. |
1783 * |
1399 * |
1784 * @type int $ID User ID. If supplied, the user will be updated. |
1400 * @type int $ID User ID. If supplied, the user will be updated. |
1785 * @type string $user_pass The plain-text user password. |
1401 * @type string $user_pass The plain-text user password. |
1786 * @type string $user_login The user's login username. |
1402 * @type string $user_login The user's login username. |
1787 * @type string $user_nicename The URL-friendly user name. |
1403 * @type string $user_nicename The URL-friendly user name. |
1788 * @type string $user_url The user URL. |
1404 * @type string $user_url The user URL. |
1789 * @type string $user_email The user email address. |
1405 * @type string $user_email The user email address. |
1790 * @type string $display_name The user's display name. |
1406 * @type string $display_name The user's display name. |
1791 * Default is the the user's username. |
1407 * Default is the user's username. |
1792 * @type string $nickname The user's nickname. Default |
1408 * @type string $nickname The user's nickname. |
1793 * Default is the the user's username. |
1409 * Default is the user's username. |
1794 * @type string $first_name The user's first name. For new users, will be used |
1410 * @type string $first_name The user's first name. For new users, will be used |
1795 * to build $display_name if unspecified. |
1411 * to build the first part of the user's display name |
1796 * @type stirng $last_name The user's last name. For new users, will be used |
1412 * if `$display_name` is not specified. |
1797 * to build $display_name if unspecified. |
1413 * @type string $last_name The user's last name. For new users, will be used |
1798 * @type string|bool $rich_editing Whether to enable the rich-editor for the user. False |
1414 * to build the second part of the user's display name |
1799 * if not empty. |
1415 * if `$display_name` is not specified. |
1800 * @type string $user_registered Date the user registered. Format is 'Y-m-d H:i:s'. |
1416 * @type string $description The user's biographical description. |
1801 * @type string $role User's role. |
1417 * @type string|bool $rich_editing Whether to enable the rich-editor for the user. |
1802 * @type string $jabber User's Jabber account username. |
1418 * False if not empty. |
1803 * @type string $aim User's AIM account username. |
1419 * @type string|bool $syntax_highlighting Whether to enable the rich code editor for the user. |
1804 * @type string $yim User's Yahoo! messenger username. |
1420 * False if not empty. |
1421 * @type string|bool $comment_shortcuts Whether to enable comment moderation keyboard |
|
1422 * shortcuts for the user. Default false. |
|
1423 * @type string $admin_color Admin color scheme for the user. Default 'fresh'. |
|
1424 * @type bool $use_ssl Whether the user should always access the admin over |
|
1425 * https. Default false. |
|
1426 * @type string $user_registered Date the user registered. Format is 'Y-m-d H:i:s'. |
|
1427 * @type string|bool $show_admin_bar_front Whether to display the Admin Bar for the user on the |
|
1428 * site's front end. Default true. |
|
1429 * @type string $role User's role. |
|
1430 * @type string $locale User's locale. Default empty. |
|
1805 * } |
1431 * } |
1806 * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not |
1432 * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not |
1807 * be created. |
1433 * be created. |
1808 */ |
1434 */ |
1809 function wp_insert_user( $userdata ) { |
1435 function wp_insert_user( $userdata ) { |
1812 if ( $userdata instanceof stdClass ) { |
1438 if ( $userdata instanceof stdClass ) { |
1813 $userdata = get_object_vars( $userdata ); |
1439 $userdata = get_object_vars( $userdata ); |
1814 } elseif ( $userdata instanceof WP_User ) { |
1440 } elseif ( $userdata instanceof WP_User ) { |
1815 $userdata = $userdata->to_array(); |
1441 $userdata = $userdata->to_array(); |
1816 } |
1442 } |
1443 |
|
1817 // Are we updating or creating? |
1444 // Are we updating or creating? |
1818 if ( ! empty( $userdata['ID'] ) ) { |
1445 if ( ! empty( $userdata['ID'] ) ) { |
1819 $ID = (int) $userdata['ID']; |
1446 $ID = (int) $userdata['ID']; |
1820 $update = true; |
1447 $update = true; |
1821 $old_user_data = WP_User::get_data_by( 'id', $ID ); |
1448 $old_user_data = get_userdata( $ID ); |
1449 |
|
1450 if ( ! $old_user_data ) { |
|
1451 return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) ); |
|
1452 } |
|
1453 |
|
1822 // hashed in wp_update_user(), plaintext if called directly |
1454 // hashed in wp_update_user(), plaintext if called directly |
1823 $user_pass = $userdata['user_pass']; |
1455 $user_pass = ! empty( $userdata['user_pass'] ) ? $userdata['user_pass'] : $old_user_data->user_pass; |
1824 } else { |
1456 } else { |
1825 $update = false; |
1457 $update = false; |
1826 // Hash the password |
1458 // Hash the password |
1827 $user_pass = wp_hash_password( $userdata['user_pass'] ); |
1459 $user_pass = wp_hash_password( $userdata['user_pass'] ); |
1828 } |
1460 } |
1829 |
1461 |
1830 $sanitized_user_login = sanitize_user( $userdata['user_login'], true ); |
1462 $sanitized_user_login = sanitize_user( $userdata['user_login'], true ); |
1831 |
1463 |
1832 /** |
1464 /** |
1833 * Filter a username after it has been sanitized. |
1465 * Filters a username after it has been sanitized. |
1834 * |
1466 * |
1835 * This filter is called before the user is created or updated. |
1467 * This filter is called before the user is created or updated. |
1836 * |
1468 * |
1837 * @since 2.0.3 |
1469 * @since 2.0.3 |
1838 * |
1470 * |
1841 $pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login ); |
1473 $pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login ); |
1842 |
1474 |
1843 //Remove any non-printable chars from the login string to see if we have ended up with an empty username |
1475 //Remove any non-printable chars from the login string to see if we have ended up with an empty username |
1844 $user_login = trim( $pre_user_login ); |
1476 $user_login = trim( $pre_user_login ); |
1845 |
1477 |
1478 // user_login must be between 0 and 60 characters. |
|
1846 if ( empty( $user_login ) ) { |
1479 if ( empty( $user_login ) ) { |
1847 return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') ); |
1480 return new WP_Error('empty_user_login', __('Cannot create a user with an empty login name.') ); |
1848 } |
1481 } elseif ( mb_strlen( $user_login ) > 60 ) { |
1482 return new WP_Error( 'user_login_too_long', __( 'Username may not be longer than 60 characters.' ) ); |
|
1483 } |
|
1484 |
|
1849 if ( ! $update && username_exists( $user_login ) ) { |
1485 if ( ! $update && username_exists( $user_login ) ) { |
1850 return new WP_Error( 'existing_user_login', __( 'Sorry, that username already exists!' ) ); |
1486 return new WP_Error( 'existing_user_login', __( 'Sorry, that username already exists!' ) ); |
1851 } |
1487 } |
1852 |
1488 |
1853 // If a nicename is provided, remove unsafe user characters before |
1489 /** |
1854 // using it. Otherwise build a nicename from the user_login. |
1490 * Filters the list of blacklisted usernames. |
1491 * |
|
1492 * @since 4.4.0 |
|
1493 * |
|
1494 * @param array $usernames Array of blacklisted usernames. |
|
1495 */ |
|
1496 $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); |
|
1497 |
|
1498 if ( in_array( strtolower( $user_login ), array_map( 'strtolower', $illegal_logins ) ) ) { |
|
1499 return new WP_Error( 'invalid_username', __( 'Sorry, that username is not allowed.' ) ); |
|
1500 } |
|
1501 |
|
1502 /* |
|
1503 * If a nicename is provided, remove unsafe user characters before using it. |
|
1504 * Otherwise build a nicename from the user_login. |
|
1505 */ |
|
1855 if ( ! empty( $userdata['user_nicename'] ) ) { |
1506 if ( ! empty( $userdata['user_nicename'] ) ) { |
1856 $user_nicename = sanitize_user( $userdata['user_nicename'], true ); |
1507 $user_nicename = sanitize_user( $userdata['user_nicename'], true ); |
1508 if ( mb_strlen( $user_nicename ) > 50 ) { |
|
1509 return new WP_Error( 'user_nicename_too_long', __( 'Nicename may not be longer than 50 characters.' ) ); |
|
1510 } |
|
1857 } else { |
1511 } else { |
1858 $user_nicename = $user_login; |
1512 $user_nicename = mb_substr( $user_login, 0, 50 ); |
1859 } |
1513 } |
1860 |
1514 |
1861 $user_nicename = sanitize_title( $user_nicename ); |
1515 $user_nicename = sanitize_title( $user_nicename ); |
1862 |
1516 |
1863 // Store values to save in user meta. |
1517 // Store values to save in user meta. |
1864 $meta = array(); |
1518 $meta = array(); |
1865 |
1519 |
1866 /** |
1520 /** |
1867 * Filter a user's nicename before the user is created or updated. |
1521 * Filters a user's nicename before the user is created or updated. |
1868 * |
1522 * |
1869 * @since 2.0.3 |
1523 * @since 2.0.3 |
1870 * |
1524 * |
1871 * @param string $user_nicename The user's nicename. |
1525 * @param string $user_nicename The user's nicename. |
1872 */ |
1526 */ |
1873 $user_nicename = apply_filters( 'pre_user_nicename', $user_nicename ); |
1527 $user_nicename = apply_filters( 'pre_user_nicename', $user_nicename ); |
1874 |
1528 |
1875 $raw_user_url = empty( $userdata['user_url'] ) ? '' : $userdata['user_url']; |
1529 $raw_user_url = empty( $userdata['user_url'] ) ? '' : $userdata['user_url']; |
1876 |
1530 |
1877 /** |
1531 /** |
1878 * Filter a user's URL before the user is created or updated. |
1532 * Filters a user's URL before the user is created or updated. |
1879 * |
1533 * |
1880 * @since 2.0.3 |
1534 * @since 2.0.3 |
1881 * |
1535 * |
1882 * @param string $raw_user_url The user's URL. |
1536 * @param string $raw_user_url The user's URL. |
1883 */ |
1537 */ |
1884 $user_url = apply_filters( 'pre_user_url', $raw_user_url ); |
1538 $user_url = apply_filters( 'pre_user_url', $raw_user_url ); |
1885 |
1539 |
1886 $raw_user_email = empty( $userdata['user_email'] ) ? '' : $userdata['user_email']; |
1540 $raw_user_email = empty( $userdata['user_email'] ) ? '' : $userdata['user_email']; |
1887 |
1541 |
1888 /** |
1542 /** |
1889 * Filter a user's email before the user is created or updated. |
1543 * Filters a user's email before the user is created or updated. |
1890 * |
1544 * |
1891 * @since 2.0.3 |
1545 * @since 2.0.3 |
1892 * |
1546 * |
1893 * @param string $raw_user_email The user's email. |
1547 * @param string $raw_user_email The user's email. |
1894 */ |
1548 */ |
1897 /* |
1551 /* |
1898 * If there is no update, just check for `email_exists`. If there is an update, |
1552 * If there is no update, just check for `email_exists`. If there is an update, |
1899 * check if current email and new email are the same, or not, and check `email_exists` |
1553 * check if current email and new email are the same, or not, and check `email_exists` |
1900 * accordingly. |
1554 * accordingly. |
1901 */ |
1555 */ |
1902 if ( ( ! $update || ( ! empty( $old_user_data ) && $user_email !== $old_user_data->user_email ) ) |
1556 if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) ) |
1903 && ! defined( 'WP_IMPORTING' ) |
1557 && ! defined( 'WP_IMPORTING' ) |
1904 && email_exists( $user_email ) |
1558 && email_exists( $user_email ) |
1905 ) { |
1559 ) { |
1906 return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) ); |
1560 return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) ); |
1907 } |
1561 } |
1908 $nickname = empty( $userdata['nickname'] ) ? $user_login : $userdata['nickname']; |
1562 $nickname = empty( $userdata['nickname'] ) ? $user_login : $userdata['nickname']; |
1909 |
1563 |
1910 /** |
1564 /** |
1911 * Filter a user's nickname before the user is created or updated. |
1565 * Filters a user's nickname before the user is created or updated. |
1912 * |
1566 * |
1913 * @since 2.0.3 |
1567 * @since 2.0.3 |
1914 * |
1568 * |
1915 * @param string $nickname The user's nickname. |
1569 * @param string $nickname The user's nickname. |
1916 */ |
1570 */ |
1917 $meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname ); |
1571 $meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname ); |
1918 |
1572 |
1919 $first_name = empty( $userdata['first_name'] ) ? '' : $userdata['first_name']; |
1573 $first_name = empty( $userdata['first_name'] ) ? '' : $userdata['first_name']; |
1920 |
1574 |
1921 /** |
1575 /** |
1922 * Filter a user's first name before the user is created or updated. |
1576 * Filters a user's first name before the user is created or updated. |
1923 * |
1577 * |
1924 * @since 2.0.3 |
1578 * @since 2.0.3 |
1925 * |
1579 * |
1926 * @param string $first_name The user's first name. |
1580 * @param string $first_name The user's first name. |
1927 */ |
1581 */ |
1928 $meta['first_name'] = apply_filters( 'pre_user_first_name', $first_name ); |
1582 $meta['first_name'] = apply_filters( 'pre_user_first_name', $first_name ); |
1929 |
1583 |
1930 $last_name = empty( $userdata['last_name'] ) ? '' : $userdata['last_name']; |
1584 $last_name = empty( $userdata['last_name'] ) ? '' : $userdata['last_name']; |
1931 |
1585 |
1932 /** |
1586 /** |
1933 * Filter a user's last name before the user is created or updated. |
1587 * Filters a user's last name before the user is created or updated. |
1934 * |
1588 * |
1935 * @since 2.0.3 |
1589 * @since 2.0.3 |
1936 * |
1590 * |
1937 * @param string $last_name The user's last name. |
1591 * @param string $last_name The user's last name. |
1938 */ |
1592 */ |
1954 } else { |
1608 } else { |
1955 $display_name = $userdata['display_name']; |
1609 $display_name = $userdata['display_name']; |
1956 } |
1610 } |
1957 |
1611 |
1958 /** |
1612 /** |
1959 * Filter a user's display name before the user is created or updated. |
1613 * Filters a user's display name before the user is created or updated. |
1960 * |
1614 * |
1961 * @since 2.0.3 |
1615 * @since 2.0.3 |
1962 * |
1616 * |
1963 * @param string $display_name The user's display name. |
1617 * @param string $display_name The user's display name. |
1964 */ |
1618 */ |
1965 $display_name = apply_filters( 'pre_user_display_name', $display_name ); |
1619 $display_name = apply_filters( 'pre_user_display_name', $display_name ); |
1966 |
1620 |
1967 $description = empty( $userdata['description'] ) ? '' : $userdata['description']; |
1621 $description = empty( $userdata['description'] ) ? '' : $userdata['description']; |
1968 |
1622 |
1969 /** |
1623 /** |
1970 * Filter a user's description before the user is created or updated. |
1624 * Filters a user's description before the user is created or updated. |
1971 * |
1625 * |
1972 * @since 2.0.3 |
1626 * @since 2.0.3 |
1973 * |
1627 * |
1974 * @param string $description The user's description. |
1628 * @param string $description The user's description. |
1975 */ |
1629 */ |
1976 $meta['description'] = apply_filters( 'pre_user_description', $description ); |
1630 $meta['description'] = apply_filters( 'pre_user_description', $description ); |
1977 |
1631 |
1978 $meta['rich_editing'] = empty( $userdata['rich_editing'] ) ? 'true' : $userdata['rich_editing']; |
1632 $meta['rich_editing'] = empty( $userdata['rich_editing'] ) ? 'true' : $userdata['rich_editing']; |
1979 |
1633 |
1980 $meta['comment_shortcuts'] = empty( $userdata['comment_shortcuts'] ) ? 'false' : $userdata['comment_shortcuts']; |
1634 $meta['syntax_highlighting'] = empty( $userdata['syntax_highlighting'] ) ? 'true' : $userdata['syntax_highlighting']; |
1635 |
|
1636 $meta['comment_shortcuts'] = empty( $userdata['comment_shortcuts'] ) || 'false' === $userdata['comment_shortcuts'] ? 'false' : 'true'; |
|
1981 |
1637 |
1982 $admin_color = empty( $userdata['admin_color'] ) ? 'fresh' : $userdata['admin_color']; |
1638 $admin_color = empty( $userdata['admin_color'] ) ? 'fresh' : $userdata['admin_color']; |
1983 $meta['admin_color'] = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $admin_color ); |
1639 $meta['admin_color'] = preg_replace( '|[^a-z0-9 _.\-@]|i', '', $admin_color ); |
1984 |
1640 |
1985 $meta['use_ssl'] = empty( $userdata['use_ssl'] ) ? 0 : $userdata['use_ssl']; |
1641 $meta['use_ssl'] = empty( $userdata['use_ssl'] ) ? 0 : $userdata['use_ssl']; |
1986 |
1642 |
1987 $user_registered = empty( $userdata['user_registered'] ) ? gmdate( 'Y-m-d H:i:s' ) : $userdata['user_registered']; |
1643 $user_registered = empty( $userdata['user_registered'] ) ? gmdate( 'Y-m-d H:i:s' ) : $userdata['user_registered']; |
1988 |
1644 |
1989 $meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front']; |
1645 $meta['show_admin_bar_front'] = empty( $userdata['show_admin_bar_front'] ) ? 'true' : $userdata['show_admin_bar_front']; |
1646 |
|
1647 $meta['locale'] = isset( $userdata['locale'] ) ? $userdata['locale'] : ''; |
|
1990 |
1648 |
1991 $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login)); |
1649 $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)); |
1992 |
1650 |
1993 if ( $user_nicename_check ) { |
1651 if ( $user_nicename_check ) { |
1994 $suffix = 2; |
1652 $suffix = 2; |
1995 while ($user_nicename_check) { |
1653 while ($user_nicename_check) { |
1996 $alt_user_nicename = $user_nicename . "-$suffix"; |
1654 // user_nicename allows 50 chars. Subtract one for a hyphen, plus the length of the suffix. |
1655 $base_length = 49 - mb_strlen( $suffix ); |
|
1656 $alt_user_nicename = mb_substr( $user_nicename, 0, $base_length ) . "-$suffix"; |
|
1997 $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)); |
1657 $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)); |
1998 $suffix++; |
1658 $suffix++; |
1999 } |
1659 } |
2000 $user_nicename = $alt_user_nicename; |
1660 $user_nicename = $alt_user_nicename; |
2001 } |
1661 } |
2002 |
1662 |
2003 $compacted = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' ); |
1663 $compacted = compact( 'user_pass', 'user_email', 'user_url', 'user_nicename', 'display_name', 'user_registered' ); |
2004 $data = wp_unslash( $compacted ); |
1664 $data = wp_unslash( $compacted ); |
1665 |
|
1666 if ( ! $update ) { |
|
1667 $data = $data + compact( 'user_login' ); |
|
1668 } |
|
1669 |
|
1670 /** |
|
1671 * Filters user data before the record is created or updated. |
|
1672 * |
|
1673 * It only includes data in the wp_users table wp_user, not any user metadata. |
|
1674 * |
|
1675 * @since 4.9.0 |
|
1676 * |
|
1677 * @param array $data { |
|
1678 * Values and keys for the user. |
|
1679 * |
|
1680 * @type string $user_login The user's login. Only included if $update == false |
|
1681 * @type string $user_pass The user's password. |
|
1682 * @type string $user_email The user's email. |
|
1683 * @type string $user_url The user's url. |
|
1684 * @type string $user_nicename The user's nice name. Defaults to a URL-safe version of user's login |
|
1685 * @type string $display_name The user's display name. |
|
1686 * @type string $user_registered MySQL timestamp describing the moment when the user registered. Defaults to |
|
1687 * the current UTC timestamp. |
|
1688 * } |
|
1689 * @param bool $update Whether the user is being updated rather than created. |
|
1690 * @param int|null $id ID of the user to be updated, or NULL if the user is being created. |
|
1691 */ |
|
1692 $data = apply_filters( 'wp_pre_insert_user_data', $data, $update, $update ? (int) $ID : null ); |
|
2005 |
1693 |
2006 if ( $update ) { |
1694 if ( $update ) { |
2007 if ( $user_email !== $old_user_data->user_email ) { |
1695 if ( $user_email !== $old_user_data->user_email ) { |
2008 $data['user_activation_key'] = ''; |
1696 $data['user_activation_key'] = ''; |
2009 } |
1697 } |
2010 $wpdb->update( $wpdb->users, $data, compact( 'ID' ) ); |
1698 $wpdb->update( $wpdb->users, $data, compact( 'ID' ) ); |
2011 $user_id = (int) $ID; |
1699 $user_id = (int) $ID; |
2012 } else { |
1700 } else { |
2013 $wpdb->insert( $wpdb->users, $data + compact( 'user_login' ) ); |
1701 $wpdb->insert( $wpdb->users, $data ); |
2014 $user_id = (int) $wpdb->insert_id; |
1702 $user_id = (int) $wpdb->insert_id; |
2015 } |
1703 } |
2016 |
1704 |
2017 $user = new WP_User( $user_id ); |
1705 $user = new WP_User( $user_id ); |
1706 |
|
1707 /** |
|
1708 * Filters a user's meta values and keys immediately after the user is created or updated |
|
1709 * and before any user meta is inserted or updated. |
|
1710 * |
|
1711 * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`. |
|
1712 * |
|
1713 * @since 4.4.0 |
|
1714 * |
|
1715 * @param array $meta { |
|
1716 * Default meta values and keys for the user. |
|
1717 * |
|
1718 * @type string $nickname The user's nickname. Default is the user's username. |
|
1719 * @type string $first_name The user's first name. |
|
1720 * @type string $last_name The user's last name. |
|
1721 * @type string $description The user's description. |
|
1722 * @type bool $rich_editing Whether to enable the rich-editor for the user. False if not empty. |
|
1723 * @type bool $syntax_highlighting Whether to enable the rich code editor for the user. False if not empty. |
|
1724 * @type bool $comment_shortcuts Whether to enable keyboard shortcuts for the user. Default false. |
|
1725 * @type string $admin_color The color scheme for a user's admin screen. Default 'fresh'. |
|
1726 * @type int|bool $use_ssl Whether to force SSL on the user's admin area. 0|false if SSL is |
|
1727 * not forced. |
|
1728 * @type bool $show_admin_bar_front Whether to show the admin bar on the front end for the user. |
|
1729 * Default true. |
|
1730 * } |
|
1731 * @param WP_User $user User object. |
|
1732 * @param bool $update Whether the user is being updated rather than created. |
|
1733 */ |
|
1734 $meta = apply_filters( 'insert_user_meta', $meta, $user, $update ); |
|
2018 |
1735 |
2019 // Update user meta. |
1736 // Update user meta. |
2020 foreach ( $meta as $key => $value ) { |
1737 foreach ( $meta as $key => $value ) { |
2021 update_user_meta( $user_id, $key, $value ); |
1738 update_user_meta( $user_id, $key, $value ); |
2022 } |
1739 } |
2039 /** |
1756 /** |
2040 * Fires immediately after an existing user is updated. |
1757 * Fires immediately after an existing user is updated. |
2041 * |
1758 * |
2042 * @since 2.0.0 |
1759 * @since 2.0.0 |
2043 * |
1760 * |
2044 * @param int $user_id User ID. |
1761 * @param int $user_id User ID. |
2045 * @param object $old_user_data Object containing user's data prior to update. |
1762 * @param WP_User $old_user_data Object containing user's data prior to update. |
2046 */ |
1763 */ |
2047 do_action( 'profile_update', $user_id, $old_user_data ); |
1764 do_action( 'profile_update', $user_id, $old_user_data ); |
2048 } else { |
1765 } else { |
2049 /** |
1766 /** |
2050 * Fires immediately after a new user is registered. |
1767 * Fires immediately after a new user is registered. |
2070 * |
1787 * |
2071 * @since 2.0.0 |
1788 * @since 2.0.0 |
2072 * |
1789 * |
2073 * @see wp_insert_user() For what fields can be set in $userdata. |
1790 * @see wp_insert_user() For what fields can be set in $userdata. |
2074 * |
1791 * |
2075 * @param mixed $userdata An array of user data or a user object of type stdClass or WP_User. |
1792 * @param object|WP_User $userdata An array of user data or a user object of type stdClass or WP_User. |
2076 * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated. |
1793 * @return int|WP_Error The updated user's ID or a WP_Error object if the user could not be updated. |
2077 */ |
1794 */ |
2078 function wp_update_user($userdata) { |
1795 function wp_update_user($userdata) { |
2079 if ( $userdata instanceof stdClass ) { |
1796 if ( $userdata instanceof stdClass ) { |
2080 $userdata = get_object_vars( $userdata ); |
1797 $userdata = get_object_vars( $userdata ); |
2101 } |
1818 } |
2102 |
1819 |
2103 // Escape data pulled from DB. |
1820 // Escape data pulled from DB. |
2104 $user = add_magic_quotes( $user ); |
1821 $user = add_magic_quotes( $user ); |
2105 |
1822 |
2106 // If password is changing, hash it now. |
1823 if ( ! empty( $userdata['user_pass'] ) && $userdata['user_pass'] !== $user_obj->user_pass ) { |
2107 if ( ! empty($userdata['user_pass']) ) { |
1824 // If password is changing, hash it now |
2108 $plaintext_pass = $userdata['user_pass']; |
1825 $plaintext_pass = $userdata['user_pass']; |
2109 $userdata['user_pass'] = wp_hash_password($userdata['user_pass']); |
1826 $userdata['user_pass'] = wp_hash_password( $userdata['user_pass'] ); |
2110 } |
1827 |
2111 |
1828 /** |
2112 wp_cache_delete($user[ 'user_email' ], 'useremail'); |
1829 * Filters whether to send the password change email. |
1830 * |
|
1831 * @since 4.3.0 |
|
1832 * |
|
1833 * @see wp_insert_user() For `$user` and `$userdata` fields. |
|
1834 * |
|
1835 * @param bool $send Whether to send the email. |
|
1836 * @param array $user The original user array. |
|
1837 * @param array $userdata The updated user array. |
|
1838 * |
|
1839 */ |
|
1840 $send_password_change_email = apply_filters( 'send_password_change_email', true, $user, $userdata ); |
|
1841 } |
|
1842 |
|
1843 if ( isset( $userdata['user_email'] ) && $user['user_email'] !== $userdata['user_email'] ) { |
|
1844 /** |
|
1845 * Filters whether to send the email change email. |
|
1846 * |
|
1847 * @since 4.3.0 |
|
1848 * |
|
1849 * @see wp_insert_user() For `$user` and `$userdata` fields. |
|
1850 * |
|
1851 * @param bool $send Whether to send the email. |
|
1852 * @param array $user The original user array. |
|
1853 * @param array $userdata The updated user array. |
|
1854 * |
|
1855 */ |
|
1856 $send_email_change_email = apply_filters( 'send_email_change_email', true, $user, $userdata ); |
|
1857 } |
|
1858 |
|
1859 wp_cache_delete( $user['user_email'], 'useremail' ); |
|
1860 wp_cache_delete( $user['user_nicename'], 'userslugs' ); |
|
2113 |
1861 |
2114 // Merge old and new fields with new fields overwriting old ones. |
1862 // Merge old and new fields with new fields overwriting old ones. |
2115 $userdata = array_merge($user, $userdata); |
1863 $userdata = array_merge( $user, $userdata ); |
2116 $user_id = wp_insert_user($userdata); |
1864 $user_id = wp_insert_user( $userdata ); |
1865 |
|
1866 if ( ! is_wp_error( $user_id ) ) { |
|
1867 |
|
1868 $blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); |
|
1869 |
|
1870 $switched_locale = false; |
|
1871 if ( ! empty( $send_password_change_email ) || ! empty( $send_email_change_email ) ) { |
|
1872 $switched_locale = switch_to_locale( get_user_locale( $user_id ) ); |
|
1873 } |
|
1874 |
|
1875 if ( ! empty( $send_password_change_email ) ) { |
|
1876 /* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */ |
|
1877 $pass_change_text = __( 'Hi ###USERNAME###, |
|
1878 |
|
1879 This notice confirms that your password was changed on ###SITENAME###. |
|
1880 |
|
1881 If you did not change your password, please contact the Site Administrator at |
|
1882 ###ADMIN_EMAIL### |
|
1883 |
|
1884 This email has been sent to ###EMAIL### |
|
1885 |
|
1886 Regards, |
|
1887 All at ###SITENAME### |
|
1888 ###SITEURL###' ); |
|
1889 |
|
1890 $pass_change_email = array( |
|
1891 'to' => $user['user_email'], |
|
1892 /* translators: User password change notification email subject. 1: Site name */ |
|
1893 'subject' => __( '[%s] Notice of Password Change' ), |
|
1894 'message' => $pass_change_text, |
|
1895 'headers' => '', |
|
1896 ); |
|
1897 |
|
1898 /** |
|
1899 * Filters the contents of the email sent when the user's password is changed. |
|
1900 * |
|
1901 * @since 4.3.0 |
|
1902 * |
|
1903 * @param array $pass_change_email { |
|
1904 * Used to build wp_mail(). |
|
1905 * @type string $to The intended recipients. Add emails in a comma separated string. |
|
1906 * @type string $subject The subject of the email. |
|
1907 * @type string $message The content of the email. |
|
1908 * The following strings have a special meaning and will get replaced dynamically: |
|
1909 * - ###USERNAME### The current user's username. |
|
1910 * - ###ADMIN_EMAIL### The admin email in case this was unexpected. |
|
1911 * - ###EMAIL### The user's email address. |
|
1912 * - ###SITENAME### The name of the site. |
|
1913 * - ###SITEURL### The URL to the site. |
|
1914 * @type string $headers Headers. Add headers in a newline (\r\n) separated string. |
|
1915 * } |
|
1916 * @param array $user The original user array. |
|
1917 * @param array $userdata The updated user array. |
|
1918 * |
|
1919 */ |
|
1920 $pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata ); |
|
1921 |
|
1922 $pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] ); |
|
1923 $pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] ); |
|
1924 $pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] ); |
|
1925 $pass_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $pass_change_email['message'] ); |
|
1926 $pass_change_email['message'] = str_replace( '###SITEURL###', home_url(), $pass_change_email['message'] ); |
|
1927 |
|
1928 wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] ); |
|
1929 } |
|
1930 |
|
1931 if ( ! empty( $send_email_change_email ) ) { |
|
1932 /* translators: Do not translate USERNAME, ADMIN_EMAIL, NEW_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */ |
|
1933 $email_change_text = __( 'Hi ###USERNAME###, |
|
1934 |
|
1935 This notice confirms that your email address on ###SITENAME### was changed to ###NEW_EMAIL###. |
|
1936 |
|
1937 If you did not change your email, please contact the Site Administrator at |
|
1938 ###ADMIN_EMAIL### |
|
1939 |
|
1940 This email has been sent to ###EMAIL### |
|
1941 |
|
1942 Regards, |
|
1943 All at ###SITENAME### |
|
1944 ###SITEURL###' ); |
|
1945 |
|
1946 $email_change_email = array( |
|
1947 'to' => $user['user_email'], |
|
1948 /* translators: User email change notification email subject. 1: Site name */ |
|
1949 'subject' => __( '[%s] Notice of Email Change' ), |
|
1950 'message' => $email_change_text, |
|
1951 'headers' => '', |
|
1952 ); |
|
1953 |
|
1954 /** |
|
1955 * Filters the contents of the email sent when the user's email is changed. |
|
1956 * |
|
1957 * @since 4.3.0 |
|
1958 * |
|
1959 * @param array $email_change_email { |
|
1960 * Used to build wp_mail(). |
|
1961 * @type string $to The intended recipients. |
|
1962 * @type string $subject The subject of the email. |
|
1963 * @type string $message The content of the email. |
|
1964 * The following strings have a special meaning and will get replaced dynamically: |
|
1965 * - ###USERNAME### The current user's username. |
|
1966 * - ###ADMIN_EMAIL### The admin email in case this was unexpected. |
|
1967 * - ###NEW_EMAIL### The new email address. |
|
1968 * - ###EMAIL### The old email address. |
|
1969 * - ###SITENAME### The name of the site. |
|
1970 * - ###SITEURL### The URL to the site. |
|
1971 * @type string $headers Headers. |
|
1972 * } |
|
1973 * @param array $user The original user array. |
|
1974 * @param array $userdata The updated user array. |
|
1975 */ |
|
1976 $email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata ); |
|
1977 |
|
1978 $email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] ); |
|
1979 $email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] ); |
|
1980 $email_change_email['message'] = str_replace( '###NEW_EMAIL###', $userdata['user_email'], $email_change_email['message'] ); |
|
1981 $email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] ); |
|
1982 $email_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $email_change_email['message'] ); |
|
1983 $email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] ); |
|
1984 |
|
1985 wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] ); |
|
1986 } |
|
1987 |
|
1988 if ( $switched_locale ) { |
|
1989 restore_previous_locale(); |
|
1990 } |
|
1991 } |
|
2117 |
1992 |
2118 // Update the cookies if the password changed. |
1993 // Update the cookies if the password changed. |
2119 $current_user = wp_get_current_user(); |
1994 $current_user = wp_get_current_user(); |
2120 if ( $current_user->ID == $ID ) { |
1995 if ( $current_user->ID == $ID ) { |
2121 if ( isset($plaintext_pass) ) { |
1996 if ( isset($plaintext_pass) ) { |
2137 |
2012 |
2138 /** |
2013 /** |
2139 * A simpler way of inserting a user into the database. |
2014 * A simpler way of inserting a user into the database. |
2140 * |
2015 * |
2141 * Creates a new user with just the username, password, and email. For more |
2016 * Creates a new user with just the username, password, and email. For more |
2142 * complex user creation use {@see wp_insert_user()} to specify more information. |
2017 * complex user creation use wp_insert_user() to specify more information. |
2143 * |
2018 * |
2144 * @since 2.0.0 |
2019 * @since 2.0.0 |
2145 * @see wp_insert_user() More complete way to create a new user |
2020 * @see wp_insert_user() More complete way to create a new user |
2146 * |
2021 * |
2147 * @param string $username The user's username. |
2022 * @param string $username The user's username. |
2148 * @param string $password The user's password. |
2023 * @param string $password The user's password. |
2149 * @param string $email Optional. The user's email. Default empty. |
2024 * @param string $email Optional. The user's email. Default empty. |
2150 * @return int The new user's ID. |
2025 * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not |
2026 * be created. |
|
2151 */ |
2027 */ |
2152 function wp_create_user($username, $password, $email = '') { |
2028 function wp_create_user($username, $password, $email = '') { |
2153 $user_login = wp_slash( $username ); |
2029 $user_login = wp_slash( $username ); |
2154 $user_email = wp_slash( $email ); |
2030 $user_email = wp_slash( $email ); |
2155 $user_pass = $password; |
2031 $user_pass = $password; |
2157 $userdata = compact('user_login', 'user_email', 'user_pass'); |
2033 $userdata = compact('user_login', 'user_email', 'user_pass'); |
2158 return wp_insert_user($userdata); |
2034 return wp_insert_user($userdata); |
2159 } |
2035 } |
2160 |
2036 |
2161 /** |
2037 /** |
2162 * Return a list of meta keys that wp_insert_user() is supposed to set. |
2038 * Returns a list of meta keys to be (maybe) populated in wp_update_user(). |
2039 * |
|
2040 * The list of keys returned via this function are dependent on the presence |
|
2041 * of those keys in the user meta data to be set. |
|
2163 * |
2042 * |
2164 * @since 3.3.0 |
2043 * @since 3.3.0 |
2165 * @access private |
2044 * @access private |
2166 * |
2045 * |
2167 * @param WP_User $user WP_User instance. |
2046 * @param WP_User $user WP_User instance. |
2168 * @return array |
2047 * @return array List of user keys to be populated in wp_update_user(). |
2169 */ |
2048 */ |
2170 function _get_additional_user_keys( $user ) { |
2049 function _get_additional_user_keys( $user ) { |
2171 $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front' ); |
2050 $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front', 'locale' ); |
2172 return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) ); |
2051 return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) ); |
2173 } |
2052 } |
2174 |
2053 |
2175 /** |
2054 /** |
2176 * Set up the user contact methods. |
2055 * Set up the user contact methods. |
2191 'jabber' => __( 'Jabber / Google Talk' ) |
2070 'jabber' => __( 'Jabber / Google Talk' ) |
2192 ); |
2071 ); |
2193 } |
2072 } |
2194 |
2073 |
2195 /** |
2074 /** |
2196 * Filter the user contact methods. |
2075 * Filters the user contact methods. |
2197 * |
2076 * |
2198 * @since 2.9.0 |
2077 * @since 2.9.0 |
2199 * |
2078 * |
2200 * @param array $methods Array of contact methods and their labels. |
2079 * @param array $methods Array of contact methods and their labels. |
2201 * @param WP_User $user WP_User object. |
2080 * @param WP_User $user WP_User object. |
2204 } |
2083 } |
2205 |
2084 |
2206 /** |
2085 /** |
2207 * The old private function for setting up user contact methods. |
2086 * The old private function for setting up user contact methods. |
2208 * |
2087 * |
2088 * Use wp_get_user_contact_methods() instead. |
|
2089 * |
|
2209 * @since 2.9.0 |
2090 * @since 2.9.0 |
2210 * @access private |
2091 * @access private |
2092 * |
|
2093 * @param WP_User $user Optional. WP_User object. Default null. |
|
2094 * @return array Array of contact methods and their labels. |
|
2211 */ |
2095 */ |
2212 function _wp_get_user_contactmethods( $user = null ) { |
2096 function _wp_get_user_contactmethods( $user = null ) { |
2213 return wp_get_user_contact_methods( $user ); |
2097 return wp_get_user_contact_methods( $user ); |
2214 } |
2098 } |
2215 |
2099 |
2219 * @since 4.1.0 |
2103 * @since 4.1.0 |
2220 * |
2104 * |
2221 * @return string The password hint text. |
2105 * @return string The password hint text. |
2222 */ |
2106 */ |
2223 function wp_get_password_hint() { |
2107 function wp_get_password_hint() { |
2224 $hint = __( 'Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers, and symbols like ! " ? $ % ^ & ).' ); |
2108 $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 ! " ? $ % ^ & ).' ); |
2225 |
2109 |
2226 /** |
2110 /** |
2227 * Filter the text describing the site's password complexity policy. |
2111 * Filters the text describing the site's password complexity policy. |
2228 * |
2112 * |
2229 * @since 4.1.0 |
2113 * @since 4.1.0 |
2230 * |
2114 * |
2231 * @param string $hint The password hint text. |
2115 * @param string $hint The password hint text. |
2232 */ |
2116 */ |
2233 return apply_filters( 'password_hint', $hint ); |
2117 return apply_filters( 'password_hint', $hint ); |
2118 } |
|
2119 |
|
2120 /** |
|
2121 * Creates, stores, then returns a password reset key for user. |
|
2122 * |
|
2123 * @since 4.4.0 |
|
2124 * |
|
2125 * @global wpdb $wpdb WordPress database abstraction object. |
|
2126 * @global PasswordHash $wp_hasher Portable PHP password hashing framework. |
|
2127 * |
|
2128 * @param WP_User $user User to retrieve password reset key for. |
|
2129 * |
|
2130 * @return string|WP_Error Password reset key on success. WP_Error on error. |
|
2131 */ |
|
2132 function get_password_reset_key( $user ) { |
|
2133 global $wpdb, $wp_hasher; |
|
2134 |
|
2135 /** |
|
2136 * Fires before a new password is retrieved. |
|
2137 * |
|
2138 * Use the {@see 'retrieve_password'} hook instead. |
|
2139 * |
|
2140 * @since 1.5.0 |
|
2141 * @deprecated 1.5.1 Misspelled. Use 'retrieve_password' hook instead. |
|
2142 * |
|
2143 * @param string $user_login The user login name. |
|
2144 */ |
|
2145 do_action( 'retreive_password', $user->user_login ); |
|
2146 |
|
2147 /** |
|
2148 * Fires before a new password is retrieved. |
|
2149 * |
|
2150 * @since 1.5.1 |
|
2151 * |
|
2152 * @param string $user_login The user login name. |
|
2153 */ |
|
2154 do_action( 'retrieve_password', $user->user_login ); |
|
2155 |
|
2156 $allow = true; |
|
2157 if ( is_multisite() && is_user_spammy( $user ) ) { |
|
2158 $allow = false; |
|
2159 } |
|
2160 |
|
2161 /** |
|
2162 * Filters whether to allow a password to be reset. |
|
2163 * |
|
2164 * @since 2.7.0 |
|
2165 * |
|
2166 * @param bool $allow Whether to allow the password to be reset. Default true. |
|
2167 * @param int $user_data->ID The ID of the user attempting to reset a password. |
|
2168 */ |
|
2169 $allow = apply_filters( 'allow_password_reset', $allow, $user->ID ); |
|
2170 |
|
2171 if ( ! $allow ) { |
|
2172 return new WP_Error( 'no_password_reset', __( 'Password reset is not allowed for this user' ) ); |
|
2173 } elseif ( is_wp_error( $allow ) ) { |
|
2174 return $allow; |
|
2175 } |
|
2176 |
|
2177 // Generate something random for a password reset key. |
|
2178 $key = wp_generate_password( 20, false ); |
|
2179 |
|
2180 /** |
|
2181 * Fires when a password reset key is generated. |
|
2182 * |
|
2183 * @since 2.5.0 |
|
2184 * |
|
2185 * @param string $user_login The username for the user. |
|
2186 * @param string $key The generated password reset key. |
|
2187 */ |
|
2188 do_action( 'retrieve_password_key', $user->user_login, $key ); |
|
2189 |
|
2190 // Now insert the key, hashed, into the DB. |
|
2191 if ( empty( $wp_hasher ) ) { |
|
2192 require_once ABSPATH . WPINC . '/class-phpass.php'; |
|
2193 $wp_hasher = new PasswordHash( 8, true ); |
|
2194 } |
|
2195 $hashed = time() . ':' . $wp_hasher->HashPassword( $key ); |
|
2196 $key_saved = $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) ); |
|
2197 if ( false === $key_saved ) { |
|
2198 return new WP_Error( 'no_password_key_update', __( 'Could not save password reset key to database.' ) ); |
|
2199 } |
|
2200 |
|
2201 return $key; |
|
2234 } |
2202 } |
2235 |
2203 |
2236 /** |
2204 /** |
2237 * Retrieves a user row based on password reset key and login |
2205 * Retrieves a user row based on password reset key and login |
2238 * |
2206 * |
2239 * A key is considered 'expired' if it exactly matches the value of the |
2207 * A key is considered 'expired' if it exactly matches the value of the |
2240 * user_activation_key field, rather than being matched after going through the |
2208 * user_activation_key field, rather than being matched after going through the |
2241 * hashing process. This field is now hashed; old values are no longer accepted |
2209 * hashing process. This field is now hashed; old values are no longer accepted |
2242 * but have a different WP_Error code so good user feedback can be provided. |
2210 * but have a different WP_Error code so good user feedback can be provided. |
2243 * |
2211 * |
2212 * @since 3.1.0 |
|
2213 * |
|
2244 * @global wpdb $wpdb WordPress database object for queries. |
2214 * @global wpdb $wpdb WordPress database object for queries. |
2245 * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance. |
2215 * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance. |
2246 * |
2216 * |
2247 * @param string $key Hash to validate sending user's password. |
2217 * @param string $key Hash to validate sending user's password. |
2248 * @param string $login The user login. |
2218 * @param string $login The user login. |
2266 if ( empty( $wp_hasher ) ) { |
2236 if ( empty( $wp_hasher ) ) { |
2267 require_once ABSPATH . WPINC . '/class-phpass.php'; |
2237 require_once ABSPATH . WPINC . '/class-phpass.php'; |
2268 $wp_hasher = new PasswordHash( 8, true ); |
2238 $wp_hasher = new PasswordHash( 8, true ); |
2269 } |
2239 } |
2270 |
2240 |
2271 if ( $wp_hasher->CheckPassword( $key, $row->user_activation_key ) ) |
2241 /** |
2242 * Filters the expiration time of password reset keys. |
|
2243 * |
|
2244 * @since 4.3.0 |
|
2245 * |
|
2246 * @param int $expiration The expiration time in seconds. |
|
2247 */ |
|
2248 $expiration_duration = apply_filters( 'password_reset_expiration', DAY_IN_SECONDS ); |
|
2249 |
|
2250 if ( false !== strpos( $row->user_activation_key, ':' ) ) { |
|
2251 list( $pass_request_time, $pass_key ) = explode( ':', $row->user_activation_key, 2 ); |
|
2252 $expiration_time = $pass_request_time + $expiration_duration; |
|
2253 } else { |
|
2254 $pass_key = $row->user_activation_key; |
|
2255 $expiration_time = false; |
|
2256 } |
|
2257 |
|
2258 if ( ! $pass_key ) { |
|
2259 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); |
|
2260 } |
|
2261 |
|
2262 $hash_is_correct = $wp_hasher->CheckPassword( $key, $pass_key ); |
|
2263 |
|
2264 if ( $hash_is_correct && $expiration_time && time() < $expiration_time ) { |
|
2272 return get_userdata( $row->ID ); |
2265 return get_userdata( $row->ID ); |
2273 |
2266 } elseif ( $hash_is_correct && $expiration_time ) { |
2274 if ( $key === $row->user_activation_key ) { |
2267 // Key has an expiration time that's passed |
2268 return new WP_Error( 'expired_key', __( 'Invalid key' ) ); |
|
2269 } |
|
2270 |
|
2271 if ( hash_equals( $row->user_activation_key, $key ) || ( $hash_is_correct && ! $expiration_time ) ) { |
|
2275 $return = new WP_Error( 'expired_key', __( 'Invalid key' ) ); |
2272 $return = new WP_Error( 'expired_key', __( 'Invalid key' ) ); |
2276 $user_id = $row->ID; |
2273 $user_id = $row->ID; |
2277 |
2274 |
2278 /** |
2275 /** |
2279 * Filter the return value of check_password_reset_key() when an |
2276 * Filters the return value of check_password_reset_key() when an |
2280 * old-style key is used (plain-text key was stored in the database). |
2277 * old-style key is used. |
2281 * |
2278 * |
2282 * @since 3.7.0 |
2279 * @since 3.7.0 Previously plain-text keys were stored in the database. |
2280 * @since 4.3.0 Previously key hashes were stored without an expiration time. |
|
2283 * |
2281 * |
2284 * @param WP_Error $return A WP_Error object denoting an expired key. |
2282 * @param WP_Error $return A WP_Error object denoting an expired key. |
2285 * Return a WP_User object to validate the key. |
2283 * Return a WP_User object to validate the key. |
2286 * @param int $user_id The matched user ID. |
2284 * @param int $user_id The matched user ID. |
2287 */ |
2285 */ |
2292 } |
2290 } |
2293 |
2291 |
2294 /** |
2292 /** |
2295 * Handles resetting the user's password. |
2293 * Handles resetting the user's password. |
2296 * |
2294 * |
2297 * @param object $user The user |
2295 * @since 2.5.0 |
2296 * |
|
2297 * @param WP_User $user The user |
|
2298 * @param string $new_pass New password for the user in plaintext |
2298 * @param string $new_pass New password for the user in plaintext |
2299 */ |
2299 */ |
2300 function reset_password( $user, $new_pass ) { |
2300 function reset_password( $user, $new_pass ) { |
2301 /** |
2301 /** |
2302 * Fires before the user's password is reset. |
2302 * Fires before the user's password is reset. |
2309 do_action( 'password_reset', $user, $new_pass ); |
2309 do_action( 'password_reset', $user, $new_pass ); |
2310 |
2310 |
2311 wp_set_password( $new_pass, $user->ID ); |
2311 wp_set_password( $new_pass, $user->ID ); |
2312 update_user_option( $user->ID, 'default_password_nag', false, true ); |
2312 update_user_option( $user->ID, 'default_password_nag', false, true ); |
2313 |
2313 |
2314 wp_password_change_notification( $user ); |
2314 /** |
2315 * Fires after the user's password is reset. |
|
2316 * |
|
2317 * @since 4.4.0 |
|
2318 * |
|
2319 * @param WP_User $user The user. |
|
2320 * @param string $new_pass New user password. |
|
2321 */ |
|
2322 do_action( 'after_password_reset', $user, $new_pass ); |
|
2315 } |
2323 } |
2316 |
2324 |
2317 /** |
2325 /** |
2318 * Handles registering a new user. |
2326 * Handles registering a new user. |
2327 * |
|
2328 * @since 2.5.0 |
|
2319 * |
2329 * |
2320 * @param string $user_login User's username for logging in |
2330 * @param string $user_login User's username for logging in |
2321 * @param string $user_email User's email address to send password and add |
2331 * @param string $user_email User's email address to send password and add |
2322 * @return int|WP_Error Either user's ID or error on failure. |
2332 * @return int|WP_Error Either user's ID or error on failure. |
2323 */ |
2333 */ |
2324 function register_new_user( $user_login, $user_email ) { |
2334 function register_new_user( $user_login, $user_email ) { |
2325 $errors = new WP_Error(); |
2335 $errors = new WP_Error(); |
2326 |
2336 |
2327 $sanitized_user_login = sanitize_user( $user_login ); |
2337 $sanitized_user_login = sanitize_user( $user_login ); |
2328 /** |
2338 /** |
2329 * Filter the email address of a user being registered. |
2339 * Filters the email address of a user being registered. |
2330 * |
2340 * |
2331 * @since 2.1.0 |
2341 * @since 2.1.0 |
2332 * |
2342 * |
2333 * @param string $user_email The email address of the new user. |
2343 * @param string $user_email The email address of the new user. |
2334 */ |
2344 */ |
2340 } elseif ( ! validate_username( $user_login ) ) { |
2350 } elseif ( ! validate_username( $user_login ) ) { |
2341 $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) ); |
2351 $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) ); |
2342 $sanitized_user_login = ''; |
2352 $sanitized_user_login = ''; |
2343 } elseif ( username_exists( $sanitized_user_login ) ) { |
2353 } elseif ( username_exists( $sanitized_user_login ) ) { |
2344 $errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ) ); |
2354 $errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ) ); |
2345 } |
2355 |
2346 |
2356 } else { |
2347 // Check the e-mail address |
2357 /** This filter is documented in wp-includes/user.php */ |
2358 $illegal_user_logins = array_map( 'strtolower', (array) apply_filters( 'illegal_user_logins', array() ) ); |
|
2359 if ( in_array( strtolower( $sanitized_user_login ), $illegal_user_logins ) ) { |
|
2360 $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: Sorry, that username is not allowed.' ) ); |
|
2361 } |
|
2362 } |
|
2363 |
|
2364 // Check the email address |
|
2348 if ( $user_email == '' ) { |
2365 if ( $user_email == '' ) { |
2349 $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your e-mail address.' ) ); |
2366 $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your email address.' ) ); |
2350 } elseif ( ! is_email( $user_email ) ) { |
2367 } elseif ( ! is_email( $user_email ) ) { |
2351 $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn’t correct.' ) ); |
2368 $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn’t correct.' ) ); |
2352 $user_email = ''; |
2369 $user_email = ''; |
2353 } elseif ( email_exists( $user_email ) ) { |
2370 } elseif ( email_exists( $user_email ) ) { |
2354 $errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) ); |
2371 $errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) ); |
2366 * or an existing username or email. |
2383 * or an existing username or email. |
2367 */ |
2384 */ |
2368 do_action( 'register_post', $sanitized_user_login, $user_email, $errors ); |
2385 do_action( 'register_post', $sanitized_user_login, $user_email, $errors ); |
2369 |
2386 |
2370 /** |
2387 /** |
2371 * Filter the errors encountered when a new user is being registered. |
2388 * Filters the errors encountered when a new user is being registered. |
2372 * |
2389 * |
2373 * The filtered WP_Error object may, for example, contain errors for an invalid |
2390 * The filtered WP_Error object may, for example, contain errors for an invalid |
2374 * or existing username or email address. A WP_Error object should always returned, |
2391 * or existing username or email address. A WP_Error object should always returned, |
2375 * but may or may not contain errors. |
2392 * but may or may not contain errors. |
2376 * |
2393 * |
2395 return $errors; |
2412 return $errors; |
2396 } |
2413 } |
2397 |
2414 |
2398 update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag. |
2415 update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag. |
2399 |
2416 |
2400 wp_new_user_notification( $user_id, $user_pass ); |
2417 /** |
2418 * Fires after a new user registration has been recorded. |
|
2419 * |
|
2420 * @since 4.4.0 |
|
2421 * |
|
2422 * @param int $user_id ID of the newly registered user. |
|
2423 */ |
|
2424 do_action( 'register_new_user', $user_id ); |
|
2401 |
2425 |
2402 return $user_id; |
2426 return $user_id; |
2427 } |
|
2428 |
|
2429 /** |
|
2430 * Initiates email notifications related to the creation of new users. |
|
2431 * |
|
2432 * Notifications are sent both to the site admin and to the newly created user. |
|
2433 * |
|
2434 * @since 4.4.0 |
|
2435 * @since 4.6.0 Converted the `$notify` parameter to accept 'user' for sending |
|
2436 * notifications only to the user created. |
|
2437 * |
|
2438 * @param int $user_id ID of the newly created user. |
|
2439 * @param string $notify Optional. Type of notification that should happen. Accepts 'admin' |
|
2440 * or an empty string (admin only), 'user', or 'both' (admin and user). |
|
2441 * Default 'both'. |
|
2442 */ |
|
2443 function wp_send_new_user_notifications( $user_id, $notify = 'both' ) { |
|
2444 wp_new_user_notification( $user_id, null, $notify ); |
|
2403 } |
2445 } |
2404 |
2446 |
2405 /** |
2447 /** |
2406 * Retrieve the current session token from the logged_in cookie. |
2448 * Retrieve the current session token from the logged_in cookie. |
2407 * |
2449 * |
2458 */ |
2500 */ |
2459 function wp_destroy_all_sessions() { |
2501 function wp_destroy_all_sessions() { |
2460 $manager = WP_Session_Tokens::get_instance( get_current_user_id() ); |
2502 $manager = WP_Session_Tokens::get_instance( get_current_user_id() ); |
2461 $manager->destroy_all(); |
2503 $manager->destroy_all(); |
2462 } |
2504 } |
2505 |
|
2506 /** |
|
2507 * Get the user IDs of all users with no role on this site. |
|
2508 * |
|
2509 * @since 4.4.0 |
|
2510 * @since 4.9.0 The `$site_id` parameter was added to support multisite. |
|
2511 * |
|
2512 * @param int|null $site_id Optional. The site ID to get users with no role for. Defaults to the current site. |
|
2513 * @return array Array of user IDs. |
|
2514 */ |
|
2515 function wp_get_users_with_no_role( $site_id = null ) { |
|
2516 global $wpdb; |
|
2517 |
|
2518 if ( ! $site_id ) { |
|
2519 $site_id = get_current_blog_id(); |
|
2520 } |
|
2521 |
|
2522 $prefix = $wpdb->get_blog_prefix( $site_id ); |
|
2523 |
|
2524 if ( is_multisite() && $site_id != get_current_blog_id() ) { |
|
2525 switch_to_blog( $site_id ); |
|
2526 $role_names = wp_roles()->get_names(); |
|
2527 restore_current_blog(); |
|
2528 } else { |
|
2529 $role_names = wp_roles()->get_names(); |
|
2530 } |
|
2531 |
|
2532 $regex = implode( '|', array_keys( $role_names ) ); |
|
2533 $regex = preg_replace( '/[^a-zA-Z_\|-]/', '', $regex ); |
|
2534 $users = $wpdb->get_col( $wpdb->prepare( " |
|
2535 SELECT user_id |
|
2536 FROM $wpdb->usermeta |
|
2537 WHERE meta_key = '{$prefix}capabilities' |
|
2538 AND meta_value NOT REGEXP %s |
|
2539 ", $regex ) ); |
|
2540 |
|
2541 return $users; |
|
2542 } |
|
2543 |
|
2544 /** |
|
2545 * Retrieves the current user object. |
|
2546 * |
|
2547 * Will set the current user, if the current user is not set. The current user |
|
2548 * will be set to the logged-in person. If no user is logged-in, then it will |
|
2549 * set the current user to 0, which is invalid and won't have any permissions. |
|
2550 * |
|
2551 * This function is used by the pluggable functions wp_get_current_user() and |
|
2552 * get_currentuserinfo(), the latter of which is deprecated but used for backward |
|
2553 * compatibility. |
|
2554 * |
|
2555 * @since 4.5.0 |
|
2556 * @access private |
|
2557 * |
|
2558 * @see wp_get_current_user() |
|
2559 * @global WP_User $current_user Checks if the current user is set. |
|
2560 * |
|
2561 * @return WP_User Current WP_User instance. |
|
2562 */ |
|
2563 function _wp_get_current_user() { |
|
2564 global $current_user; |
|
2565 |
|
2566 if ( ! empty( $current_user ) ) { |
|
2567 if ( $current_user instanceof WP_User ) { |
|
2568 return $current_user; |
|
2569 } |
|
2570 |
|
2571 // Upgrade stdClass to WP_User |
|
2572 if ( is_object( $current_user ) && isset( $current_user->ID ) ) { |
|
2573 $cur_id = $current_user->ID; |
|
2574 $current_user = null; |
|
2575 wp_set_current_user( $cur_id ); |
|
2576 return $current_user; |
|
2577 } |
|
2578 |
|
2579 // $current_user has a junk value. Force to WP_User with ID 0. |
|
2580 $current_user = null; |
|
2581 wp_set_current_user( 0 ); |
|
2582 return $current_user; |
|
2583 } |
|
2584 |
|
2585 if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) { |
|
2586 wp_set_current_user( 0 ); |
|
2587 return $current_user; |
|
2588 } |
|
2589 |
|
2590 /** |
|
2591 * Filters the current user. |
|
2592 * |
|
2593 * The default filters use this to determine the current user from the |
|
2594 * request's cookies, if available. |
|
2595 * |
|
2596 * Returning a value of false will effectively short-circuit setting |
|
2597 * the current user. |
|
2598 * |
|
2599 * @since 3.9.0 |
|
2600 * |
|
2601 * @param int|bool $user_id User ID if one has been determined, false otherwise. |
|
2602 */ |
|
2603 $user_id = apply_filters( 'determine_current_user', false ); |
|
2604 if ( ! $user_id ) { |
|
2605 wp_set_current_user( 0 ); |
|
2606 return $current_user; |
|
2607 } |
|
2608 |
|
2609 wp_set_current_user( $user_id ); |
|
2610 |
|
2611 return $current_user; |
|
2612 } |
|
2613 |
|
2614 /** |
|
2615 * Send a confirmation request email when a change of user email address is attempted. |
|
2616 * |
|
2617 * @since 3.0.0 |
|
2618 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. |
|
2619 * |
|
2620 * @global WP_Error $errors WP_Error object. |
|
2621 * @global wpdb $wpdb WordPress database object. |
|
2622 */ |
|
2623 function send_confirmation_on_profile_email() { |
|
2624 global $errors, $wpdb; |
|
2625 |
|
2626 $current_user = wp_get_current_user(); |
|
2627 if ( ! is_object( $errors ) ) { |
|
2628 $errors = new WP_Error(); |
|
2629 } |
|
2630 |
|
2631 if ( $current_user->ID != $_POST['user_id'] ) { |
|
2632 return false; |
|
2633 } |
|
2634 |
|
2635 if ( $current_user->user_email != $_POST['email'] ) { |
|
2636 if ( ! is_email( $_POST['email'] ) ) { |
|
2637 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn’t correct." ), array( |
|
2638 'form-field' => 'email', |
|
2639 ) ); |
|
2640 |
|
2641 return; |
|
2642 } |
|
2643 |
|
2644 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) { |
|
2645 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( |
|
2646 'form-field' => 'email', |
|
2647 ) ); |
|
2648 delete_user_meta( $current_user->ID, '_new_email' ); |
|
2649 |
|
2650 return; |
|
2651 } |
|
2652 |
|
2653 $hash = md5( $_POST['email'] . time() . wp_rand() ); |
|
2654 $new_user_email = array( |
|
2655 'hash' => $hash, |
|
2656 'newemail' => $_POST['email'], |
|
2657 ); |
|
2658 update_user_meta( $current_user->ID, '_new_email', $new_user_email ); |
|
2659 |
|
2660 $sitename = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); |
|
2661 |
|
2662 /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ |
|
2663 $email_text = __( 'Howdy ###USERNAME###, |
|
2664 |
|
2665 You recently requested to have the email address on your account changed. |
|
2666 |
|
2667 If this is correct, please click on the following link to change it: |
|
2668 ###ADMIN_URL### |
|
2669 |
|
2670 You can safely ignore and delete this email if you do not want to |
|
2671 take this action. |
|
2672 |
|
2673 This email has been sent to ###EMAIL### |
|
2674 |
|
2675 Regards, |
|
2676 All at ###SITENAME### |
|
2677 ###SITEURL###' ); |
|
2678 |
|
2679 /** |
|
2680 * Filters the text of the email sent when a change of user email address is attempted. |
|
2681 * |
|
2682 * The following strings have a special meaning and will get replaced dynamically: |
|
2683 * ###USERNAME### The current user's username. |
|
2684 * ###ADMIN_URL### The link to click on to confirm the email change. |
|
2685 * ###EMAIL### The new email. |
|
2686 * ###SITENAME### The name of the site. |
|
2687 * ###SITEURL### The URL to the site. |
|
2688 * |
|
2689 * @since MU (3.0.0) |
|
2690 * @since 4.9.0 This filter is no longer Multisite specific. |
|
2691 * |
|
2692 * @param string $email_text Text in the email. |
|
2693 * @param array $new_user_email { |
|
2694 * Data relating to the new user email address. |
|
2695 * |
|
2696 * @type string $hash The secure hash used in the confirmation link URL. |
|
2697 * @type string $newemail The proposed new email address. |
|
2698 * } |
|
2699 */ |
|
2700 $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email ); |
|
2701 |
|
2702 $content = str_replace( '###USERNAME###', $current_user->user_login, $content ); |
|
2703 $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail=' . $hash ) ), $content ); |
|
2704 $content = str_replace( '###EMAIL###', $_POST['email'], $content ); |
|
2705 $content = str_replace( '###SITENAME###', $sitename, $content ); |
|
2706 $content = str_replace( '###SITEURL###', home_url(), $content ); |
|
2707 |
|
2708 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), $sitename ), $content ); |
|
2709 |
|
2710 $_POST['email'] = $current_user->user_email; |
|
2711 } |
|
2712 } |
|
2713 |
|
2714 /** |
|
2715 * Adds an admin notice alerting the user to check for confirmation request email |
|
2716 * after email address change. |
|
2717 * |
|
2718 * @since 3.0.0 |
|
2719 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. |
|
2720 * |
|
2721 * @global string $pagenow |
|
2722 */ |
|
2723 function new_user_email_admin_notice() { |
|
2724 global $pagenow; |
|
2725 if ( 'profile.php' === $pagenow && isset( $_GET['updated'] ) && $email = get_user_meta( get_current_user_id(), '_new_email', true ) ) { |
|
2726 /* translators: %s: New email address */ |
|
2727 echo '<div class="notice notice-info"><p>' . sprintf( __( 'Your email address has not been updated yet. Please check your inbox at %s for a confirmation email.' ), '<code>' . esc_html( $email['newemail'] ) . '</code>' ) . '</p></div>'; |
|
2728 } |
|
2729 } |
|
2730 |
|
2731 /** |
|
2732 * Get all user privacy request types. |
|
2733 * |
|
2734 * @since 4.9.6 |
|
2735 * @access private |
|
2736 * |
|
2737 * @return array List of core privacy action types. |
|
2738 */ |
|
2739 function _wp_privacy_action_request_types() { |
|
2740 return array( |
|
2741 'export_personal_data', |
|
2742 'remove_personal_data', |
|
2743 ); |
|
2744 } |
|
2745 |
|
2746 /** |
|
2747 * Registers the personal data exporter for users. |
|
2748 * |
|
2749 * @since 4.9.6 |
|
2750 * |
|
2751 * @param array $exporters An array of personal data exporters. |
|
2752 * @return array An array of personal data exporters. |
|
2753 */ |
|
2754 function wp_register_user_personal_data_exporter( $exporters ) { |
|
2755 $exporters['wordpress-user'] = array( |
|
2756 'exporter_friendly_name' => __( 'WordPress User' ), |
|
2757 'callback' => 'wp_user_personal_data_exporter', |
|
2758 ); |
|
2759 |
|
2760 return $exporters; |
|
2761 } |
|
2762 |
|
2763 /** |
|
2764 * Finds and exports personal data associated with an email address from the user and user_meta table. |
|
2765 * |
|
2766 * @since 4.9.6 |
|
2767 * |
|
2768 * @param string $email_address The users email address. |
|
2769 * @return array An array of personal data. |
|
2770 */ |
|
2771 function wp_user_personal_data_exporter( $email_address ) { |
|
2772 $email_address = trim( $email_address ); |
|
2773 |
|
2774 $data_to_export = array(); |
|
2775 |
|
2776 $user = get_user_by( 'email', $email_address ); |
|
2777 |
|
2778 if ( ! $user ) { |
|
2779 return array( |
|
2780 'data' => array(), |
|
2781 'done' => true, |
|
2782 ); |
|
2783 } |
|
2784 |
|
2785 $user_meta = get_user_meta( $user->ID ); |
|
2786 |
|
2787 $user_prop_to_export = array( |
|
2788 'ID' => __( 'User ID' ), |
|
2789 'user_login' => __( 'User Login Name' ), |
|
2790 'user_nicename' => __( 'User Nice Name' ), |
|
2791 'user_email' => __( 'User Email' ), |
|
2792 'user_url' => __( 'User URL' ), |
|
2793 'user_registered' => __( 'User Registration Date' ), |
|
2794 'display_name' => __( 'User Display Name' ), |
|
2795 'nickname' => __( 'User Nickname' ), |
|
2796 'first_name' => __( 'User First Name' ), |
|
2797 'last_name' => __( 'User Last Name' ), |
|
2798 'description' => __( 'User Description' ), |
|
2799 ); |
|
2800 |
|
2801 $user_data_to_export = array(); |
|
2802 |
|
2803 foreach ( $user_prop_to_export as $key => $name ) { |
|
2804 $value = ''; |
|
2805 |
|
2806 switch ( $key ) { |
|
2807 case 'ID': |
|
2808 case 'user_login': |
|
2809 case 'user_nicename': |
|
2810 case 'user_email': |
|
2811 case 'user_url': |
|
2812 case 'user_registered': |
|
2813 case 'display_name': |
|
2814 $value = $user->data->$key; |
|
2815 break; |
|
2816 case 'nickname': |
|
2817 case 'first_name': |
|
2818 case 'last_name': |
|
2819 case 'description': |
|
2820 $value = $user_meta[ $key ][0]; |
|
2821 break; |
|
2822 } |
|
2823 |
|
2824 if ( ! empty( $value ) ) { |
|
2825 $user_data_to_export[] = array( |
|
2826 'name' => $name, |
|
2827 'value' => $value, |
|
2828 ); |
|
2829 } |
|
2830 } |
|
2831 |
|
2832 $data_to_export[] = array( |
|
2833 'group_id' => 'user', |
|
2834 'group_label' => __( 'User' ), |
|
2835 'item_id' => "user-{$user->ID}", |
|
2836 'data' => $user_data_to_export, |
|
2837 ); |
|
2838 |
|
2839 return array( |
|
2840 'data' => $data_to_export, |
|
2841 'done' => true, |
|
2842 ); |
|
2843 } |
|
2844 |
|
2845 /** |
|
2846 * Update log when privacy request is confirmed. |
|
2847 * |
|
2848 * @since 4.9.6 |
|
2849 * @access private |
|
2850 * |
|
2851 * @param int $request_id ID of the request. |
|
2852 */ |
|
2853 function _wp_privacy_account_request_confirmed( $request_id ) { |
|
2854 $request_data = wp_get_user_request_data( $request_id ); |
|
2855 |
|
2856 if ( ! $request_data ) { |
|
2857 return; |
|
2858 } |
|
2859 |
|
2860 if ( ! in_array( $request_data->status, array( 'request-pending', 'request-failed' ), true ) ) { |
|
2861 return; |
|
2862 } |
|
2863 |
|
2864 update_post_meta( $request_id, '_wp_user_request_confirmed_timestamp', time() ); |
|
2865 wp_update_post( array( |
|
2866 'ID' => $request_id, |
|
2867 'post_status' => 'request-confirmed', |
|
2868 ) ); |
|
2869 } |
|
2870 |
|
2871 /** |
|
2872 * Notify the site administrator via email when a request is confirmed. |
|
2873 * |
|
2874 * Without this, the admin would have to manually check the site to see if any |
|
2875 * action was needed on their part yet. |
|
2876 * |
|
2877 * @since 4.9.6 |
|
2878 * |
|
2879 * @param int $request_id The ID of the request. |
|
2880 */ |
|
2881 function _wp_privacy_send_request_confirmation_notification( $request_id ) { |
|
2882 $request_data = wp_get_user_request_data( $request_id ); |
|
2883 |
|
2884 if ( ! is_a( $request_data, 'WP_User_Request' ) || 'request-confirmed' !== $request_data->status ) { |
|
2885 return; |
|
2886 } |
|
2887 |
|
2888 $already_notified = (bool) get_post_meta( $request_id, '_wp_admin_notified', true ); |
|
2889 |
|
2890 if ( $already_notified ) { |
|
2891 return; |
|
2892 } |
|
2893 |
|
2894 $manage_url = add_query_arg( 'page', $request_data->action_name, admin_url( 'tools.php' ) ); |
|
2895 $action_description = wp_user_request_action_description( $request_data->action_name ); |
|
2896 |
|
2897 /** |
|
2898 * Filters the recipient of the data request confirmation notification. |
|
2899 * |
|
2900 * In a Multisite environment, this will default to the email address of the |
|
2901 * network admin because, by default, single site admins do not have the |
|
2902 * capabilities required to process requests. Some networks may wish to |
|
2903 * delegate those capabilities to a single-site admin, or a dedicated person |
|
2904 * responsible for managing privacy requests. |
|
2905 * |
|
2906 * @since 4.9.6 |
|
2907 * |
|
2908 * @param string $admin_email The email address of the notification recipient. |
|
2909 * @param WP_User_Request $request_data The request that is initiating the notification. |
|
2910 */ |
|
2911 $admin_email = apply_filters( 'user_request_confirmed_email_to', get_site_option( 'admin_email' ), $request_data ); |
|
2912 |
|
2913 $email_data = array( |
|
2914 'request' => $request_data, |
|
2915 'user_email' => $request_data->email, |
|
2916 'description' => $action_description, |
|
2917 'manage_url' => $manage_url, |
|
2918 'sitename' => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), |
|
2919 'siteurl' => home_url(), |
|
2920 'admin_email' => $admin_email, |
|
2921 ); |
|
2922 |
|
2923 /* translators: Do not translate SITENAME, USER_EMAIL, DESCRIPTION, MANAGE_URL, SITEURL; those are placeholders. */ |
|
2924 $email_text = __( |
|
2925 'Howdy, |
|
2926 |
|
2927 A user data privacy request has been confirmed on ###SITENAME###: |
|
2928 |
|
2929 User: ###USER_EMAIL### |
|
2930 Request: ###DESCRIPTION### |
|
2931 |
|
2932 You can view and manage these data privacy requests here: |
|
2933 |
|
2934 ###MANAGE_URL### |
|
2935 |
|
2936 Regards, |
|
2937 All at ###SITENAME### |
|
2938 ###SITEURL###' |
|
2939 ); |
|
2940 |
|
2941 /** |
|
2942 * Filters the body of the user request confirmation email. |
|
2943 * |
|
2944 * The email is sent to an administrator when an user request is confirmed. |
|
2945 * The following strings have a special meaning and will get replaced dynamically: |
|
2946 * |
|
2947 * ###SITENAME### The name of the site. |
|
2948 * ###USER_EMAIL### The user email for the request. |
|
2949 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for. |
|
2950 * ###MANAGE_URL### The URL to manage requests. |
|
2951 * ###SITEURL### The URL to the site. |
|
2952 * |
|
2953 * @since 4.9.6 |
|
2954 * |
|
2955 * @param string $email_text Text in the email. |
|
2956 * @param array $email_data { |
|
2957 * Data relating to the account action email. |
|
2958 * |
|
2959 * @type WP_User_Request $request User request object. |
|
2960 * @type string $user_email The email address confirming a request |
|
2961 * @type string $description Description of the action being performed so the user knows what the email is for. |
|
2962 * @type string $manage_url The link to click manage privacy requests of this type. |
|
2963 * @type string $sitename The site name sending the mail. |
|
2964 * @type string $siteurl The site URL sending the mail. |
|
2965 * @type string $admin_email The administrator email receiving the mail. |
|
2966 * } |
|
2967 */ |
|
2968 $content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data ); |
|
2969 |
|
2970 $content = str_replace( '###SITENAME###', $email_data['sitename'], $content ); |
|
2971 $content = str_replace( '###USER_EMAIL###', $email_data['user_email'], $content ); |
|
2972 $content = str_replace( '###DESCRIPTION###', $email_data['description'], $content ); |
|
2973 $content = str_replace( '###MANAGE_URL###', esc_url_raw( $email_data['manage_url'] ), $content ); |
|
2974 $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content ); |
|
2975 |
|
2976 $subject = sprintf( |
|
2977 /* translators: 1: Site name. 2: Name of the confirmed action. */ |
|
2978 __( '[%1$s] Action Confirmed: %2$s' ), |
|
2979 $email_data['sitename'], |
|
2980 $action_description |
|
2981 ); |
|
2982 |
|
2983 /** |
|
2984 * Filters the subject of the user request confirmation email. |
|
2985 * |
|
2986 * @since 4.9.8 |
|
2987 * |
|
2988 * @param string $subject The email subject. |
|
2989 * @param string $sitename The name of the site. |
|
2990 * @param array $email_data { |
|
2991 * Data relating to the account action email. |
|
2992 * |
|
2993 * @type WP_User_Request $request User request object. |
|
2994 * @type string $user_email The email address confirming a request |
|
2995 * @type string $description Description of the action being performed so the user knows what the email is for. |
|
2996 * @type string $manage_url The link to click manage privacy requests of this type. |
|
2997 * @type string $sitename The site name sending the mail. |
|
2998 * @type string $siteurl The site URL sending the mail. |
|
2999 * @type string $admin_email The administrator email receiving the mail. |
|
3000 * } |
|
3001 */ |
|
3002 $subject = apply_filters( 'user_request_confirmed_email_subject', $subject, $email_data['sitename'], $email_data ); |
|
3003 |
|
3004 $email_sent = wp_mail( $email_data['admin_email'], $subject, $content ); |
|
3005 |
|
3006 if ( $email_sent ) { |
|
3007 update_post_meta( $request_id, '_wp_admin_notified', true ); |
|
3008 } |
|
3009 } |
|
3010 |
|
3011 /** |
|
3012 * Notify the user when their erasure request is fulfilled. |
|
3013 * |
|
3014 * Without this, the user would never know if their data was actually erased. |
|
3015 * |
|
3016 * @since 4.9.6 |
|
3017 * |
|
3018 * @param int $request_id The privacy request post ID associated with this request. |
|
3019 */ |
|
3020 function _wp_privacy_send_erasure_fulfillment_notification( $request_id ) { |
|
3021 $request_data = wp_get_user_request_data( $request_id ); |
|
3022 |
|
3023 if ( ! is_a( $request_data, 'WP_User_Request' ) || 'request-completed' !== $request_data->status ) { |
|
3024 return; |
|
3025 } |
|
3026 |
|
3027 $already_notified = (bool) get_post_meta( $request_id, '_wp_user_notified', true ); |
|
3028 |
|
3029 if ( $already_notified ) { |
|
3030 return; |
|
3031 } |
|
3032 |
|
3033 /** |
|
3034 * Filters the recipient of the data erasure fulfillment notification. |
|
3035 * |
|
3036 * @since 4.9.6 |
|
3037 * |
|
3038 * @param string $user_email The email address of the notification recipient. |
|
3039 * @param WP_User_Request $request_data The request that is initiating the notification. |
|
3040 */ |
|
3041 $user_email = apply_filters( 'user_erasure_fulfillment_email_to', $request_data->email, $request_data ); |
|
3042 |
|
3043 $email_data = array( |
|
3044 'request' => $request_data, |
|
3045 'message_recipient' => $user_email, |
|
3046 'privacy_policy_url' => get_privacy_policy_url(), |
|
3047 'sitename' => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), |
|
3048 'siteurl' => home_url(), |
|
3049 ); |
|
3050 |
|
3051 $subject = sprintf( |
|
3052 /* translators: %s: Site name. */ |
|
3053 __( '[%s] Erasure Request Fulfilled' ), |
|
3054 $email_data['sitename'] |
|
3055 ); |
|
3056 |
|
3057 /** |
|
3058 * Filters the subject of the email sent when an erasure request is completed. |
|
3059 * |
|
3060 * @since 4.9.8 |
|
3061 * |
|
3062 * @param string $subject The email subject. |
|
3063 * @param string $sitename The name of the site. |
|
3064 * @param array $email_data { |
|
3065 * Data relating to the account action email. |
|
3066 * |
|
3067 * @type WP_User_Request $request User request object. |
|
3068 * @type string $message_recipient The address that the email will be sent to. Defaults |
|
3069 * to the value of `$request->email`, but can be changed |
|
3070 * by the `user_erasure_fulfillment_email_to` filter. |
|
3071 * @type string $privacy_policy_url Privacy policy URL. |
|
3072 * @type string $sitename The site name sending the mail. |
|
3073 * @type string $siteurl The site URL sending the mail. |
|
3074 * } |
|
3075 */ |
|
3076 $subject = apply_filters( 'user_erasure_complete_email_subject', $subject, $email_data['sitename'], $email_data ); |
|
3077 |
|
3078 if ( empty( $email_data['privacy_policy_url'] ) ) { |
|
3079 /* translators: Do not translate SITENAME, SITEURL; those are placeholders. */ |
|
3080 $email_text = __( |
|
3081 'Howdy, |
|
3082 |
|
3083 Your request to erase your personal data on ###SITENAME### has been completed. |
|
3084 |
|
3085 If you have any follow-up questions or concerns, please contact the site administrator. |
|
3086 |
|
3087 Regards, |
|
3088 All at ###SITENAME### |
|
3089 ###SITEURL###' |
|
3090 ); |
|
3091 } else { |
|
3092 /* translators: Do not translate SITENAME, SITEURL, PRIVACY_POLICY_URL; those are placeholders. */ |
|
3093 $email_text = __( |
|
3094 'Howdy, |
|
3095 |
|
3096 Your request to erase your personal data on ###SITENAME### has been completed. |
|
3097 |
|
3098 If you have any follow-up questions or concerns, please contact the site administrator. |
|
3099 |
|
3100 For more information, you can also read our privacy policy: ###PRIVACY_POLICY_URL### |
|
3101 |
|
3102 Regards, |
|
3103 All at ###SITENAME### |
|
3104 ###SITEURL###' |
|
3105 ); |
|
3106 } |
|
3107 |
|
3108 /** |
|
3109 * Filters the body of the data erasure fulfillment notification. |
|
3110 * |
|
3111 * The email is sent to a user when a their data erasure request is fulfilled |
|
3112 * by an administrator. |
|
3113 * |
|
3114 * The following strings have a special meaning and will get replaced dynamically: |
|
3115 * |
|
3116 * ###SITENAME### The name of the site. |
|
3117 * ###PRIVACY_POLICY_URL### Privacy policy page URL. |
|
3118 * ###SITEURL### The URL to the site. |
|
3119 * |
|
3120 * @since 4.9.6 |
|
3121 * |
|
3122 * @param string $email_text Text in the email. |
|
3123 * @param array $email_data { |
|
3124 * Data relating to the account action email. |
|
3125 * |
|
3126 * @type WP_User_Request $request User request object. |
|
3127 * @type string $message_recipient The address that the email will be sent to. Defaults |
|
3128 * to the value of `$request->email`, but can be changed |
|
3129 * by the `user_erasure_fulfillment_email_to` filter. |
|
3130 * @type string $privacy_policy_url Privacy policy URL. |
|
3131 * @type string $sitename The site name sending the mail. |
|
3132 * @type string $siteurl The site URL sending the mail. |
|
3133 * } |
|
3134 */ |
|
3135 $content = apply_filters( 'user_confirmed_action_email_content', $email_text, $email_data ); |
|
3136 |
|
3137 $content = str_replace( '###SITENAME###', $email_data['sitename'], $content ); |
|
3138 $content = str_replace( '###PRIVACY_POLICY_URL###', $email_data['privacy_policy_url'], $content ); |
|
3139 $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content ); |
|
3140 |
|
3141 $email_sent = wp_mail( $user_email, $subject, $content ); |
|
3142 |
|
3143 if ( $email_sent ) { |
|
3144 update_post_meta( $request_id, '_wp_user_notified', true ); |
|
3145 } |
|
3146 } |
|
3147 |
|
3148 /** |
|
3149 * Return request confirmation message HTML. |
|
3150 * |
|
3151 * @since 4.9.6 |
|
3152 * @access private |
|
3153 * |
|
3154 * @param int $request_id The request ID being confirmed. |
|
3155 * @return string $message The confirmation message. |
|
3156 */ |
|
3157 function _wp_privacy_account_request_confirmed_message( $request_id ) { |
|
3158 $request = wp_get_user_request_data( $request_id ); |
|
3159 |
|
3160 $message = '<p class="success">' . __( 'Action has been confirmed.' ) . '</p>'; |
|
3161 $message .= '<p>' . __( 'The site administrator has been notified and will fulfill your request as soon as possible.' ) . '</p>'; |
|
3162 |
|
3163 if ( $request && in_array( $request->action_name, _wp_privacy_action_request_types(), true ) ) { |
|
3164 if ( 'export_personal_data' === $request->action_name ) { |
|
3165 $message = '<p class="success">' . __( 'Thanks for confirming your export request.' ) . '</p>'; |
|
3166 $message .= '<p>' . __( 'The site administrator has been notified. You will receive a link to download your export via email when they fulfill your request.' ) . '</p>'; |
|
3167 } elseif ( 'remove_personal_data' === $request->action_name ) { |
|
3168 $message = '<p class="success">' . __( 'Thanks for confirming your erasure request.' ) . '</p>'; |
|
3169 $message .= '<p>' . __( 'The site administrator has been notified. You will receive an email confirmation when they erase your data.' ) . '</p>'; |
|
3170 } |
|
3171 } |
|
3172 |
|
3173 /** |
|
3174 * Filters the message displayed to a user when they confirm a data request. |
|
3175 * |
|
3176 * @since 4.9.6 |
|
3177 * |
|
3178 * @param string $message The message to the user. |
|
3179 * @param int $request_id The ID of the request being confirmed. |
|
3180 */ |
|
3181 $message = apply_filters( 'user_request_action_confirmed_message', $message, $request_id ); |
|
3182 |
|
3183 return $message; |
|
3184 } |
|
3185 |
|
3186 /** |
|
3187 * Create and log a user request to perform a specific action. |
|
3188 * |
|
3189 * Requests are stored inside a post type named `user_request` since they can apply to both |
|
3190 * users on the site, or guests without a user account. |
|
3191 * |
|
3192 * @since 4.9.6 |
|
3193 * |
|
3194 * @param string $email_address User email address. This can be the address of a registered or non-registered user. |
|
3195 * @param string $action_name Name of the action that is being confirmed. Required. |
|
3196 * @param array $request_data Misc data you want to send with the verification request and pass to the actions once the request is confirmed. |
|
3197 * @return int|WP_Error Returns the request ID if successful, or a WP_Error object on failure. |
|
3198 */ |
|
3199 function wp_create_user_request( $email_address = '', $action_name = '', $request_data = array() ) { |
|
3200 $email_address = sanitize_email( $email_address ); |
|
3201 $action_name = sanitize_key( $action_name ); |
|
3202 |
|
3203 if ( ! is_email( $email_address ) ) { |
|
3204 return new WP_Error( 'invalid_email', __( 'Invalid email address.' ) ); |
|
3205 } |
|
3206 |
|
3207 if ( ! $action_name ) { |
|
3208 return new WP_Error( 'invalid_action', __( 'Invalid action name.' ) ); |
|
3209 } |
|
3210 |
|
3211 $user = get_user_by( 'email', $email_address ); |
|
3212 $user_id = $user && ! is_wp_error( $user ) ? $user->ID : 0; |
|
3213 |
|
3214 // Check for duplicates. |
|
3215 $requests_query = new WP_Query( array( |
|
3216 'post_type' => 'user_request', |
|
3217 'post_name__in' => array( $action_name ), // Action name stored in post_name column. |
|
3218 'title' => $email_address, // Email address stored in post_title column. |
|
3219 'post_status' => 'any', |
|
3220 'fields' => 'ids', |
|
3221 ) ); |
|
3222 |
|
3223 if ( $requests_query->found_posts ) { |
|
3224 return new WP_Error( 'duplicate_request', __( 'A request for this email address already exists.' ) ); |
|
3225 } |
|
3226 |
|
3227 $request_id = wp_insert_post( array( |
|
3228 'post_author' => $user_id, |
|
3229 'post_name' => $action_name, |
|
3230 'post_title' => $email_address, |
|
3231 'post_content' => wp_json_encode( $request_data ), |
|
3232 'post_status' => 'request-pending', |
|
3233 'post_type' => 'user_request', |
|
3234 'post_date' => current_time( 'mysql', false ), |
|
3235 'post_date_gmt' => current_time( 'mysql', true ), |
|
3236 ), true ); |
|
3237 |
|
3238 return $request_id; |
|
3239 } |
|
3240 |
|
3241 /** |
|
3242 * Get action description from the name and return a string. |
|
3243 * |
|
3244 * @since 4.9.6 |
|
3245 * |
|
3246 * @param string $action_name Action name of the request. |
|
3247 * @return string Human readable action name. |
|
3248 */ |
|
3249 function wp_user_request_action_description( $action_name ) { |
|
3250 switch ( $action_name ) { |
|
3251 case 'export_personal_data': |
|
3252 $description = __( 'Export Personal Data' ); |
|
3253 break; |
|
3254 case 'remove_personal_data': |
|
3255 $description = __( 'Erase Personal Data' ); |
|
3256 break; |
|
3257 default: |
|
3258 /* translators: %s: action name */ |
|
3259 $description = sprintf( __( 'Confirm the "%s" action' ), $action_name ); |
|
3260 break; |
|
3261 } |
|
3262 |
|
3263 /** |
|
3264 * Filters the user action description. |
|
3265 * |
|
3266 * @since 4.9.6 |
|
3267 * |
|
3268 * @param string $description The default description. |
|
3269 * @param string $action_name The name of the request. |
|
3270 */ |
|
3271 return apply_filters( 'user_request_action_description', $description, $action_name ); |
|
3272 } |
|
3273 |
|
3274 /** |
|
3275 * Send a confirmation request email to confirm an action. |
|
3276 * |
|
3277 * If the request is not already pending, it will be updated. |
|
3278 * |
|
3279 * @since 4.9.6 |
|
3280 * |
|
3281 * @param string $request_id ID of the request created via wp_create_user_request(). |
|
3282 * @return WP_Error|bool Will return true/false based on the success of sending the email, or a WP_Error object. |
|
3283 */ |
|
3284 function wp_send_user_request( $request_id ) { |
|
3285 $request_id = absint( $request_id ); |
|
3286 $request = wp_get_user_request_data( $request_id ); |
|
3287 |
|
3288 if ( ! $request ) { |
|
3289 return new WP_Error( 'user_request_error', __( 'Invalid request.' ) ); |
|
3290 } |
|
3291 |
|
3292 $email_data = array( |
|
3293 'request' => $request, |
|
3294 'email' => $request->email, |
|
3295 'description' => wp_user_request_action_description( $request->action_name ), |
|
3296 'confirm_url' => add_query_arg( array( |
|
3297 'action' => 'confirmaction', |
|
3298 'request_id' => $request_id, |
|
3299 'confirm_key' => wp_generate_user_request_key( $request_id ), |
|
3300 ), wp_login_url() ), |
|
3301 'sitename' => wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), |
|
3302 'siteurl' => home_url(), |
|
3303 ); |
|
3304 |
|
3305 /* translators: Do not translate DESCRIPTION, CONFIRM_URL, SITENAME, SITEURL: those are placeholders. */ |
|
3306 $email_text = __( |
|
3307 'Howdy, |
|
3308 |
|
3309 A request has been made to perform the following action on your account: |
|
3310 |
|
3311 ###DESCRIPTION### |
|
3312 |
|
3313 To confirm this, please click on the following link: |
|
3314 ###CONFIRM_URL### |
|
3315 |
|
3316 You can safely ignore and delete this email if you do not want to |
|
3317 take this action. |
|
3318 |
|
3319 Regards, |
|
3320 All at ###SITENAME### |
|
3321 ###SITEURL###' |
|
3322 ); |
|
3323 |
|
3324 /** |
|
3325 * Filters the text of the email sent when an account action is attempted. |
|
3326 * |
|
3327 * The following strings have a special meaning and will get replaced dynamically: |
|
3328 * |
|
3329 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for. |
|
3330 * ###CONFIRM_URL### The link to click on to confirm the account action. |
|
3331 * ###SITENAME### The name of the site. |
|
3332 * ###SITEURL### The URL to the site. |
|
3333 * |
|
3334 * @since 4.9.6 |
|
3335 * |
|
3336 * @param string $email_text Text in the email. |
|
3337 * @param array $email_data { |
|
3338 * Data relating to the account action email. |
|
3339 * |
|
3340 * @type WP_User_Request $request User request object. |
|
3341 * @type string $email The email address this is being sent to. |
|
3342 * @type string $description Description of the action being performed so the user knows what the email is for. |
|
3343 * @type string $confirm_url The link to click on to confirm the account action. |
|
3344 * @type string $sitename The site name sending the mail. |
|
3345 * @type string $siteurl The site URL sending the mail. |
|
3346 * } |
|
3347 */ |
|
3348 $content = apply_filters( 'user_request_action_email_content', $email_text, $email_data ); |
|
3349 |
|
3350 $content = str_replace( '###DESCRIPTION###', $email_data['description'], $content ); |
|
3351 $content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content ); |
|
3352 $content = str_replace( '###EMAIL###', $email_data['email'], $content ); |
|
3353 $content = str_replace( '###SITENAME###', $email_data['sitename'], $content ); |
|
3354 $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content ); |
|
3355 |
|
3356 /* translators: Privacy data request subject. 1: Site name, 2: Name of the action */ |
|
3357 $subject = sprintf( __( '[%1$s] Confirm Action: %2$s' ), $email_data['sitename'], $email_data['description'] ); |
|
3358 |
|
3359 /** |
|
3360 * Filters the subject of the email sent when an account action is attempted. |
|
3361 * |
|
3362 * @since 4.9.6 |
|
3363 * |
|
3364 * @param string $subject The email subject. |
|
3365 * @param string $sitename The name of the site. |
|
3366 * @param array $email_data { |
|
3367 * Data relating to the account action email. |
|
3368 * |
|
3369 * @type WP_User_Request $request User request object. |
|
3370 * @type string $email The email address this is being sent to. |
|
3371 * @type string $description Description of the action being performed so the user knows what the email is for. |
|
3372 * @type string $confirm_url The link to click on to confirm the account action. |
|
3373 * @type string $sitename The site name sending the mail. |
|
3374 * @type string $siteurl The site URL sending the mail. |
|
3375 * } |
|
3376 */ |
|
3377 $subject = apply_filters( 'user_request_action_email_subject', $subject, $email_data['sitename'], $email_data ); |
|
3378 |
|
3379 return wp_mail( $email_data['email'], $subject, $content ); |
|
3380 } |
|
3381 |
|
3382 /** |
|
3383 * Returns a confirmation key for a user action and stores the hashed version for future comparison. |
|
3384 * |
|
3385 * @since 4.9.6 |
|
3386 * |
|
3387 * @param int $request_id Request ID. |
|
3388 * @return string Confirmation key. |
|
3389 */ |
|
3390 function wp_generate_user_request_key( $request_id ) { |
|
3391 global $wp_hasher; |
|
3392 |
|
3393 // Generate something random for a confirmation key. |
|
3394 $key = wp_generate_password( 20, false ); |
|
3395 |
|
3396 // Return the key, hashed. |
|
3397 if ( empty( $wp_hasher ) ) { |
|
3398 require_once ABSPATH . WPINC . '/class-phpass.php'; |
|
3399 $wp_hasher = new PasswordHash( 8, true ); |
|
3400 } |
|
3401 |
|
3402 wp_update_post( array( |
|
3403 'ID' => $request_id, |
|
3404 'post_status' => 'request-pending', |
|
3405 'post_password' => $wp_hasher->HashPassword( $key ), |
|
3406 'post_modified' => current_time( 'mysql', false ), |
|
3407 'post_modified_gmt' => current_time( 'mysql', true ), |
|
3408 ) ); |
|
3409 |
|
3410 return $key; |
|
3411 } |
|
3412 |
|
3413 /** |
|
3414 * Validate a user request by comparing the key with the request's key. |
|
3415 * |
|
3416 * @since 4.9.6 |
|
3417 * |
|
3418 * @param string $request_id ID of the request being confirmed. |
|
3419 * @param string $key Provided key to validate. |
|
3420 * @return bool|WP_Error WP_Error on failure, true on success. |
|
3421 */ |
|
3422 function wp_validate_user_request_key( $request_id, $key ) { |
|
3423 global $wp_hasher; |
|
3424 |
|
3425 $request_id = absint( $request_id ); |
|
3426 $request = wp_get_user_request_data( $request_id ); |
|
3427 |
|
3428 if ( ! $request ) { |
|
3429 return new WP_Error( 'user_request_error', __( 'Invalid request.' ) ); |
|
3430 } |
|
3431 |
|
3432 if ( ! in_array( $request->status, array( 'request-pending', 'request-failed' ), true ) ) { |
|
3433 return __( 'This link has expired.' ); |
|
3434 } |
|
3435 |
|
3436 if ( empty( $key ) ) { |
|
3437 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); |
|
3438 } |
|
3439 |
|
3440 if ( empty( $wp_hasher ) ) { |
|
3441 require_once ABSPATH . WPINC . '/class-phpass.php'; |
|
3442 $wp_hasher = new PasswordHash( 8, true ); |
|
3443 } |
|
3444 |
|
3445 $key_request_time = $request->modified_timestamp; |
|
3446 $saved_key = $request->confirm_key; |
|
3447 |
|
3448 if ( ! $saved_key ) { |
|
3449 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); |
|
3450 } |
|
3451 |
|
3452 if ( ! $key_request_time ) { |
|
3453 return new WP_Error( 'invalid_key', __( 'Invalid action' ) ); |
|
3454 } |
|
3455 |
|
3456 /** |
|
3457 * Filters the expiration time of confirm keys. |
|
3458 * |
|
3459 * @since 4.9.6 |
|
3460 * |
|
3461 * @param int $expiration The expiration time in seconds. |
|
3462 */ |
|
3463 $expiration_duration = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS ); |
|
3464 $expiration_time = $key_request_time + $expiration_duration; |
|
3465 |
|
3466 if ( ! $wp_hasher->CheckPassword( $key, $saved_key ) ) { |
|
3467 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); |
|
3468 } |
|
3469 |
|
3470 if ( ! $expiration_time || time() > $expiration_time ) { |
|
3471 return new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) ); |
|
3472 } |
|
3473 |
|
3474 return true; |
|
3475 } |
|
3476 |
|
3477 /** |
|
3478 * Return data about a user request. |
|
3479 * |
|
3480 * @since 4.9.6 |
|
3481 * |
|
3482 * @param int $request_id Request ID to get data about. |
|
3483 * @return WP_User_Request|false |
|
3484 */ |
|
3485 function wp_get_user_request_data( $request_id ) { |
|
3486 $request_id = absint( $request_id ); |
|
3487 $post = get_post( $request_id ); |
|
3488 |
|
3489 if ( ! $post || 'user_request' !== $post->post_type ) { |
|
3490 return false; |
|
3491 } |
|
3492 |
|
3493 return new WP_User_Request( $post ); |
|
3494 } |
|
3495 |
|
3496 /** |
|
3497 * WP_User_Request class. |
|
3498 * |
|
3499 * Represents user request data loaded from a WP_Post object. |
|
3500 * |
|
3501 * @since 4.9.6 |
|
3502 */ |
|
3503 final class WP_User_Request { |
|
3504 /** |
|
3505 * Request ID. |
|
3506 * |
|
3507 * @var int |
|
3508 */ |
|
3509 public $ID = 0; |
|
3510 |
|
3511 /** |
|
3512 * User ID. |
|
3513 * |
|
3514 * @var int |
|
3515 */ |
|
3516 |
|
3517 public $user_id = 0; |
|
3518 |
|
3519 /** |
|
3520 * User email. |
|
3521 * |
|
3522 * @var int |
|
3523 */ |
|
3524 public $email = ''; |
|
3525 |
|
3526 /** |
|
3527 * Action name. |
|
3528 * |
|
3529 * @var string |
|
3530 */ |
|
3531 public $action_name = ''; |
|
3532 |
|
3533 /** |
|
3534 * Current status. |
|
3535 * |
|
3536 * @var string |
|
3537 */ |
|
3538 public $status = ''; |
|
3539 |
|
3540 /** |
|
3541 * Timestamp this request was created. |
|
3542 * |
|
3543 * @var int|null |
|
3544 */ |
|
3545 public $created_timestamp = null; |
|
3546 |
|
3547 /** |
|
3548 * Timestamp this request was last modified. |
|
3549 * |
|
3550 * @var int|null |
|
3551 */ |
|
3552 public $modified_timestamp = null; |
|
3553 |
|
3554 /** |
|
3555 * Timestamp this request was confirmed. |
|
3556 * |
|
3557 * @var int |
|
3558 */ |
|
3559 public $confirmed_timestamp = null; |
|
3560 |
|
3561 /** |
|
3562 * Timestamp this request was completed. |
|
3563 * |
|
3564 * @var int |
|
3565 */ |
|
3566 public $completed_timestamp = null; |
|
3567 |
|
3568 /** |
|
3569 * Misc data assigned to this request. |
|
3570 * |
|
3571 * @var array |
|
3572 */ |
|
3573 public $request_data = array(); |
|
3574 |
|
3575 /** |
|
3576 * Key used to confirm this request. |
|
3577 * |
|
3578 * @var string |
|
3579 */ |
|
3580 public $confirm_key = ''; |
|
3581 |
|
3582 /** |
|
3583 * Constructor. |
|
3584 * |
|
3585 * @since 4.9.6 |
|
3586 * |
|
3587 * @param WP_Post|object $post Post object. |
|
3588 */ |
|
3589 public function __construct( $post ) { |
|
3590 $this->ID = $post->ID; |
|
3591 $this->user_id = $post->post_author; |
|
3592 $this->email = $post->post_title; |
|
3593 $this->action_name = $post->post_name; |
|
3594 $this->status = $post->post_status; |
|
3595 $this->created_timestamp = strtotime( $post->post_date_gmt ); |
|
3596 $this->modified_timestamp = strtotime( $post->post_modified_gmt ); |
|
3597 $this->confirmed_timestamp = (int) get_post_meta( $post->ID, '_wp_user_request_confirmed_timestamp', true ); |
|
3598 $this->completed_timestamp = (int) get_post_meta( $post->ID, '_wp_user_request_completed_timestamp', true ); |
|
3599 $this->request_data = json_decode( $post->post_content, true ); |
|
3600 $this->confirm_key = $post->post_password; |
|
3601 } |
|
3602 } |