[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-user.php (source)

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


Generated : Fri Oct 10 08:20:03 2025 Cross-referenced by PHPXref