Make WordPress Core

source: trunk/src/wp-includes/class-wp-user.php

Last change on this file was 61210, checked in by SergeyBiryukov, 5 weeks ago

Users: Initialize the WP_User::$roles property as a sequential array.

Previously, if any roles were filtered out via array_filter() when assigning the WP_User::$roles property in WP_User::get_role_caps(), the resulting array could contain non-sequential numeric keys, which would then cause it to be treated as an object when JSON-encoded, e.g. in wp_localize_script(), instead of a proper array, breaking client-side expectations.

This commit ensures that the WP_User::$roles property is always treated as an array.

Follow-up to [2703], [2793], [22118].

Props haruncpi, peterwilsoncc, SirLouen, getsyash, wildworks, johnjamesjacoby, SergeyBiryukov.
Fixes #63427.

  • Property svn:eol-style set to native
File size: 22.5 KB
Line 
1<?php
2/**
3 * User API: WP_User class
4 *
5 * @package WordPress
6 * @subpackage Users
7 * @since 4.4.0
8 */
9
10/**
11 * Core class used to implement the WP_User object.
12 *
13 * @since 2.0.0
14 * @since 6.8.0 The `user_pass` property is now hashed using bcrypt by default instead of phpass.
15 *              Existing passwords may still be hashed using phpass.
16 *
17 * @property string $nickname
18 * @property string $description
19 * @property string $user_description
20 * @property string $first_name
21 * @property string $user_firstname
22 * @property string $last_name
23 * @property string $user_lastname
24 * @property string $user_login
25 * @property string $user_pass
26 * @property string $user_nicename
27 * @property string $user_email
28 * @property string $user_url
29 * @property string $user_registered
30 * @property string $user_activation_key
31 * @property string $user_status
32 * @property int    $user_level
33 * @property string $display_name
34 * @property string $spam
35 * @property string $deleted
36 * @property string $locale
37 * @property string $rich_editing
38 * @property string $syntax_highlighting
39 * @property string $use_ssl
40 */
41#[AllowDynamicProperties]
42class WP_User {
43        /**
44         * User data container.
45         *
46         * @since 2.0.0
47         * @var stdClass
48         */
49        public $data;
50
51        /**
52         * The user's ID.
53         *
54         * @since 2.1.0
55         * @var int
56         */
57        public $ID = 0;
58
59        /**
60         * Capabilities that the individual user has been granted outside of those inherited from their role.
61         *
62         * @since 2.0.0
63         * @var bool[] Array of key/value pairs where keys represent a capability name
64         *             and boolean values represent whether the user has that capability.
65         */
66        public $caps = array();
67
68        /**
69         * User metadata option name.
70         *
71         * @since 2.0.0
72         * @var string
73         */
74        public $cap_key;
75
76        /**
77         * The roles the user is part of.
78         *
79         * @since 2.0.0
80         * @var string[]
81         */
82        public $roles = array();
83
84        /**
85         * All capabilities the user has, including individual and role based.
86         *
87         * @since 2.0.0
88         * @var bool[] Array of key/value pairs where keys represent a capability name
89         *             and boolean values represent whether the user has that capability.
90         */
91        public $allcaps = array();
92
93        /**
94         * The filter context applied to user data fields.
95         *
96         * @since 2.9.0
97         * @var string
98         */
99        public $filter = null;
100
101        /**
102         * The site ID the capabilities of this user are initialized for.
103         *
104         * @since 4.9.0
105         * @var int
106         */
107        private $site_id = 0;
108
109        /**
110         * @since 3.3.0
111         * @var array
112         */
113        private static $back_compat_keys;
114
115        /**
116         * Constructor.
117         *
118         * Retrieves the userdata and passes it to WP_User::init().
119         *
120         * @since 2.0.0
121         *
122         * @global wpdb $wpdb WordPress database abstraction object.
123         *
124         * @param int|string|stdClass|WP_User $id      User's ID, a WP_User object, or a user object from the DB.
125         * @param string                      $name    Optional. User's username
126         * @param int                         $site_id Optional Site ID, defaults to current site.
127         */
128        public function __construct( $id = 0, $name = '', $site_id = 0 ) {
129                global $wpdb;
130
131                if ( ! isset( self::$back_compat_keys ) ) {
132                        $prefix = $wpdb->prefix;
133
134                        self::$back_compat_keys = array(
135                                'user_firstname'             => 'first_name',
136                                'user_lastname'              => 'last_name',
137                                'user_description'           => 'description',
138                                'user_level'                 => $prefix . 'user_level',
139                                $prefix . 'usersettings'     => $prefix . 'user-settings',
140                                $prefix . 'usersettingstime' => $prefix . 'user-settings-time',
141                        );
142                }
143
144                if ( $id instanceof WP_User ) {
145                        $this->init( $id->data, $site_id );
146                        return;
147                } elseif ( is_object( $id ) ) {
148                        $this->init( $id, $site_id );
149                        return;
150                }
151
152                if ( ! empty( $id ) && ! is_numeric( $id ) ) {
153                        $name = $id;
154                        $id   = 0;
155                }
156
157                if ( $id ) {
158                        $data = self::get_data_by( 'id', $id );
159                } else {
160                        $data = self::get_data_by( 'login', $name );
161                }
162
163                if ( $data ) {
164                        $this->init( $data, $site_id );
165                } else {
166                        $this->data = new stdClass();
167                }
168        }
169
170        /**
171         * Sets up object properties, including capabilities.
172         *
173         * @since 3.3.0
174         *
175         * @param object $data    User DB row object.
176         * @param int    $site_id Optional. The site ID to initialize for.
177         */
178        public function init( $data, $site_id = 0 ) {
179                if ( ! isset( $data->ID ) ) {
180                        $data->ID = 0;
181                }
182                $this->data = $data;
183                $this->ID   = (int) $data->ID;
184
185                $this->for_site( $site_id );
186        }
187
188        /**
189         * Returns only the main user fields.
190         *
191         * @since 3.3.0
192         * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter.
193         *
194         * @global wpdb $wpdb WordPress database abstraction object.
195         *
196         * @param string     $field The field to query against: Accepts 'id', 'ID', 'slug', 'email' or 'login'.
197         * @param string|int $value The field value.
198         * @return object|false Raw user object.
199         */
200        public static function get_data_by( $field, $value ) {
201                global $wpdb;
202
203                // 'ID' is an alias of 'id'.
204                if ( 'ID' === $field ) {
205                        $field = 'id';
206                }
207
208                if ( 'id' === $field ) {
209                        // Make sure the value is numeric to avoid casting objects, for example, to int 1.
210                        if ( ! is_numeric( $value ) ) {
211                                return false;
212                        }
213                        $value = (int) $value;
214                        if ( $value < 1 ) {
215                                return false;
216                        }
217                } else {
218                        $value = trim( $value );
219                }
220
221                if ( ! $value ) {
222                        return false;
223                }
224
225                switch ( $field ) {
226                        case 'id':
227                                $user_id  = $value;
228                                $db_field = 'ID';
229                                break;
230                        case 'slug':
231                                $user_id  = wp_cache_get( $value, 'userslugs' );
232                                $db_field = 'user_nicename';
233                                break;
234                        case 'email':
235                                $user_id  = wp_cache_get( $value, 'useremail' );
236                                $db_field = 'user_email';
237                                break;
238                        case 'login':
239                                $value    = sanitize_user( $value );
240                                $user_id  = wp_cache_get( $value, 'userlogins' );
241                                $db_field = 'user_login';
242                                break;
243                        default:
244                                return false;
245                }
246
247                if ( false !== $user_id ) {
248                        $user = wp_cache_get( $user_id, 'users' );
249                        if ( $user ) {
250                                return $user;
251                        }
252                }
253
254                $user = $wpdb->get_row(
255                        $wpdb->prepare(
256                                "SELECT * FROM $wpdb->users WHERE $db_field = %s LIMIT 1",
257                                $value
258                        )
259                );
260                if ( ! $user ) {
261                        return false;
262                }
263
264                update_user_caches( $user );
265
266                return $user;
267        }
268
269        /**
270         * Magic method for checking the existence of a certain custom field.
271         *
272         * @since 3.3.0
273         *
274         * @param string $key User meta key to check if set.
275         * @return bool Whether the given user meta key is set.
276         */
277        public function __isset( $key ) {
278                if ( 'id' === $key ) {
279                        _deprecated_argument(
280                                'WP_User->id',
281                                '2.1.0',
282                                sprintf(
283                                        /* translators: %s: WP_User->ID */
284                                        __( 'Use %s instead.' ),
285                                        '<code>WP_User->ID</code>'
286                                )
287                        );
288                        $key = 'ID';
289                }
290
291                if ( isset( $this->data->$key ) ) {
292                        return true;
293                }
294
295                if ( isset( self::$back_compat_keys[ $key ] ) ) {
296                        $key = self::$back_compat_keys[ $key ];
297                }
298
299                return metadata_exists( 'user', $this->ID, $key );
300        }
301
302        /**
303         * Magic method for accessing custom fields.
304         *
305         * @since 3.3.0
306         *
307         * @param string $key User meta key to retrieve.
308         * @return mixed Value of the given user meta key (if set). If `$key` is 'id', the user ID.
309         */
310        public function __get( $key ) {
311                if ( 'id' === $key ) {
312                        _deprecated_argument(
313                                'WP_User->id',
314                                '2.1.0',
315                                sprintf(
316                                        /* translators: %s: WP_User->ID */
317                                        __( 'Use %s instead.' ),
318                                        '<code>WP_User->ID</code>'
319                                )
320                        );
321                        return $this->ID;
322                }
323
324                if ( isset( $this->data->$key ) ) {
325                        $value = $this->data->$key;
326                } else {
327                        if ( isset( self::$back_compat_keys[ $key ] ) ) {
328                                $key = self::$back_compat_keys[ $key ];
329                        }
330                        $value = get_user_meta( $this->ID, $key, true );
331                }
332
333                if ( $this->filter ) {
334                        $value = sanitize_user_field( $key, $value, $this->ID, $this->filter );
335                }
336
337                return $value;
338        }
339
340        /**
341         * Magic method for setting custom user fields.
342         *
343         * This method does not update custom fields in the database. It only stores
344         * the value on the WP_User instance.
345         *
346         * @since 3.3.0
347         *
348         * @param string $key   User meta key.
349         * @param mixed  $value User meta value.
350         */
351        public function __set( $key, $value ) {
352                if ( 'id' === $key ) {
353                        _deprecated_argument(
354                                'WP_User->id',
355                                '2.1.0',
356                                sprintf(
357                                        /* translators: %s: WP_User->ID */
358                                        __( 'Use %s instead.' ),
359                                        '<code>WP_User->ID</code>'
360                                )
361                        );
362                        $this->ID = $value;
363                        return;
364                }
365
366                $this->data->$key = $value;
367        }
368
369        /**
370         * Magic method for unsetting a certain custom field.
371         *
372         * @since 4.4.0
373         *
374         * @param string $key User meta key to unset.
375         */
376        public function __unset( $key ) {
377                if ( 'id' === $key ) {
378                        _deprecated_argument(
379                                'WP_User->id',
380                                '2.1.0',
381                                sprintf(
382                                        /* translators: %s: WP_User->ID */
383                                        __( 'Use %s instead.' ),
384                                        '<code>WP_User->ID</code>'
385                                )
386                        );
387                }
388
389                if ( isset( $this->data->$key ) ) {
390                        unset( $this->data->$key );
391                }
392
393                if ( isset( self::$back_compat_keys[ $key ] ) ) {
394                        unset( self::$back_compat_keys[ $key ] );
395                }
396        }
397
398        /**
399         * Determines whether the user exists in the database.
400         *
401         * @since 3.4.0
402         *
403         * @return bool True if user exists in the database, false if not.
404         */
405        public function exists() {
406                return ! empty( $this->ID );
407        }
408
409        /**
410         * Retrieves the value of a property or meta key.
411         *
412         * Retrieves from the users and usermeta table.
413         *
414         * @since 3.3.0
415         *
416         * @param string $key Property
417         * @return mixed
418         */
419        public function get( $key ) {
420                return $this->__get( $key );
421        }
422
423        /**
424         * Determines whether a property or meta key is set.
425         *
426         * Consults the users and usermeta tables.
427         *
428         * @since 3.3.0
429         *
430         * @param string $key Property.
431         * @return bool
432         */
433        public function has_prop( $key ) {
434                return $this->__isset( $key );
435        }
436
437        /**
438         * Returns an array representation.
439         *
440         * @since 3.5.0
441         *
442         * @return array Array representation.
443         */
444        public function to_array() {
445                return get_object_vars( $this->data );
446        }
447
448        /**
449         * Makes private/protected methods readable for backward compatibility.
450         *
451         * @since 4.3.0
452         *
453         * @param string $name      Method to call.
454         * @param array  $arguments Arguments to pass when calling.
455         * @return mixed|false Return value of the callback, false otherwise.
456         */
457        public function __call( $name, $arguments ) {
458                if ( '_init_caps' === $name ) {
459                        return $this->_init_caps( ...$arguments );
460                }
461                return false;
462        }
463
464        /**
465         * Sets up capability object properties.
466         *
467         * Will set the value for the 'cap_key' property to current database table
468         * prefix, followed by 'capabilities'. Will then check to see if the
469         * property matching the 'cap_key' exists and is an array. If so, it will be
470         * used.
471         *
472         * @since 2.1.0
473         * @deprecated 4.9.0 Use WP_User::for_site()
474         *
475         * @global wpdb $wpdb WordPress database abstraction object.
476         *
477         * @param string $cap_key Optional capability key
478         */
479        protected function _init_caps( $cap_key = '' ) {
480                global $wpdb;
481
482                _deprecated_function( __METHOD__, '4.9.0', 'WP_User::for_site()' );
483
484                if ( empty( $cap_key ) ) {
485                        $this->cap_key = $wpdb->get_blog_prefix( $this->site_id ) . 'capabilities';
486                } else {
487                        $this->cap_key = $cap_key;
488                }
489
490                $this->caps = $this->get_caps_data();
491
492                $this->get_role_caps();
493        }
494
495        /**
496         * Retrieves all of the capabilities of the user's roles, and merges them with
497         * individual user capabilities.
498         *
499         * All of the capabilities of the user's roles are merged with the user's individual
500         * capabilities. This means that the user can be denied specific capabilities that
501         * their role might have, but the user is specifically denied.
502         *
503         * @since 2.0.0
504         *
505         * @return bool[] Array of key/value pairs where keys represent a capability name
506         *                and boolean values represent whether the user has that capability.
507         */
508        public function get_role_caps() {
509                $switch_site = false;
510                if ( is_multisite() && get_current_blog_id() !== $this->site_id ) {
511                        $switch_site = true;
512
513                        switch_to_blog( $this->site_id );
514                }
515
516                $wp_roles = wp_roles();
517
518                // Select caps that are role names and assign to $this->roles.
519                if ( is_array( $this->caps ) ) {
520                        $this->roles = array();
521
522                        foreach ( $this->caps as $key => $value ) {
523                                if ( $wp_roles->is_role( $key ) ) {
524                                        $this->roles[] = $key;
525                                }
526                        }
527                }
528
529                // Build $allcaps from role caps, overlay user's $caps.
530                $this->allcaps = array();
531                foreach ( (array) $this->roles as $role ) {
532                        $the_role      = $wp_roles->get_role( $role );
533                        $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
534                }
535                $this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
536
537                if ( $switch_site ) {
538                        restore_current_blog();
539                }
540
541                return $this->allcaps;
542        }
543
544        /**
545         * Adds role to user.
546         *
547         * Updates the user's meta data option with capabilities and roles.
548         *
549         * @since 2.0.0
550         *
551         * @param string $role Role name.
552         */
553        public function add_role( $role ) {
554                if ( empty( $role ) ) {
555                        return;
556                }
557
558                if ( in_array( $role, $this->roles, true ) ) {
559                        return;
560                }
561
562                $this->caps[ $role ] = true;
563                update_user_meta( $this->ID, $this->cap_key, $this->caps );
564                $this->get_role_caps();
565                $this->update_user_level_from_caps();
566
567                /**
568                 * Fires immediately after the user has been given a new role.
569                 *
570                 * @since 4.3.0
571                 *
572                 * @param int    $user_id The user ID.
573                 * @param string $role    The new role.
574                 */
575                do_action( 'add_user_role', $this->ID, $role );
576        }
577
578        /**
579         * Removes role from user.
580         *
581         * @since 2.0.0
582         *
583         * @param string $role Role name.
584         */
585        public function remove_role( $role ) {
586                if ( ! in_array( $role, $this->roles, true ) ) {
587                        return;
588                }
589
590                unset( $this->caps[ $role ] );
591                update_user_meta( $this->ID, $this->cap_key, $this->caps );
592                $this->get_role_caps();
593                $this->update_user_level_from_caps();
594
595                /**
596                 * Fires immediately after a role as been removed from a user.
597                 *
598                 * @since 4.3.0
599                 *
600                 * @param int    $user_id The user ID.
601                 * @param string $role    The removed role.
602                 */
603                do_action( 'remove_user_role', $this->ID, $role );
604        }
605
606        /**
607         * Sets the role of the user.
608         *
609         * This will remove the previous roles of the user and assign the user the
610         * new one. You can set the role to an empty string and it will remove all
611         * of the roles from the user.
612         *
613         * @since 2.0.0
614         *
615         * @param string $role Role name.
616         */
617        public function set_role( $role ) {
618                if ( 1 === count( $this->roles ) && current( $this->roles ) === $role ) {
619                        return;
620                }
621
622                foreach ( (array) $this->roles as $oldrole ) {
623                        unset( $this->caps[ $oldrole ] );
624                }
625
626                $old_roles = $this->roles;
627
628                if ( ! empty( $role ) ) {
629                        $this->caps[ $role ] = true;
630                        $this->roles         = array( $role => true );
631                } else {
632                        $this->roles = array();
633                }
634
635                update_user_meta( $this->ID, $this->cap_key, $this->caps );
636                $this->get_role_caps();
637                $this->update_user_level_from_caps();
638
639                foreach ( $old_roles as $old_role ) {
640                        if ( ! $old_role || $old_role === $role ) {
641                                continue;
642                        }
643
644                        /** This action is documented in wp-includes/class-wp-user.php */
645                        do_action( 'remove_user_role', $this->ID, $old_role );
646                }
647
648                if ( $role && ! in_array( $role, $old_roles, true ) ) {
649                        /** This action is documented in wp-includes/class-wp-user.php */
650                        do_action( 'add_user_role', $this->ID, $role );
651                }
652
653                /**
654                 * Fires after the user's role has changed.
655                 *
656                 * @since 2.9.0
657                 * @since 3.6.0 Added $old_roles to include an array of the user's previous roles.
658                 *
659                 * @param int      $user_id   The user ID.
660                 * @param string   $role      The new role.
661                 * @param string[] $old_roles An array of the user's previous roles.
662                 */
663                do_action( 'set_user_role', $this->ID, $role, $old_roles );
664        }
665
666        /**
667         * Chooses the maximum level the user has.
668         *
669         * Will compare the level from the $item parameter against the $max
670         * parameter. If the item is incorrect, then just the $max parameter value
671         * will be returned.
672         *
673         * Used to get the max level based on the capabilities the user has. This
674         * is also based on roles, so if the user is assigned the Administrator role
675         * then the capability 'level_10' will exist and the user will get that
676         * value.
677         *
678         * @since 2.0.0
679         *
680         * @param int    $max  Max level of user.
681         * @param string $item Level capability name.
682         * @return int Max Level.
683         */
684        public function level_reduction( $max, $item ) {
685                if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) {
686                        $level = (int) $matches[1];
687                        return max( $max, $level );
688                } else {
689                        return $max;
690                }
691        }
692
693        /**
694         * Updates the maximum user level for the user.
695         *
696         * Updates the 'user_level' user metadata (includes prefix that is the
697         * database table prefix) with the maximum user level. Gets the value from
698         * the all of the capabilities that the user has.
699         *
700         * @since 2.0.0
701         *
702         * @global wpdb $wpdb WordPress database abstraction object.
703         */
704        public function update_user_level_from_caps() {
705                global $wpdb;
706                $this->user_level = array_reduce( array_keys( $this->allcaps ), array( $this, 'level_reduction' ), 0 );
707                update_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level', $this->user_level );
708        }
709
710        /**
711         * Adds capability and grant or deny access to capability.
712         *
713         * @since 2.0.0
714         *
715         * @param string $cap   Capability name.
716         * @param bool   $grant Whether to grant capability to user.
717         */
718        public function add_cap( $cap, $grant = true ) {
719                $this->caps[ $cap ] = $grant;
720                update_user_meta( $this->ID, $this->cap_key, $this->caps );
721                $this->get_role_caps();
722                $this->update_user_level_from_caps();
723        }
724
725        /**
726         * Removes capability from user.
727         *
728         * @since 2.0.0
729         *
730         * @param string $cap Capability name.
731         */
732        public function remove_cap( $cap ) {
733                if ( ! isset( $this->caps[ $cap ] ) ) {
734                        return;
735                }
736                unset( $this->caps[ $cap ] );
737                update_user_meta( $this->ID, $this->cap_key, $this->caps );
738                $this->get_role_caps();
739                $this->update_user_level_from_caps();
740        }
741
742        /**
743         * Removes all of the capabilities of the user.
744         *
745         * @since 2.1.0
746         *
747         * @global wpdb $wpdb WordPress database abstraction object.
748         */
749        public function remove_all_caps() {
750                global $wpdb;
751                $this->caps = array();
752                delete_user_meta( $this->ID, $this->cap_key );
753                delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' );
754                $this->get_role_caps();
755        }
756
757        /**
758         * Returns whether the user has the specified capability.
759         *
760         * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
761         * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
762         * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
763         *
764         * Example usage:
765         *
766         *     $user->has_cap( 'edit_posts' );
767         *     $user->has_cap( 'edit_post', $post->ID );
768         *     $user->has_cap( 'edit_post_meta', $post->ID, $meta_key );
769         *
770         * While checking against a role in place of a capability is supported in part, this practice is discouraged as it
771         * may produce unreliable results.
772         *
773         * @since 2.0.0
774         * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
775         *              by adding it to the function signature.
776         *
777         * @see map_meta_cap()
778         *
779         * @param string $cap     Capability name.
780         * @param mixed  ...$args Optional further parameters, typically starting with an object ID.
781         * @return bool Whether the user has the given capability, or, if an object ID is passed, whether the user has
782         *              the given capability for that object.
783         */
784        public function has_cap( $cap, ...$args ) {
785                if ( is_numeric( $cap ) ) {
786                        _deprecated_argument( __FUNCTION__, '2.0.0', __( 'Usage of user levels is deprecated. Use capabilities instead.' ) );
787                        $cap = $this->translate_level_to_cap( $cap );
788                }
789
790                $caps = map_meta_cap( $cap, $this->ID, ...$args );
791
792                // Multisite super admin has all caps by definition, Unless specifically denied.
793                if ( is_multisite() && is_super_admin( $this->ID ) ) {
794                        if ( in_array( 'do_not_allow', $caps, true ) ) {
795                                return false;
796                        }
797                        return true;
798                }
799
800                // Maintain BC for the argument passed to the "user_has_cap" filter.
801                $args = array_merge( array( $cap, $this->ID ), $args );
802
803                /**
804                 * Dynamically filter a user's capabilities.
805                 *
806                 * @since 2.0.0
807                 * @since 3.7.0 Added the `$user` parameter.
808                 *
809                 * @param bool[]   $allcaps Array of key/value pairs where keys represent a capability name
810                 *                          and boolean values represent whether the user has that capability.
811                 * @param string[] $caps    Required primitive capabilities for the requested capability.
812                 * @param array    $args {
813                 *     Arguments that accompany the requested capability check.
814                 *
815                 *     @type string    $0 Requested capability.
816                 *     @type int       $1 Concerned user ID.
817                 *     @type mixed  ...$2 Optional second and further parameters, typically object ID.
818                 * }
819                 * @param WP_User  $user    The user object.
820                 */
821                $capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this );
822
823                // Everyone is allowed to exist.
824                $capabilities['exist'] = true;
825
826                // Nobody is allowed to do things they are not allowed to do.
827                unset( $capabilities['do_not_allow'] );
828
829                // Must have ALL requested caps.
830                foreach ( (array) $caps as $cap ) {
831                        if ( empty( $capabilities[ $cap ] ) ) {
832                                return false;
833                        }
834                }
835
836                return true;
837        }
838
839        /**
840         * Converts numeric level to level capability name.
841         *
842         * Prepends 'level_' to level number.
843         *
844         * @since 2.0.0
845         *
846         * @param int $level Level number, 1 to 10.
847         * @return string
848         */
849        public function translate_level_to_cap( $level ) {
850                return 'level_' . $level;
851        }
852
853        /**
854         * Sets the site to operate on. Defaults to the current site.
855         *
856         * @since 3.0.0
857         * @deprecated 4.9.0 Use WP_User::for_site()
858         *
859         * @param int $blog_id Optional. Site ID, defaults to current site.
860         */
861        public function for_blog( $blog_id = 0 ) {
862                _deprecated_function( __METHOD__, '4.9.0', 'WP_User::for_site()' );
863
864                $this->for_site( $blog_id );
865        }
866
867        /**
868         * Sets the site to operate on. Defaults to the current site.
869         *
870         * @since 4.9.0
871         *
872         * @global wpdb $wpdb WordPress database abstraction object.
873         *
874         * @param int $site_id Site ID to initialize user capabilities for. Default is the current site.
875         */
876        public function for_site( $site_id = 0 ) {
877                global $wpdb;
878
879                if ( ! empty( $site_id ) ) {
880                        $this->site_id = absint( $site_id );
881                } else {
882                        $this->site_id = get_current_blog_id();
883                }
884
885                $this->cap_key = $wpdb->get_blog_prefix( $this->site_id ) . 'capabilities';
886
887                $this->caps = $this->get_caps_data();
888
889                $this->get_role_caps();
890        }
891
892        /**
893         * Gets the ID of the site for which the user's capabilities are currently initialized.
894         *
895         * @since 4.9.0
896         *
897         * @return int Site ID.
898         */
899        public function get_site_id() {
900                return $this->site_id;
901        }
902
903        /**
904         * Gets the available user capabilities data.
905         *
906         * @since 4.9.0
907         *
908         * @return bool[] List of capabilities keyed by the capability name,
909         *                e.g. `array( 'edit_posts' => true, 'delete_posts' => false )`.
910         */
911        private function get_caps_data() {
912                $caps = get_user_meta( $this->ID, $this->cap_key, true );
913
914                if ( ! is_array( $caps ) ) {
915                        return array();
916                }
917
918                return $caps;
919        }
920}
Note: See TracBrowser for help on using the repository browser.