~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/user.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

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