balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-user.php (22194B)


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