wp/wp-includes/capabilities.php
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * WordPress Roles and Capabilities.
     3  * Core User Role & Capabilities API
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage User
     6  * @subpackage Users
     7  */
     7  */
     8 
       
     9 /**
       
    10  * WordPress User Roles.
       
    11  *
       
    12  * The role option is simple, the structure is organized by role name that store
       
    13  * the name in value of the 'name' key. The capabilities are stored as an array
       
    14  * in the value of the 'capability' key.
       
    15  *
       
    16  *     array (
       
    17  *    		'rolename' => array (
       
    18  *    			'name' => 'rolename',
       
    19  *    			'capabilities' => array()
       
    20  *    		)
       
    21  *     )
       
    22  *
       
    23  * @since 2.0.0
       
    24  * @package WordPress
       
    25  * @subpackage User
       
    26  */
       
    27 class WP_Roles {
       
    28 	/**
       
    29 	 * List of roles and capabilities.
       
    30 	 *
       
    31 	 * @since 2.0.0
       
    32 	 * @access public
       
    33 	 * @var array
       
    34 	 */
       
    35 	public $roles;
       
    36 
       
    37 	/**
       
    38 	 * List of the role objects.
       
    39 	 *
       
    40 	 * @since 2.0.0
       
    41 	 * @access public
       
    42 	 * @var array
       
    43 	 */
       
    44 	public $role_objects = array();
       
    45 
       
    46 	/**
       
    47 	 * List of role names.
       
    48 	 *
       
    49 	 * @since 2.0.0
       
    50 	 * @access public
       
    51 	 * @var array
       
    52 	 */
       
    53 	public $role_names = array();
       
    54 
       
    55 	/**
       
    56 	 * Option name for storing role list.
       
    57 	 *
       
    58 	 * @since 2.0.0
       
    59 	 * @access public
       
    60 	 * @var string
       
    61 	 */
       
    62 	public $role_key;
       
    63 
       
    64 	/**
       
    65 	 * Whether to use the database for retrieval and storage.
       
    66 	 *
       
    67 	 * @since 2.1.0
       
    68 	 * @access public
       
    69 	 * @var bool
       
    70 	 */
       
    71 	public $use_db = true;
       
    72 
       
    73 	/**
       
    74 	 * Constructor
       
    75 	 *
       
    76 	 * @since 2.0.0
       
    77 	 */
       
    78 	public function __construct() {
       
    79 		$this->_init();
       
    80 	}
       
    81 
       
    82 	/**
       
    83 	 * Make private/protected methods readable for backwards compatibility.
       
    84 	 *
       
    85 	 * @since 4.0.0
       
    86 	 * @access public
       
    87 	 *
       
    88 	 * @param callable $name      Method to call.
       
    89 	 * @param array    $arguments Arguments to pass when calling.
       
    90 	 * @return mixed|bool Return value of the callback, false otherwise.
       
    91 	 */
       
    92 	public function __call( $name, $arguments ) {
       
    93 		if ( '_init' === $name ) {
       
    94 			return call_user_func_array( array( $this, $name ), $arguments );
       
    95 		}
       
    96 		return false;
       
    97 	}
       
    98 
       
    99 	/**
       
   100 	 * Set up the object properties.
       
   101 	 *
       
   102 	 * The role key is set to the current prefix for the $wpdb object with
       
   103 	 * 'user_roles' appended. If the $wp_user_roles global is set, then it will
       
   104 	 * be used and the role option will not be updated or used.
       
   105 	 *
       
   106 	 * @since 2.1.0
       
   107 	 * @access protected
       
   108 	 *
       
   109 	 * @global wpdb  $wpdb          WordPress database abstraction object.
       
   110 	 * @global array $wp_user_roles Used to set the 'roles' property value.
       
   111 	 */
       
   112 	protected function _init() {
       
   113 		global $wpdb, $wp_user_roles;
       
   114 		$this->role_key = $wpdb->get_blog_prefix() . 'user_roles';
       
   115 		if ( ! empty( $wp_user_roles ) ) {
       
   116 			$this->roles = $wp_user_roles;
       
   117 			$this->use_db = false;
       
   118 		} else {
       
   119 			$this->roles = get_option( $this->role_key );
       
   120 		}
       
   121 
       
   122 		if ( empty( $this->roles ) )
       
   123 			return;
       
   124 
       
   125 		$this->role_objects = array();
       
   126 		$this->role_names =  array();
       
   127 		foreach ( array_keys( $this->roles ) as $role ) {
       
   128 			$this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] );
       
   129 			$this->role_names[$role] = $this->roles[$role]['name'];
       
   130 		}
       
   131 	}
       
   132 
       
   133 	/**
       
   134 	 * Reinitialize the object
       
   135 	 *
       
   136 	 * Recreates the role objects. This is typically called only by switch_to_blog()
       
   137 	 * after switching wpdb to a new blog ID.
       
   138 	 *
       
   139 	 * @since 3.5.0
       
   140 	 * @access public
       
   141 	 */
       
   142 	public function reinit() {
       
   143 		// There is no need to reinit if using the wp_user_roles global.
       
   144 		if ( ! $this->use_db )
       
   145 			return;
       
   146 
       
   147 		global $wpdb;
       
   148 
       
   149 		// Duplicated from _init() to avoid an extra function call.
       
   150 		$this->role_key = $wpdb->get_blog_prefix() . 'user_roles';
       
   151 		$this->roles = get_option( $this->role_key );
       
   152 		if ( empty( $this->roles ) )
       
   153 			return;
       
   154 
       
   155 		$this->role_objects = array();
       
   156 		$this->role_names =  array();
       
   157 		foreach ( array_keys( $this->roles ) as $role ) {
       
   158 			$this->role_objects[$role] = new WP_Role( $role, $this->roles[$role]['capabilities'] );
       
   159 			$this->role_names[$role] = $this->roles[$role]['name'];
       
   160 		}
       
   161 	}
       
   162 
       
   163 	/**
       
   164 	 * Add role name with capabilities to list.
       
   165 	 *
       
   166 	 * Updates the list of roles, if the role doesn't already exist.
       
   167 	 *
       
   168 	 * The capabilities are defined in the following format `array( 'read' => true );`
       
   169 	 * To explicitly deny a role a capability you set the value for that capability to false.
       
   170 	 *
       
   171 	 * @since 2.0.0
       
   172 	 * @access public
       
   173 	 *
       
   174 	 * @param string $role Role name.
       
   175 	 * @param string $display_name Role display name.
       
   176 	 * @param array $capabilities List of role capabilities in the above format.
       
   177 	 * @return WP_Role|null WP_Role object if role is added, null if already exists.
       
   178 	 */
       
   179 	public function add_role( $role, $display_name, $capabilities = array() ) {
       
   180 		if ( isset( $this->roles[$role] ) )
       
   181 			return;
       
   182 
       
   183 		$this->roles[$role] = array(
       
   184 			'name' => $display_name,
       
   185 			'capabilities' => $capabilities
       
   186 			);
       
   187 		if ( $this->use_db )
       
   188 			update_option( $this->role_key, $this->roles );
       
   189 		$this->role_objects[$role] = new WP_Role( $role, $capabilities );
       
   190 		$this->role_names[$role] = $display_name;
       
   191 		return $this->role_objects[$role];
       
   192 	}
       
   193 
       
   194 	/**
       
   195 	 * Remove role by name.
       
   196 	 *
       
   197 	 * @since 2.0.0
       
   198 	 * @access public
       
   199 	 *
       
   200 	 * @param string $role Role name.
       
   201 	 */
       
   202 	public function remove_role( $role ) {
       
   203 		if ( ! isset( $this->role_objects[$role] ) )
       
   204 			return;
       
   205 
       
   206 		unset( $this->role_objects[$role] );
       
   207 		unset( $this->role_names[$role] );
       
   208 		unset( $this->roles[$role] );
       
   209 
       
   210 		if ( $this->use_db )
       
   211 			update_option( $this->role_key, $this->roles );
       
   212 
       
   213 		if ( get_option( 'default_role' ) == $role )
       
   214 			update_option( 'default_role', 'subscriber' );
       
   215 	}
       
   216 
       
   217 	/**
       
   218 	 * Add capability to role.
       
   219 	 *
       
   220 	 * @since 2.0.0
       
   221 	 * @access public
       
   222 	 *
       
   223 	 * @param string $role Role name.
       
   224 	 * @param string $cap Capability name.
       
   225 	 * @param bool $grant Optional, default is true. Whether role is capable of performing capability.
       
   226 	 */
       
   227 	public function add_cap( $role, $cap, $grant = true ) {
       
   228 		if ( ! isset( $this->roles[$role] ) )
       
   229 			return;
       
   230 
       
   231 		$this->roles[$role]['capabilities'][$cap] = $grant;
       
   232 		if ( $this->use_db )
       
   233 			update_option( $this->role_key, $this->roles );
       
   234 	}
       
   235 
       
   236 	/**
       
   237 	 * Remove capability from role.
       
   238 	 *
       
   239 	 * @since 2.0.0
       
   240 	 * @access public
       
   241 	 *
       
   242 	 * @param string $role Role name.
       
   243 	 * @param string $cap Capability name.
       
   244 	 */
       
   245 	public function remove_cap( $role, $cap ) {
       
   246 		if ( ! isset( $this->roles[$role] ) )
       
   247 			return;
       
   248 
       
   249 		unset( $this->roles[$role]['capabilities'][$cap] );
       
   250 		if ( $this->use_db )
       
   251 			update_option( $this->role_key, $this->roles );
       
   252 	}
       
   253 
       
   254 	/**
       
   255 	 * Retrieve role object by name.
       
   256 	 *
       
   257 	 * @since 2.0.0
       
   258 	 * @access public
       
   259 	 *
       
   260 	 * @param string $role Role name.
       
   261 	 * @return WP_Role|null WP_Role object if found, null if the role does not exist.
       
   262 	 */
       
   263 	public function get_role( $role ) {
       
   264 		if ( isset( $this->role_objects[$role] ) )
       
   265 			return $this->role_objects[$role];
       
   266 		else
       
   267 			return null;
       
   268 	}
       
   269 
       
   270 	/**
       
   271 	 * Retrieve list of role names.
       
   272 	 *
       
   273 	 * @since 2.0.0
       
   274 	 * @access public
       
   275 	 *
       
   276 	 * @return array List of role names.
       
   277 	 */
       
   278 	public function get_names() {
       
   279 		return $this->role_names;
       
   280 	}
       
   281 
       
   282 	/**
       
   283 	 * Whether role name is currently in the list of available roles.
       
   284 	 *
       
   285 	 * @since 2.0.0
       
   286 	 * @access public
       
   287 	 *
       
   288 	 * @param string $role Role name to look up.
       
   289 	 * @return bool
       
   290 	 */
       
   291 	public function is_role( $role ) {
       
   292 		return isset( $this->role_names[$role] );
       
   293 	}
       
   294 }
       
   295 
       
   296 /**
       
   297  * WordPress Role class.
       
   298  *
       
   299  * @since 2.0.0
       
   300  * @package WordPress
       
   301  * @subpackage User
       
   302  */
       
   303 class WP_Role {
       
   304 	/**
       
   305 	 * Role name.
       
   306 	 *
       
   307 	 * @since 2.0.0
       
   308 	 * @access public
       
   309 	 * @var string
       
   310 	 */
       
   311 	public $name;
       
   312 
       
   313 	/**
       
   314 	 * List of capabilities the role contains.
       
   315 	 *
       
   316 	 * @since 2.0.0
       
   317 	 * @access public
       
   318 	 * @var array
       
   319 	 */
       
   320 	public $capabilities;
       
   321 
       
   322 	/**
       
   323 	 * Constructor - Set up object properties.
       
   324 	 *
       
   325 	 * The list of capabilities, must have the key as the name of the capability
       
   326 	 * and the value a boolean of whether it is granted to the role.
       
   327 	 *
       
   328 	 * @since 2.0.0
       
   329 	 * @access public
       
   330 	 *
       
   331 	 * @param string $role Role name.
       
   332 	 * @param array $capabilities List of capabilities.
       
   333 	 */
       
   334 	public function __construct( $role, $capabilities ) {
       
   335 		$this->name = $role;
       
   336 		$this->capabilities = $capabilities;
       
   337 	}
       
   338 
       
   339 	/**
       
   340 	 * Assign role a capability.
       
   341 	 *
       
   342 	 * @see WP_Roles::add_cap() Method uses implementation for role.
       
   343 	 * @since 2.0.0
       
   344 	 * @access public
       
   345 	 *
       
   346 	 * @param string $cap Capability name.
       
   347 	 * @param bool $grant Whether role has capability privilege.
       
   348 	 */
       
   349 	public function add_cap( $cap, $grant = true ) {
       
   350 		global $wp_roles;
       
   351 
       
   352 		if ( ! isset( $wp_roles ) )
       
   353 			$wp_roles = new WP_Roles();
       
   354 
       
   355 		$this->capabilities[$cap] = $grant;
       
   356 		$wp_roles->add_cap( $this->name, $cap, $grant );
       
   357 	}
       
   358 
       
   359 	/**
       
   360 	 * Remove capability from role.
       
   361 	 *
       
   362 	 * This is a container for {@link WP_Roles::remove_cap()} to remove the
       
   363 	 * capability from the role. That is to say, that {@link
       
   364 	 * WP_Roles::remove_cap()} implements the functionality, but it also makes
       
   365 	 * sense to use this class, because you don't need to enter the role name.
       
   366 	 *
       
   367 	 * @since 2.0.0
       
   368 	 * @access public
       
   369 	 *
       
   370 	 * @param string $cap Capability name.
       
   371 	 */
       
   372 	public function remove_cap( $cap ) {
       
   373 		global $wp_roles;
       
   374 
       
   375 		if ( ! isset( $wp_roles ) )
       
   376 			$wp_roles = new WP_Roles();
       
   377 
       
   378 		unset( $this->capabilities[$cap] );
       
   379 		$wp_roles->remove_cap( $this->name, $cap );
       
   380 	}
       
   381 
       
   382 	/**
       
   383 	 * Whether role has capability.
       
   384 	 *
       
   385 	 * The capabilities is passed through the 'role_has_cap' filter. The first
       
   386 	 * parameter for the hook is the list of capabilities the class has
       
   387 	 * assigned. The second parameter is the capability name to look for. The
       
   388 	 * third and final parameter for the hook is the role name.
       
   389 	 *
       
   390 	 * @since 2.0.0
       
   391 	 * @access public
       
   392 	 *
       
   393 	 * @param string $cap Capability name.
       
   394 	 * @return bool True, if user has capability. False, if doesn't have capability.
       
   395 	 */
       
   396 	public function has_cap( $cap ) {
       
   397 		/**
       
   398 		 * Filter which capabilities a role has.
       
   399 		 *
       
   400 		 * @since 2.0.0
       
   401 		 *
       
   402 		 * @param array  $capabilities Array of role capabilities.
       
   403 		 * @param string $cap          Capability name.
       
   404 		 * @param string $name         Role name.
       
   405 		 */
       
   406 		$capabilities = apply_filters( 'role_has_cap', $this->capabilities, $cap, $this->name );
       
   407 		if ( !empty( $capabilities[$cap] ) )
       
   408 			return $capabilities[$cap];
       
   409 		else
       
   410 			return false;
       
   411 	}
       
   412 
       
   413 }
       
   414 
       
   415 /**
       
   416  * WordPress User class.
       
   417  *
       
   418  * @since 2.0.0
       
   419  * @package WordPress
       
   420  * @subpackage User
       
   421  *
       
   422  * @property string $nickname
       
   423  * @property string $user_description
       
   424  * @property string $user_firstname
       
   425  * @property string $user_lastname
       
   426  * @property string $user_login
       
   427  * @property string $user_pass
       
   428  * @property string $user_nicename
       
   429  * @property string $user_email
       
   430  * @property string $user_url
       
   431  * @property string $user_registered
       
   432  * @property string $user_activation_key
       
   433  * @property string $user_status
       
   434  * @property string $display_name
       
   435  * @property string $spam
       
   436  * @property string $deleted
       
   437  */
       
   438 class WP_User {
       
   439 	/**
       
   440 	 * User data container.
       
   441 	 *
       
   442 	 * @since 2.0.0
       
   443 	 * @var object
       
   444 	 */
       
   445 	public $data;
       
   446 
       
   447 	/**
       
   448 	 * The user's ID.
       
   449 	 *
       
   450 	 * @since 2.1.0
       
   451 	 * @access public
       
   452 	 * @var int
       
   453 	 */
       
   454 	public $ID = 0;
       
   455 
       
   456 	/**
       
   457 	 * The individual capabilities the user has been given.
       
   458 	 *
       
   459 	 * @since 2.0.0
       
   460 	 * @access public
       
   461 	 * @var array
       
   462 	 */
       
   463 	public $caps = array();
       
   464 
       
   465 	/**
       
   466 	 * User metadata option name.
       
   467 	 *
       
   468 	 * @since 2.0.0
       
   469 	 * @access public
       
   470 	 * @var string
       
   471 	 */
       
   472 	public $cap_key;
       
   473 
       
   474 	/**
       
   475 	 * The roles the user is part of.
       
   476 	 *
       
   477 	 * @since 2.0.0
       
   478 	 * @access public
       
   479 	 * @var array
       
   480 	 */
       
   481 	public $roles = array();
       
   482 
       
   483 	/**
       
   484 	 * All capabilities the user has, including individual and role based.
       
   485 	 *
       
   486 	 * @since 2.0.0
       
   487 	 * @access public
       
   488 	 * @var array
       
   489 	 */
       
   490 	public $allcaps = array();
       
   491 
       
   492 	/**
       
   493 	 * The filter context applied to user data fields.
       
   494 	 *
       
   495 	 * @since 2.9.0
       
   496 	 * @access private
       
   497 	 * @var string
       
   498 	 */
       
   499 	var $filter = null;
       
   500 
       
   501 	private static $back_compat_keys;
       
   502 
       
   503 	/**
       
   504 	 * Constructor
       
   505 	 *
       
   506 	 * Retrieves the userdata and passes it to {@link WP_User::init()}.
       
   507 	 *
       
   508 	 * @since 2.0.0
       
   509 	 * @access public
       
   510 	 *
       
   511 	 * @param int|string|stdClass|WP_User $id User's ID, a WP_User object, or a user object from the DB.
       
   512 	 * @param string $name Optional. User's username
       
   513 	 * @param int $blog_id Optional Blog ID, defaults to current blog.
       
   514 	 */
       
   515 	public function __construct( $id = 0, $name = '', $blog_id = '' ) {
       
   516 		if ( ! isset( self::$back_compat_keys ) ) {
       
   517 			$prefix = $GLOBALS['wpdb']->prefix;
       
   518 			self::$back_compat_keys = array(
       
   519 				'user_firstname' => 'first_name',
       
   520 				'user_lastname' => 'last_name',
       
   521 				'user_description' => 'description',
       
   522 				'user_level' => $prefix . 'user_level',
       
   523 				$prefix . 'usersettings' => $prefix . 'user-settings',
       
   524 				$prefix . 'usersettingstime' => $prefix . 'user-settings-time',
       
   525 			);
       
   526 		}
       
   527 
       
   528 		if ( $id instanceof WP_User ) {
       
   529 			$this->init( $id->data, $blog_id );
       
   530 			return;
       
   531 		} elseif ( is_object( $id ) ) {
       
   532 			$this->init( $id, $blog_id );
       
   533 			return;
       
   534 		}
       
   535 
       
   536 		if ( ! empty( $id ) && ! is_numeric( $id ) ) {
       
   537 			$name = $id;
       
   538 			$id = 0;
       
   539 		}
       
   540 
       
   541 		if ( $id ) {
       
   542 			$data = self::get_data_by( 'id', $id );
       
   543 		} else {
       
   544 			$data = self::get_data_by( 'login', $name );
       
   545 		}
       
   546 
       
   547 		if ( $data ) {
       
   548 			$this->init( $data, $blog_id );
       
   549 		} else {
       
   550 			$this->data = new stdClass;
       
   551 		}
       
   552 	}
       
   553 
       
   554 	/**
       
   555 	 * Sets up object properties, including capabilities.
       
   556 	 *
       
   557 	 * @param object $data User DB row object
       
   558 	 * @param int $blog_id Optional. The blog id to initialize for
       
   559 	 */
       
   560 	public function init( $data, $blog_id = '' ) {
       
   561 		$this->data = $data;
       
   562 		$this->ID = (int) $data->ID;
       
   563 
       
   564 		$this->for_blog( $blog_id );
       
   565 	}
       
   566 
       
   567 	/**
       
   568 	 * Return only the main user fields
       
   569 	 *
       
   570 	 * @since 3.3.0
       
   571 	 *
       
   572 	 * @param string $field The field to query against: 'id', 'slug', 'email' or 'login'
       
   573 	 * @param string|int $value The field value
       
   574 	 * @return object|false Raw user object
       
   575 	 */
       
   576 	public static function get_data_by( $field, $value ) {
       
   577 		global $wpdb;
       
   578 
       
   579 		if ( 'id' == $field ) {
       
   580 			// Make sure the value is numeric to avoid casting objects, for example,
       
   581 			// to int 1.
       
   582 			if ( ! is_numeric( $value ) )
       
   583 				return false;
       
   584 			$value = intval( $value );
       
   585 			if ( $value < 1 )
       
   586 				return false;
       
   587 		} else {
       
   588 			$value = trim( $value );
       
   589 		}
       
   590 
       
   591 		if ( !$value )
       
   592 			return false;
       
   593 
       
   594 		switch ( $field ) {
       
   595 			case 'id':
       
   596 				$user_id = $value;
       
   597 				$db_field = 'ID';
       
   598 				break;
       
   599 			case 'slug':
       
   600 				$user_id = wp_cache_get($value, 'userslugs');
       
   601 				$db_field = 'user_nicename';
       
   602 				break;
       
   603 			case 'email':
       
   604 				$user_id = wp_cache_get($value, 'useremail');
       
   605 				$db_field = 'user_email';
       
   606 				break;
       
   607 			case 'login':
       
   608 				$value = sanitize_user( $value );
       
   609 				$user_id = wp_cache_get($value, 'userlogins');
       
   610 				$db_field = 'user_login';
       
   611 				break;
       
   612 			default:
       
   613 				return false;
       
   614 		}
       
   615 
       
   616 		if ( false !== $user_id ) {
       
   617 			if ( $user = wp_cache_get( $user_id, 'users' ) )
       
   618 				return $user;
       
   619 		}
       
   620 
       
   621 		if ( !$user = $wpdb->get_row( $wpdb->prepare(
       
   622 			"SELECT * FROM $wpdb->users WHERE $db_field = %s", $value
       
   623 		) ) )
       
   624 			return false;
       
   625 
       
   626 		update_user_caches( $user );
       
   627 
       
   628 		return $user;
       
   629 	}
       
   630 
       
   631 	/**
       
   632 	 * Magic method for checking the existence of a certain custom field
       
   633 	 *
       
   634 	 * @since 3.3.0
       
   635 	 * @param string $key
       
   636 	 * @return bool
       
   637 	 */
       
   638 	public function __isset( $key ) {
       
   639 		if ( 'id' == $key ) {
       
   640 			_deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) );
       
   641 			$key = 'ID';
       
   642 		}
       
   643 
       
   644 		if ( isset( $this->data->$key ) )
       
   645 			return true;
       
   646 
       
   647 		if ( isset( self::$back_compat_keys[ $key ] ) )
       
   648 			$key = self::$back_compat_keys[ $key ];
       
   649 
       
   650 		return metadata_exists( 'user', $this->ID, $key );
       
   651 	}
       
   652 
       
   653 	/**
       
   654 	 * Magic method for accessing custom fields
       
   655 	 *
       
   656 	 * @since 3.3.0
       
   657 	 * @param string $key
       
   658 	 * @return mixed
       
   659 	 */
       
   660 	public function __get( $key ) {
       
   661 		if ( 'id' == $key ) {
       
   662 			_deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) );
       
   663 			return $this->ID;
       
   664 		}
       
   665 
       
   666 		if ( isset( $this->data->$key ) ) {
       
   667 			$value = $this->data->$key;
       
   668 		} else {
       
   669 			if ( isset( self::$back_compat_keys[ $key ] ) )
       
   670 				$key = self::$back_compat_keys[ $key ];
       
   671 			$value = get_user_meta( $this->ID, $key, true );
       
   672 		}
       
   673 
       
   674 		if ( $this->filter ) {
       
   675 			$value = sanitize_user_field( $key, $value, $this->ID, $this->filter );
       
   676 		}
       
   677 
       
   678 		return $value;
       
   679 	}
       
   680 
       
   681 	/**
       
   682 	 * Magic method for setting custom fields
       
   683 	 *
       
   684 	 * @since 3.3.0
       
   685 	 */
       
   686 	public function __set( $key, $value ) {
       
   687 		if ( 'id' == $key ) {
       
   688 			_deprecated_argument( 'WP_User->id', '2.1', __( 'Use <code>WP_User->ID</code> instead.' ) );
       
   689 			$this->ID = $value;
       
   690 			return;
       
   691 		}
       
   692 
       
   693 		$this->data->$key = $value;
       
   694 	}
       
   695 
       
   696 	/**
       
   697 	 * Determine whether the user exists in the database.
       
   698 	 *
       
   699 	 * @since 3.4.0
       
   700 	 * @access public
       
   701 	 *
       
   702 	 * @return bool True if user exists in the database, false if not.
       
   703 	 */
       
   704 	public function exists() {
       
   705 		return ! empty( $this->ID );
       
   706 	}
       
   707 
       
   708 	/**
       
   709 	 * Retrieve the value of a property or meta key.
       
   710 	 *
       
   711 	 * Retrieves from the users and usermeta table.
       
   712 	 *
       
   713 	 * @since 3.3.0
       
   714 	 *
       
   715 	 * @param string $key Property
       
   716 	 */
       
   717 	public function get( $key ) {
       
   718 		return $this->__get( $key );
       
   719 	}
       
   720 
       
   721 	/**
       
   722 	 * Determine whether a property or meta key is set
       
   723 	 *
       
   724 	 * Consults the users and usermeta tables.
       
   725 	 *
       
   726 	 * @since 3.3.0
       
   727 	 *
       
   728 	 * @param string $key Property
       
   729 	 */
       
   730 	public function has_prop( $key ) {
       
   731 		return $this->__isset( $key );
       
   732 	}
       
   733 
       
   734 	/**
       
   735 	 * Return an array representation.
       
   736 	 *
       
   737 	 * @since 3.5.0
       
   738 	 *
       
   739 	 * @return array Array representation.
       
   740 	 */
       
   741 	public function to_array() {
       
   742 		return get_object_vars( $this->data );
       
   743 	}
       
   744 
       
   745 	/**
       
   746 	 * Set up capability object properties.
       
   747 	 *
       
   748 	 * Will set the value for the 'cap_key' property to current database table
       
   749 	 * prefix, followed by 'capabilities'. Will then check to see if the
       
   750 	 * property matching the 'cap_key' exists and is an array. If so, it will be
       
   751 	 * used.
       
   752 	 *
       
   753 	 * @access protected
       
   754 	 * @since 2.1.0
       
   755 	 *
       
   756 	 * @param string $cap_key Optional capability key
       
   757 	 */
       
   758 	function _init_caps( $cap_key = '' ) {
       
   759 		global $wpdb;
       
   760 
       
   761 		if ( empty($cap_key) )
       
   762 			$this->cap_key = $wpdb->get_blog_prefix() . 'capabilities';
       
   763 		else
       
   764 			$this->cap_key = $cap_key;
       
   765 
       
   766 		$this->caps = get_user_meta( $this->ID, $this->cap_key, true );
       
   767 
       
   768 		if ( ! is_array( $this->caps ) )
       
   769 			$this->caps = array();
       
   770 
       
   771 		$this->get_role_caps();
       
   772 	}
       
   773 
       
   774 	/**
       
   775 	 * Retrieve all of the role capabilities and merge with individual capabilities.
       
   776 	 *
       
   777 	 * All of the capabilities of the roles the user belongs to are merged with
       
   778 	 * the users individual roles. This also means that the user can be denied
       
   779 	 * specific roles that their role might have, but the specific user isn't
       
   780 	 * granted permission to.
       
   781 	 *
       
   782 	 * @since 2.0.0
       
   783 	 * @uses $wp_roles
       
   784 	 * @access public
       
   785 	 *
       
   786 	 * @return array List of all capabilities for the user.
       
   787 	 */
       
   788 	public function get_role_caps() {
       
   789 		global $wp_roles;
       
   790 
       
   791 		if ( ! isset( $wp_roles ) )
       
   792 			$wp_roles = new WP_Roles();
       
   793 
       
   794 		//Filter out caps that are not role names and assign to $this->roles
       
   795 		if ( is_array( $this->caps ) )
       
   796 			$this->roles = array_filter( array_keys( $this->caps ), array( $wp_roles, 'is_role' ) );
       
   797 
       
   798 		//Build $allcaps from role caps, overlay user's $caps
       
   799 		$this->allcaps = array();
       
   800 		foreach ( (array) $this->roles as $role ) {
       
   801 			$the_role = $wp_roles->get_role( $role );
       
   802 			$this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
       
   803 		}
       
   804 		$this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );
       
   805 
       
   806 		return $this->allcaps;
       
   807 	}
       
   808 
       
   809 	/**
       
   810 	 * Add role to user.
       
   811 	 *
       
   812 	 * Updates the user's meta data option with capabilities and roles.
       
   813 	 *
       
   814 	 * @since 2.0.0
       
   815 	 * @access public
       
   816 	 *
       
   817 	 * @param string $role Role name.
       
   818 	 */
       
   819 	public function add_role( $role ) {
       
   820 		$this->caps[$role] = true;
       
   821 		update_user_meta( $this->ID, $this->cap_key, $this->caps );
       
   822 		$this->get_role_caps();
       
   823 		$this->update_user_level_from_caps();
       
   824 	}
       
   825 
       
   826 	/**
       
   827 	 * Remove role from user.
       
   828 	 *
       
   829 	 * @since 2.0.0
       
   830 	 * @access public
       
   831 	 *
       
   832 	 * @param string $role Role name.
       
   833 	 */
       
   834 	public function remove_role( $role ) {
       
   835 		if ( !in_array($role, $this->roles) )
       
   836 			return;
       
   837 		unset( $this->caps[$role] );
       
   838 		update_user_meta( $this->ID, $this->cap_key, $this->caps );
       
   839 		$this->get_role_caps();
       
   840 		$this->update_user_level_from_caps();
       
   841 	}
       
   842 
       
   843 	/**
       
   844 	 * Set the role of the user.
       
   845 	 *
       
   846 	 * This will remove the previous roles of the user and assign the user the
       
   847 	 * new one. You can set the role to an empty string and it will remove all
       
   848 	 * of the roles from the user.
       
   849 	 *
       
   850 	 * @since 2.0.0
       
   851 	 * @access public
       
   852 	 *
       
   853 	 * @param string $role Role name.
       
   854 	 */
       
   855 	public function set_role( $role ) {
       
   856 		if ( 1 == count( $this->roles ) && $role == current( $this->roles ) )
       
   857 			return;
       
   858 
       
   859 		foreach ( (array) $this->roles as $oldrole )
       
   860 			unset( $this->caps[$oldrole] );
       
   861 
       
   862 		$old_roles = $this->roles;
       
   863 		if ( !empty( $role ) ) {
       
   864 			$this->caps[$role] = true;
       
   865 			$this->roles = array( $role => true );
       
   866 		} else {
       
   867 			$this->roles = false;
       
   868 		}
       
   869 		update_user_meta( $this->ID, $this->cap_key, $this->caps );
       
   870 		$this->get_role_caps();
       
   871 		$this->update_user_level_from_caps();
       
   872 
       
   873 		/**
       
   874 		 * Fires after the user's role has changed.
       
   875 		 *
       
   876 		 * @since 2.9.0
       
   877 		 * @since 3.6.0 Added $old_roles to include an array of the user's previous roles.
       
   878 		 *
       
   879 		 * @param int    $user_id   The user ID.
       
   880 		 * @param string $role      The new role.
       
   881 		 * @param array  $old_roles An array of the user's previous roles.
       
   882 		 */
       
   883 		do_action( 'set_user_role', $this->ID, $role, $old_roles );
       
   884 	}
       
   885 
       
   886 	/**
       
   887 	 * Choose the maximum level the user has.
       
   888 	 *
       
   889 	 * Will compare the level from the $item parameter against the $max
       
   890 	 * parameter. If the item is incorrect, then just the $max parameter value
       
   891 	 * will be returned.
       
   892 	 *
       
   893 	 * Used to get the max level based on the capabilities the user has. This
       
   894 	 * is also based on roles, so if the user is assigned the Administrator role
       
   895 	 * then the capability 'level_10' will exist and the user will get that
       
   896 	 * value.
       
   897 	 *
       
   898 	 * @since 2.0.0
       
   899 	 * @access public
       
   900 	 *
       
   901 	 * @param int $max Max level of user.
       
   902 	 * @param string $item Level capability name.
       
   903 	 * @return int Max Level.
       
   904 	 */
       
   905 	public function level_reduction( $max, $item ) {
       
   906 		if ( preg_match( '/^level_(10|[0-9])$/i', $item, $matches ) ) {
       
   907 			$level = intval( $matches[1] );
       
   908 			return max( $max, $level );
       
   909 		} else {
       
   910 			return $max;
       
   911 		}
       
   912 	}
       
   913 
       
   914 	/**
       
   915 	 * Update the maximum user level for the user.
       
   916 	 *
       
   917 	 * Updates the 'user_level' user metadata (includes prefix that is the
       
   918 	 * database table prefix) with the maximum user level. Gets the value from
       
   919 	 * the all of the capabilities that the user has.
       
   920 	 *
       
   921 	 * @since 2.0.0
       
   922 	 * @access public
       
   923 	 */
       
   924 	public function update_user_level_from_caps() {
       
   925 		global $wpdb;
       
   926 		$this->user_level = array_reduce( array_keys( $this->allcaps ), array( $this, 'level_reduction' ), 0 );
       
   927 		update_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level', $this->user_level );
       
   928 	}
       
   929 
       
   930 	/**
       
   931 	 * Add capability and grant or deny access to capability.
       
   932 	 *
       
   933 	 * @since 2.0.0
       
   934 	 * @access public
       
   935 	 *
       
   936 	 * @param string $cap Capability name.
       
   937 	 * @param bool $grant Whether to grant capability to user.
       
   938 	 */
       
   939 	public function add_cap( $cap, $grant = true ) {
       
   940 		$this->caps[$cap] = $grant;
       
   941 		update_user_meta( $this->ID, $this->cap_key, $this->caps );
       
   942 		$this->get_role_caps();
       
   943 		$this->update_user_level_from_caps();
       
   944 	}
       
   945 
       
   946 	/**
       
   947 	 * Remove capability from user.
       
   948 	 *
       
   949 	 * @since 2.0.0
       
   950 	 * @access public
       
   951 	 *
       
   952 	 * @param string $cap Capability name.
       
   953 	 */
       
   954 	public function remove_cap( $cap ) {
       
   955 		if ( ! isset( $this->caps[ $cap ] ) ) {
       
   956 			return;
       
   957 		}
       
   958 		unset( $this->caps[ $cap ] );
       
   959 		update_user_meta( $this->ID, $this->cap_key, $this->caps );
       
   960 		$this->get_role_caps();
       
   961 		$this->update_user_level_from_caps();
       
   962 	}
       
   963 
       
   964 	/**
       
   965 	 * Remove all of the capabilities of the user.
       
   966 	 *
       
   967 	 * @since 2.1.0
       
   968 	 * @access public
       
   969 	 */
       
   970 	public function remove_all_caps() {
       
   971 		global $wpdb;
       
   972 		$this->caps = array();
       
   973 		delete_user_meta( $this->ID, $this->cap_key );
       
   974 		delete_user_meta( $this->ID, $wpdb->get_blog_prefix() . 'user_level' );
       
   975 		$this->get_role_caps();
       
   976 	}
       
   977 
       
   978 	/**
       
   979 	 * Whether user has capability or role name.
       
   980 	 *
       
   981 	 * This is useful for looking up whether the user has a specific role
       
   982 	 * assigned to the user. The second optional parameter can also be used to
       
   983 	 * check for capabilities against a specific object, such as a post or user.
       
   984 	 *
       
   985 	 * @since 2.0.0
       
   986 	 * @access public
       
   987 	 *
       
   988 	 * @param string|int $cap Capability or role name to search.
       
   989 	 * @return bool True, if user has capability; false, if user does not have capability.
       
   990 	 */
       
   991 	public function has_cap( $cap ) {
       
   992 		if ( is_numeric( $cap ) ) {
       
   993 			_deprecated_argument( __FUNCTION__, '2.0', __('Usage of user levels by plugins and themes is deprecated. Use roles and capabilities instead.') );
       
   994 			$cap = $this->translate_level_to_cap( $cap );
       
   995 		}
       
   996 
       
   997 		$args = array_slice( func_get_args(), 1 );
       
   998 		$args = array_merge( array( $cap, $this->ID ), $args );
       
   999 		$caps = call_user_func_array( 'map_meta_cap', $args );
       
  1000 
       
  1001 		// Multisite super admin has all caps by definition, Unless specifically denied.
       
  1002 		if ( is_multisite() && is_super_admin( $this->ID ) ) {
       
  1003 			if ( in_array('do_not_allow', $caps) )
       
  1004 				return false;
       
  1005 			return true;
       
  1006 		}
       
  1007 
       
  1008 		/**
       
  1009 		 * Dynamically filter a user's capabilities.
       
  1010 		 *
       
  1011 		 * @since 2.0.0
       
  1012 		 * @since 3.7.0 Added the user object.
       
  1013 		 *
       
  1014 		 * @param array   $allcaps An array of all the user's capabilities.
       
  1015 		 * @param array   $caps    Actual capabilities for meta capability.
       
  1016 		 * @param array   $args    Optional parameters passed to has_cap(), typically object ID.
       
  1017 		 * @param WP_User $user    The user object.
       
  1018 		 */
       
  1019 		// Must have ALL requested caps
       
  1020 		$capabilities = apply_filters( 'user_has_cap', $this->allcaps, $caps, $args, $this );
       
  1021 		$capabilities['exist'] = true; // Everyone is allowed to exist
       
  1022 		foreach ( (array) $caps as $cap ) {
       
  1023 			if ( empty( $capabilities[ $cap ] ) )
       
  1024 				return false;
       
  1025 		}
       
  1026 
       
  1027 		return true;
       
  1028 	}
       
  1029 
       
  1030 	/**
       
  1031 	 * Convert numeric level to level capability name.
       
  1032 	 *
       
  1033 	 * Prepends 'level_' to level number.
       
  1034 	 *
       
  1035 	 * @since 2.0.0
       
  1036 	 * @access public
       
  1037 	 *
       
  1038 	 * @param int $level Level number, 1 to 10.
       
  1039 	 * @return string
       
  1040 	 */
       
  1041 	public function translate_level_to_cap( $level ) {
       
  1042 		return 'level_' . $level;
       
  1043 	}
       
  1044 
       
  1045 	/**
       
  1046 	 * Set the blog to operate on. Defaults to the current blog.
       
  1047 	 *
       
  1048 	 * @since 3.0.0
       
  1049 	 *
       
  1050 	 * @param int $blog_id Optional Blog ID, defaults to current blog.
       
  1051 	 */
       
  1052 	public function for_blog( $blog_id = '' ) {
       
  1053 		global $wpdb;
       
  1054 		if ( ! empty( $blog_id ) )
       
  1055 			$cap_key = $wpdb->get_blog_prefix( $blog_id ) . 'capabilities';
       
  1056 		else
       
  1057 			$cap_key = '';
       
  1058 		$this->_init_caps( $cap_key );
       
  1059 	}
       
  1060 }
       
  1061 
     8 
  1062 /**
     9 /**
  1063  * Map meta capabilities to primitive capabilities.
    10  * Map meta capabilities to primitive capabilities.
  1064  *
    11  *
  1065  * This does not actually compare whether the user ID has the actual capability,
    12  * This does not actually compare whether the user ID has the actual capability,
  1067  * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post',
    14  * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post',
  1068  * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'.
    15  * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'.
  1069  *
    16  *
  1070  * @since 2.0.0
    17  * @since 2.0.0
  1071  *
    18  *
  1072  * @param string $cap Capability name.
    19  * @global array $post_type_meta_caps Used to get post type meta capabilities.
  1073  * @param int $user_id User ID.
    20  *
       
    21  * @param string $cap       Capability name.
       
    22  * @param int    $user_id   User ID.
       
    23  * @param int    $object_id Optional. ID of the specific object to check against if `$cap` is a "meta" cap.
       
    24  *                          "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
       
    25  *                          by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
       
    26  *                          'edit_others_posts', etc. The parameter is accessed via func_get_args().
  1074  * @return array Actual capabilities for meta capability.
    27  * @return array Actual capabilities for meta capability.
  1075  */
    28  */
  1076 function map_meta_cap( $cap, $user_id ) {
    29 function map_meta_cap( $cap, $user_id ) {
  1077 	$args = array_slice( func_get_args(), 2 );
    30 	$args = array_slice( func_get_args(), 2 );
  1078 	$caps = array();
    31 	$caps = array();
  1079 
    32 
  1080 	switch ( $cap ) {
    33 	switch ( $cap ) {
  1081 	case 'remove_user':
    34 	case 'remove_user':
  1082 		$caps[] = 'remove_users';
    35 		// In multisite the user must be a super admin to remove themselves.
       
    36 		if ( isset( $args[0] ) && $user_id == $args[0] && ! is_super_admin( $user_id ) ) {
       
    37 			$caps[] = 'do_not_allow';
       
    38 		} else {
       
    39 			$caps[] = 'remove_users';
       
    40 		}
  1083 		break;
    41 		break;
  1084 	case 'promote_user':
    42 	case 'promote_user':
       
    43 	case 'add_users':
  1085 		$caps[] = 'promote_users';
    44 		$caps[] = 'promote_users';
  1086 		break;
    45 		break;
  1087 	case 'edit_user':
    46 	case 'edit_user':
  1088 	case 'edit_users':
    47 	case 'edit_users':
  1089 		// Allow user to edit itself
    48 		// Allow user to edit itself
  1090 		if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] )
    49 		if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] )
  1091 			break;
    50 			break;
  1092 
    51 
  1093 		// If multisite these caps are allowed only for super admins.
    52 		// In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
  1094 		if ( is_multisite() && !is_super_admin( $user_id ) )
    53 		if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
  1095 			$caps[] = 'do_not_allow';
    54 			$caps[] = 'do_not_allow';
  1096 		else
    55 		} else {
  1097 			$caps[] = 'edit_users'; // edit_user maps to edit_users.
    56 			$caps[] = 'edit_users'; // edit_user maps to edit_users.
       
    57 		}
  1098 		break;
    58 		break;
  1099 	case 'delete_post':
    59 	case 'delete_post':
  1100 	case 'delete_page':
    60 	case 'delete_page':
  1101 		$post = get_post( $args[0] );
    61 		$post = get_post( $args[0] );
       
    62 		if ( ! $post ) {
       
    63 			$caps[] = 'do_not_allow';
       
    64 			break;
       
    65 		}
  1102 
    66 
  1103 		if ( 'revision' == $post->post_type ) {
    67 		if ( 'revision' == $post->post_type ) {
  1104 			$post = get_post( $post->post_parent );
    68 			$post = get_post( $post->post_parent );
       
    69 			if ( ! $post ) {
       
    70 				$caps[] = 'do_not_allow';
       
    71 				break;
       
    72 			}
       
    73 		}
       
    74 
       
    75 		if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) {
       
    76 			$caps[] = 'manage_options';
       
    77 			break;
  1105 		}
    78 		}
  1106 
    79 
  1107 		$post_type = get_post_type_object( $post->post_type );
    80 		$post_type = get_post_type_object( $post->post_type );
       
    81 		if ( ! $post_type ) {
       
    82 			/* translators: 1: post type, 2: capability name */
       
    83 			_doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
       
    84 			$caps[] = 'edit_others_posts';
       
    85 			break;
       
    86 		}
  1108 
    87 
  1109 		if ( ! $post_type->map_meta_cap ) {
    88 		if ( ! $post_type->map_meta_cap ) {
  1110 			$caps[] = $post_type->cap->$cap;
    89 			$caps[] = $post_type->cap->$cap;
  1111 			// Prior to 3.1 we would re-call map_meta_cap here.
    90 			// Prior to 3.1 we would re-call map_meta_cap here.
  1112 			if ( 'delete_post' == $cap )
    91 			if ( 'delete_post' == $cap )
  1114 			break;
    93 			break;
  1115 		}
    94 		}
  1116 
    95 
  1117 		// If the post author is set and the user is the author...
    96 		// If the post author is set and the user is the author...
  1118 		if ( $post->post_author && $user_id == $post->post_author ) {
    97 		if ( $post->post_author && $user_id == $post->post_author ) {
  1119 			// If the post is published...
    98 			// If the post is published or scheduled...
  1120 			if ( 'publish' == $post->post_status ) {
    99 			if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  1121 				$caps[] = $post_type->cap->delete_published_posts;
   100 				$caps[] = $post_type->cap->delete_published_posts;
  1122 			} elseif ( 'trash' == $post->post_status ) {
   101 			} elseif ( 'trash' == $post->post_status ) {
  1123 				if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) {
   102 				$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
       
   103 				if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
  1124 					$caps[] = $post_type->cap->delete_published_posts;
   104 					$caps[] = $post_type->cap->delete_published_posts;
       
   105 				} else {
       
   106 					$caps[] = $post_type->cap->delete_posts;
  1125 				}
   107 				}
  1126 			} else {
   108 			} else {
  1127 				// If the post is draft...
   109 				// If the post is draft...
  1128 				$caps[] = $post_type->cap->delete_posts;
   110 				$caps[] = $post_type->cap->delete_posts;
  1129 			}
   111 			}
  1130 		} else {
   112 		} else {
  1131 			// The user is trying to edit someone else's post.
   113 			// The user is trying to edit someone else's post.
  1132 			$caps[] = $post_type->cap->delete_others_posts;
   114 			$caps[] = $post_type->cap->delete_others_posts;
  1133 			// The post is published, extra cap required.
   115 			// The post is published or scheduled, extra cap required.
  1134 			if ( 'publish' == $post->post_status ) {
   116 			if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  1135 				$caps[] = $post_type->cap->delete_published_posts;
   117 				$caps[] = $post_type->cap->delete_published_posts;
  1136 			} elseif ( 'private' == $post->post_status ) {
   118 			} elseif ( 'private' == $post->post_status ) {
  1137 				$caps[] = $post_type->cap->delete_private_posts;
   119 				$caps[] = $post_type->cap->delete_private_posts;
  1138 			}
   120 			}
  1139 		}
   121 		}
       
   122 
       
   123 		/*
       
   124 		 * Setting the privacy policy page requires `manage_privacy_options`,
       
   125 		 * so deleting it should require that too.
       
   126 		 */
       
   127 		if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
       
   128 			$caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
       
   129 		}
       
   130 
  1140 		break;
   131 		break;
  1141 		// edit_post breaks down to edit_posts, edit_published_posts, or
   132 		// edit_post breaks down to edit_posts, edit_published_posts, or
  1142 		// edit_others_posts
   133 		// edit_others_posts
  1143 	case 'edit_post':
   134 	case 'edit_post':
  1144 	case 'edit_page':
   135 	case 'edit_page':
  1145 		$post = get_post( $args[0] );
   136 		$post = get_post( $args[0] );
  1146 		if ( empty( $post ) )
   137 		if ( ! $post ) {
  1147 			break;
   138 			$caps[] = 'do_not_allow';
       
   139 			break;
       
   140 		}
  1148 
   141 
  1149 		if ( 'revision' == $post->post_type ) {
   142 		if ( 'revision' == $post->post_type ) {
  1150 			$post = get_post( $post->post_parent );
   143 			$post = get_post( $post->post_parent );
       
   144 			if ( ! $post ) {
       
   145 				$caps[] = 'do_not_allow';
       
   146 				break;
       
   147 			}
  1151 		}
   148 		}
  1152 
   149 
  1153 		$post_type = get_post_type_object( $post->post_type );
   150 		$post_type = get_post_type_object( $post->post_type );
       
   151 		if ( ! $post_type ) {
       
   152 			/* translators: 1: post type, 2: capability name */
       
   153 			_doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
       
   154 			$caps[] = 'edit_others_posts';
       
   155 			break;
       
   156 		}
  1154 
   157 
  1155 		if ( ! $post_type->map_meta_cap ) {
   158 		if ( ! $post_type->map_meta_cap ) {
  1156 			$caps[] = $post_type->cap->$cap;
   159 			$caps[] = $post_type->cap->$cap;
  1157 			// Prior to 3.1 we would re-call map_meta_cap here.
   160 			// Prior to 3.1 we would re-call map_meta_cap here.
  1158 			if ( 'edit_post' == $cap )
   161 			if ( 'edit_post' == $cap )
  1160 			break;
   163 			break;
  1161 		}
   164 		}
  1162 
   165 
  1163 		// If the post author is set and the user is the author...
   166 		// If the post author is set and the user is the author...
  1164 		if ( $post->post_author && $user_id == $post->post_author ) {
   167 		if ( $post->post_author && $user_id == $post->post_author ) {
  1165 			// If the post is published...
   168 			// If the post is published or scheduled...
  1166 			if ( 'publish' == $post->post_status ) {
   169 			if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  1167 				$caps[] = $post_type->cap->edit_published_posts;
   170 				$caps[] = $post_type->cap->edit_published_posts;
  1168 			} elseif ( 'trash' == $post->post_status ) {
   171 			} elseif ( 'trash' == $post->post_status ) {
  1169 				if ( 'publish' == get_post_meta( $post->ID, '_wp_trash_meta_status', true ) ) {
   172 				$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
       
   173 				if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
  1170 					$caps[] = $post_type->cap->edit_published_posts;
   174 					$caps[] = $post_type->cap->edit_published_posts;
       
   175 				} else {
       
   176 					$caps[] = $post_type->cap->edit_posts;
  1171 				}
   177 				}
  1172 			} else {
   178 			} else {
  1173 				// If the post is draft...
   179 				// If the post is draft...
  1174 				$caps[] = $post_type->cap->edit_posts;
   180 				$caps[] = $post_type->cap->edit_posts;
  1175 			}
   181 			}
  1176 		} else {
   182 		} else {
  1177 			// The user is trying to edit someone else's post.
   183 			// The user is trying to edit someone else's post.
  1178 			$caps[] = $post_type->cap->edit_others_posts;
   184 			$caps[] = $post_type->cap->edit_others_posts;
  1179 			// The post is published, extra cap required.
   185 			// The post is published or scheduled, extra cap required.
  1180 			if ( 'publish' == $post->post_status ) {
   186 			if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
  1181 				$caps[] = $post_type->cap->edit_published_posts;
   187 				$caps[] = $post_type->cap->edit_published_posts;
  1182 			} elseif ( 'private' == $post->post_status ) {
   188 			} elseif ( 'private' == $post->post_status ) {
  1183 				$caps[] = $post_type->cap->edit_private_posts;
   189 				$caps[] = $post_type->cap->edit_private_posts;
  1184 			}
   190 			}
  1185 		}
   191 		}
       
   192 
       
   193 		/*
       
   194 		 * Setting the privacy policy page requires `manage_privacy_options`,
       
   195 		 * so editing it should require that too.
       
   196 		 */
       
   197 		if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
       
   198 			$caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
       
   199 		}
       
   200 
  1186 		break;
   201 		break;
  1187 	case 'read_post':
   202 	case 'read_post':
  1188 	case 'read_page':
   203 	case 'read_page':
  1189 		$post = get_post( $args[0] );
   204 		$post = get_post( $args[0] );
       
   205 		if ( ! $post ) {
       
   206 			$caps[] = 'do_not_allow';
       
   207 			break;
       
   208 		}
  1190 
   209 
  1191 		if ( 'revision' == $post->post_type ) {
   210 		if ( 'revision' == $post->post_type ) {
  1192 			$post = get_post( $post->post_parent );
   211 			$post = get_post( $post->post_parent );
       
   212 			if ( ! $post ) {
       
   213 				$caps[] = 'do_not_allow';
       
   214 				break;
       
   215 			}
  1193 		}
   216 		}
  1194 
   217 
  1195 		$post_type = get_post_type_object( $post->post_type );
   218 		$post_type = get_post_type_object( $post->post_type );
       
   219 		if ( ! $post_type ) {
       
   220 			/* translators: 1: post type, 2: capability name */
       
   221 			_doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
       
   222 			$caps[] = 'edit_others_posts';
       
   223 			break;
       
   224 		}
  1196 
   225 
  1197 		if ( ! $post_type->map_meta_cap ) {
   226 		if ( ! $post_type->map_meta_cap ) {
  1198 			$caps[] = $post_type->cap->$cap;
   227 			$caps[] = $post_type->cap->$cap;
  1199 			// Prior to 3.1 we would re-call map_meta_cap here.
   228 			// Prior to 3.1 we would re-call map_meta_cap here.
  1200 			if ( 'read_post' == $cap )
   229 			if ( 'read_post' == $cap )
  1216 			$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
   245 			$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
  1217 		}
   246 		}
  1218 		break;
   247 		break;
  1219 	case 'publish_post':
   248 	case 'publish_post':
  1220 		$post = get_post( $args[0] );
   249 		$post = get_post( $args[0] );
       
   250 		if ( ! $post ) {
       
   251 			$caps[] = 'do_not_allow';
       
   252 			break;
       
   253 		}
       
   254 
  1221 		$post_type = get_post_type_object( $post->post_type );
   255 		$post_type = get_post_type_object( $post->post_type );
       
   256 		if ( ! $post_type ) {
       
   257 			/* translators: 1: post type, 2: capability name */
       
   258 			_doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
       
   259 			$caps[] = 'edit_others_posts';
       
   260 			break;
       
   261 		}
  1222 
   262 
  1223 		$caps[] = $post_type->cap->publish_posts;
   263 		$caps[] = $post_type->cap->publish_posts;
  1224 		break;
   264 		break;
  1225 	case 'edit_post_meta':
   265 	case 'edit_post_meta':
  1226 	case 'delete_post_meta':
   266 	case 'delete_post_meta':
  1227 	case 'add_post_meta':
   267 	case 'add_post_meta':
  1228 		$post = get_post( $args[0] );
   268 	case 'edit_comment_meta':
  1229 		$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
   269 	case 'delete_comment_meta':
  1230 
   270 	case 'add_comment_meta':
  1231 		$meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false;
   271 	case 'edit_term_meta':
  1232 
   272 	case 'delete_term_meta':
  1233 		if ( $meta_key && has_filter( "auth_post_meta_{$meta_key}" ) ) {
   273 	case 'add_term_meta':
  1234 			/**
   274 	case 'edit_user_meta':
  1235 			 * Filter whether the user is allowed to add post meta to a post.
   275 	case 'delete_user_meta':
  1236 			 *
   276 	case 'add_user_meta':
  1237 			 * The dynamic portion of the hook name, `$meta_key`, refers to the
   277 		list( $_, $object_type, $_ ) = explode( '_', $cap );
  1238 			 * meta key passed to {@see map_meta_cap()}.
   278 		$object_id = (int) $args[0];
  1239 			 *
   279 		$object_subtype = get_object_subtype( $object_type, $object_id );
  1240 			 * @since 3.3.0
   280 
  1241 			 *
   281 		if ( empty( $object_subtype ) ) {
  1242 			 * @param bool   $allowed  Whether the user can add the post meta. Default false.
   282 			$caps[] = 'do_not_allow';
  1243 			 * @param string $meta_key The meta key.
   283 			break;
  1244 			 * @param int    $post_id  Post ID.
   284 		}
  1245 			 * @param int    $user_id  User ID.
   285 
  1246 			 * @param string $cap      Capability name.
   286 		$caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id );
  1247 			 * @param array  $caps     User capabilities.
   287 
  1248 			 */
   288 		$meta_key = isset( $args[1] ) ? $args[1] : false;
  1249 			$allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps );
   289 
  1250 			if ( ! $allowed )
   290 		if ( $meta_key ) {
       
   291 			$allowed = ! is_protected_meta( $meta_key, $object_type );
       
   292 
       
   293 			if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
       
   294 
       
   295 				/**
       
   296 				 * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
       
   297 				 *
       
   298 				 * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
       
   299 				 * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
       
   300 				 * the meta key value, and the object subtype respectively.
       
   301 				 *
       
   302 				 * @since 4.9.8
       
   303 				 *
       
   304 				 * @param bool     $allowed   Whether the user can add the object meta. Default false.
       
   305 				 * @param string   $meta_key  The meta key.
       
   306 				 * @param int      $object_id Object ID.
       
   307 				 * @param int      $user_id   User ID.
       
   308 				 * @param string   $cap       Capability name.
       
   309 				 * @param string[] $caps      Array of the user's capabilities.
       
   310 				 */
       
   311 				$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
       
   312 			} else {
       
   313 
       
   314 				/**
       
   315 				 * Filters whether the user is allowed to edit a specific meta key of a specific object type.
       
   316 				 *
       
   317 				 * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
       
   318 				 *
       
   319 				 * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
       
   320 				 * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
       
   321 				 *
       
   322 				 * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
       
   323 				 * @since 4.6.0
       
   324 				 *
       
   325 				 * @param bool     $allowed   Whether the user can add the object meta. Default false.
       
   326 				 * @param string   $meta_key  The meta key.
       
   327 				 * @param int      $object_id Object ID.
       
   328 				 * @param int      $user_id   User ID.
       
   329 				 * @param string   $cap       Capability name.
       
   330 				 * @param string[] $caps      Array of the user's capabilities.
       
   331 				 */
       
   332 				$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
       
   333 			}
       
   334 
       
   335 			if ( ! empty( $object_subtype ) ) {
       
   336 
       
   337 				/**
       
   338 				 * Filters whether the user is allowed to edit meta for specific object types/subtypes.
       
   339 				 *
       
   340 				 * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
       
   341 				 *
       
   342 				 * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
       
   343 				 * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
       
   344 				 * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
       
   345 				 *
       
   346 				 * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
       
   347 				 * @since 4.7.0
       
   348 				 * @deprecated 4.9.8 Use `auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}`
       
   349 				 *
       
   350 				 * @param bool     $allowed   Whether the user can add the object meta. Default false.
       
   351 				 * @param string   $meta_key  The meta key.
       
   352 				 * @param int      $object_id Object ID.
       
   353 				 * @param int      $user_id   User ID.
       
   354 				 * @param string   $cap       Capability name.
       
   355 				 * @param string[] $caps      Array of the user's capabilities.
       
   356 				 */
       
   357 				$allowed = apply_filters_deprecated( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ), '4.9.8', "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" );
       
   358 			}
       
   359 
       
   360 			if ( ! $allowed ) {
  1251 				$caps[] = $cap;
   361 				$caps[] = $cap;
  1252 		} elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) {
   362 			}
  1253 			$caps[] = $cap;
       
  1254 		}
   363 		}
  1255 		break;
   364 		break;
  1256 	case 'edit_comment':
   365 	case 'edit_comment':
  1257 		$comment = get_comment( $args[0] );
   366 		$comment = get_comment( $args[0] );
  1258 		if ( empty( $comment ) )
   367 		if ( ! $comment ) {
  1259 			break;
   368 			$caps[] = 'do_not_allow';
       
   369 			break;
       
   370 		}
       
   371 
  1260 		$post = get_post( $comment->comment_post_ID );
   372 		$post = get_post( $comment->comment_post_ID );
  1261 		$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
   373 
       
   374 		/*
       
   375 		 * If the post doesn't exist, we have an orphaned comment.
       
   376 		 * Fall back to the edit_posts capability, instead.
       
   377 		 */
       
   378 		if ( $post ) {
       
   379 			$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
       
   380 		} else {
       
   381 			$caps = map_meta_cap( 'edit_posts', $user_id );
       
   382 		}
  1262 		break;
   383 		break;
  1263 	case 'unfiltered_upload':
   384 	case 'unfiltered_upload':
  1264 		if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) )  )
   385 		if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) )  )
  1265 			$caps[] = $cap;
   386 			$caps[] = $cap;
  1266 		else
   387 		else
  1267 			$caps[] = 'do_not_allow';
   388 			$caps[] = 'do_not_allow';
  1268 		break;
   389 		break;
       
   390 	case 'edit_css' :
  1269 	case 'unfiltered_html' :
   391 	case 'unfiltered_html' :
  1270 		// Disallow unfiltered_html for all users, even admins and super admins.
   392 		// Disallow unfiltered_html for all users, even admins and super admins.
  1271 		if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML )
   393 		if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML )
  1272 			$caps[] = 'do_not_allow';
   394 			$caps[] = 'do_not_allow';
  1273 		elseif ( is_multisite() && ! is_super_admin( $user_id ) )
   395 		elseif ( is_multisite() && ! is_super_admin( $user_id ) )
  1274 			$caps[] = 'do_not_allow';
   396 			$caps[] = 'do_not_allow';
  1275 		else
   397 		else
  1276 			$caps[] = $cap;
   398 			$caps[] = 'unfiltered_html';
  1277 		break;
   399 		break;
  1278 	case 'edit_files':
   400 	case 'edit_files':
  1279 	case 'edit_plugins':
   401 	case 'edit_plugins':
  1280 	case 'edit_themes':
   402 	case 'edit_themes':
  1281 		// Disallow the file editors.
   403 		// Disallow the file editors.
  1282 		if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT )
   404 		if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT )
  1283 			$caps[] = 'do_not_allow';
   405 			$caps[] = 'do_not_allow';
  1284 		elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS )
   406 		elseif ( ! wp_is_file_mod_allowed( 'capability_edit_themes' ) )
  1285 			$caps[] = 'do_not_allow';
   407 			$caps[] = 'do_not_allow';
  1286 		elseif ( is_multisite() && ! is_super_admin( $user_id ) )
   408 		elseif ( is_multisite() && ! is_super_admin( $user_id ) )
  1287 			$caps[] = 'do_not_allow';
   409 			$caps[] = 'do_not_allow';
  1288 		else
   410 		else
  1289 			$caps[] = $cap;
   411 			$caps[] = $cap;
  1297 	case 'install_themes':
   419 	case 'install_themes':
  1298 	case 'upload_themes':
   420 	case 'upload_themes':
  1299 	case 'update_core':
   421 	case 'update_core':
  1300 		// Disallow anything that creates, deletes, or updates core, plugin, or theme files.
   422 		// Disallow anything that creates, deletes, or updates core, plugin, or theme files.
  1301 		// Files in uploads are excepted.
   423 		// Files in uploads are excepted.
  1302 		if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
   424 		if ( ! wp_is_file_mod_allowed( 'capability_update_core' ) ) {
  1303 			$caps[] = 'do_not_allow';
   425 			$caps[] = 'do_not_allow';
  1304 		} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
   426 		} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
  1305 			$caps[] = 'do_not_allow';
   427 			$caps[] = 'do_not_allow';
  1306 		} elseif ( 'upload_themes' === $cap ) {
   428 		} elseif ( 'upload_themes' === $cap ) {
  1307 			$caps[] = 'install_themes';
   429 			$caps[] = 'install_themes';
  1309 			$caps[] = 'install_plugins';
   431 			$caps[] = 'install_plugins';
  1310 		} else {
   432 		} else {
  1311 			$caps[] = $cap;
   433 			$caps[] = $cap;
  1312 		}
   434 		}
  1313 		break;
   435 		break;
       
   436 	case 'install_languages':
       
   437 	case 'update_languages':
       
   438 		if ( ! wp_is_file_mod_allowed( 'can_install_language_pack' ) ) {
       
   439 			$caps[] = 'do_not_allow';
       
   440 		} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
       
   441 			$caps[] = 'do_not_allow';
       
   442 		} else {
       
   443 			$caps[] = 'install_languages';
       
   444 		}
       
   445 		break;
  1314 	case 'activate_plugins':
   446 	case 'activate_plugins':
  1315 		$caps[] = $cap;
   447 	case 'deactivate_plugins':
       
   448 	case 'activate_plugin':
       
   449 	case 'deactivate_plugin':
       
   450 		$caps[] = 'activate_plugins';
  1316 		if ( is_multisite() ) {
   451 		if ( is_multisite() ) {
  1317 			// update_, install_, and delete_ are handled above with is_super_admin().
   452 			// update_, install_, and delete_ are handled above with is_super_admin().
  1318 			$menu_perms = get_site_option( 'menu_items', array() );
   453 			$menu_perms = get_site_option( 'menu_items', array() );
  1319 			if ( empty( $menu_perms['plugins'] ) )
   454 			if ( empty( $menu_perms['plugins'] ) )
  1320 				$caps[] = 'manage_network_plugins';
   455 				$caps[] = 'manage_network_plugins';
  1329 			$caps[] = 'delete_users'; // delete_user maps to delete_users.
   464 			$caps[] = 'delete_users'; // delete_user maps to delete_users.
  1330 		break;
   465 		break;
  1331 	case 'create_users':
   466 	case 'create_users':
  1332 		if ( !is_multisite() )
   467 		if ( !is_multisite() )
  1333 			$caps[] = $cap;
   468 			$caps[] = $cap;
  1334 		elseif ( is_super_admin() || get_site_option( 'add_new_users' ) )
   469 		elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) )
  1335 			$caps[] = $cap;
   470 			$caps[] = $cap;
  1336 		else
   471 		else
  1337 			$caps[] = 'do_not_allow';
   472 			$caps[] = 'do_not_allow';
  1338 		break;
   473 		break;
  1339 	case 'manage_links' :
   474 	case 'manage_links' :
  1344 		break;
   479 		break;
  1345 	case 'customize' :
   480 	case 'customize' :
  1346 		$caps[] = 'edit_theme_options';
   481 		$caps[] = 'edit_theme_options';
  1347 		break;
   482 		break;
  1348 	case 'delete_site':
   483 	case 'delete_site':
  1349 		$caps[] = 'manage_options';
   484 		if ( is_multisite() ) {
       
   485 			$caps[] = 'manage_options';
       
   486 		} else {
       
   487 			$caps[] = 'do_not_allow';
       
   488 		}
       
   489 		break;
       
   490 	case 'edit_term':
       
   491 	case 'delete_term':
       
   492 	case 'assign_term':
       
   493 		$term_id = (int) $args[0];
       
   494 		$term = get_term( $term_id );
       
   495 		if ( ! $term || is_wp_error( $term ) ) {
       
   496 			$caps[] = 'do_not_allow';
       
   497 			break;
       
   498 		}
       
   499 
       
   500 		$tax = get_taxonomy( $term->taxonomy );
       
   501 		if ( ! $tax ) {
       
   502 			$caps[] = 'do_not_allow';
       
   503 			break;
       
   504 		}
       
   505 
       
   506 		if ( 'delete_term' === $cap && ( $term->term_id == get_option( 'default_' . $term->taxonomy ) ) ) {
       
   507 			$caps[] = 'do_not_allow';
       
   508 			break;
       
   509 		}
       
   510 
       
   511 		$taxo_cap = $cap . 's';
       
   512 
       
   513 		$caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id );
       
   514 
       
   515 		break;
       
   516 	case 'manage_post_tags':
       
   517 	case 'edit_categories':
       
   518 	case 'edit_post_tags':
       
   519 	case 'delete_categories':
       
   520 	case 'delete_post_tags':
       
   521 		$caps[] = 'manage_categories';
       
   522 		break;
       
   523 	case 'assign_categories':
       
   524 	case 'assign_post_tags':
       
   525 		$caps[] = 'edit_posts';
       
   526 		break;
       
   527 	case 'create_sites':
       
   528 	case 'delete_sites':
       
   529 	case 'manage_network':
       
   530 	case 'manage_sites':
       
   531 	case 'manage_network_users':
       
   532 	case 'manage_network_plugins':
       
   533 	case 'manage_network_themes':
       
   534 	case 'manage_network_options':
       
   535 	case 'upgrade_network':
       
   536 		$caps[] = $cap;
       
   537 		break;
       
   538 	case 'setup_network':
       
   539 		if ( is_multisite() ) {
       
   540 			$caps[] = 'manage_network_options';
       
   541 		} else {
       
   542 			$caps[] = 'manage_options';
       
   543 		}
       
   544 		break;
       
   545 	case 'export_others_personal_data':
       
   546 	case 'erase_others_personal_data':
       
   547 	case 'manage_privacy_options':
       
   548 		$caps[] = is_multisite() ? 'manage_network' : 'manage_options';
  1350 		break;
   549 		break;
  1351 	default:
   550 	default:
  1352 		// Handle meta capabilities for custom post types.
   551 		// Handle meta capabilities for custom post types.
  1353 		$post_type_meta_caps = _post_type_meta_capabilities();
   552 		global $post_type_meta_caps;
  1354 		if ( isset( $post_type_meta_caps[ $cap ] ) ) {
   553 		if ( isset( $post_type_meta_caps[ $cap ] ) ) {
  1355 			$args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args );
   554 			$args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args );
  1356 			return call_user_func_array( 'map_meta_cap', $args );
   555 			return call_user_func_array( 'map_meta_cap', $args );
  1357 		}
   556 		}
  1358 
   557 
  1359 		// If no meta caps match, return the original cap.
   558 		// If no meta caps match, return the original cap.
  1360 		$caps[] = $cap;
   559 		$caps[] = $cap;
  1361 	}
   560 	}
  1362 
   561 
  1363 	/**
   562 	/**
  1364 	 * Filter a user's capabilities depending on specific context and/or privilege.
   563 	 * Filters a user's capabilities depending on specific context and/or privilege.
  1365 	 *
   564 	 *
  1366 	 * @since 2.8.0
   565 	 * @since 2.8.0
  1367 	 *
   566 	 *
  1368 	 * @param array  $caps    Returns the user's actual capabilities.
   567 	 * @param array  $caps    Returns the user's actual capabilities.
  1369 	 * @param string $cap     Capability name.
   568 	 * @param string $cap     Capability name.
  1372 	 */
   571 	 */
  1373 	return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
   572 	return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
  1374 }
   573 }
  1375 
   574 
  1376 /**
   575 /**
  1377  * Whether current user has capability or role.
   576  * Whether the current user has a specific capability.
       
   577  *
       
   578  * While checking against particular roles in place of a capability is supported
       
   579  * in part, this practice is discouraged as it may produce unreliable results.
       
   580  *
       
   581  * Note: Will always return true if the current user is a super admin, unless specifically denied.
  1378  *
   582  *
  1379  * @since 2.0.0
   583  * @since 2.0.0
  1380  *
   584  *
  1381  * @param string $capability Capability or role name.
   585  * @see WP_User::has_cap()
  1382  * @return bool
   586  * @see map_meta_cap()
       
   587  *
       
   588  * @param string $capability Capability name.
       
   589  * @param int    $object_id  Optional. ID of the specific object to check against if `$capability` is a "meta" cap.
       
   590  *                           "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used
       
   591  *                           by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts',
       
   592  *                           'edit_others_posts', etc. Accessed via func_get_args() and passed to WP_User::has_cap(),
       
   593  *                           then map_meta_cap().
       
   594  * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is
       
   595  *              passed, whether the current user has the given meta capability for the given object.
  1383  */
   596  */
  1384 function current_user_can( $capability ) {
   597 function current_user_can( $capability ) {
  1385 	$current_user = wp_get_current_user();
   598 	$current_user = wp_get_current_user();
  1386 
   599 
  1387 	if ( empty( $current_user ) )
   600 	if ( empty( $current_user ) )
  1392 
   605 
  1393 	return call_user_func_array( array( $current_user, 'has_cap' ), $args );
   606 	return call_user_func_array( array( $current_user, 'has_cap' ), $args );
  1394 }
   607 }
  1395 
   608 
  1396 /**
   609 /**
  1397  * Whether current user has a capability or role for a given blog.
   610  * Whether the current user has a specific capability for a given site.
  1398  *
   611  *
  1399  * @since 3.0.0
   612  * @since 3.0.0
  1400  *
   613  *
  1401  * @param int $blog_id Blog ID
   614  * @param int    $blog_id    Site ID.
  1402  * @param string $capability Capability or role name.
   615  * @param string $capability Capability name.
  1403  * @return bool
   616  * @return bool Whether the user has the given capability.
  1404  */
   617  */
  1405 function current_user_can_for_blog( $blog_id, $capability ) {
   618 function current_user_can_for_blog( $blog_id, $capability ) {
  1406 	$switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
   619 	$switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
  1407 
   620 
  1408 	$current_user = wp_get_current_user();
   621 	$current_user = wp_get_current_user();
  1425 
   638 
  1426 	return $can;
   639 	return $can;
  1427 }
   640 }
  1428 
   641 
  1429 /**
   642 /**
  1430  * Whether author of supplied post has capability or role.
   643  * Whether the author of the supplied post has a specific capability.
  1431  *
   644  *
  1432  * @since 2.9.0
   645  * @since 2.9.0
  1433  *
   646  *
  1434  * @param int|object $post Post ID or post object.
   647  * @param int|WP_Post $post       Post ID or post object.
  1435  * @param string $capability Capability or role name.
   648  * @param string      $capability Capability name.
  1436  * @return bool
   649  * @return bool Whether the post author has the given capability.
  1437  */
   650  */
  1438 function author_can( $post, $capability ) {
   651 function author_can( $post, $capability ) {
  1439 	if ( !$post = get_post($post) )
   652 	if ( !$post = get_post($post) )
  1440 		return false;
   653 		return false;
  1441 
   654 
  1449 
   662 
  1450 	return call_user_func_array( array( $author, 'has_cap' ), $args );
   663 	return call_user_func_array( array( $author, 'has_cap' ), $args );
  1451 }
   664 }
  1452 
   665 
  1453 /**
   666 /**
  1454  * Whether a particular user has capability or role.
   667  * Whether a particular user has a specific capability.
  1455  *
   668  *
  1456  * @since 3.1.0
   669  * @since 3.1.0
  1457  *
   670  *
  1458  * @param int|object $user User ID or object.
   671  * @param int|WP_User $user       User ID or object.
  1459  * @param string $capability Capability or role name.
   672  * @param string      $capability Capability name.
  1460  * @return bool
   673  * @return bool Whether the user has the given capability.
  1461  */
   674  */
  1462 function user_can( $user, $capability ) {
   675 function user_can( $user, $capability ) {
  1463 	if ( ! is_object( $user ) )
   676 	if ( ! is_object( $user ) )
  1464 		$user = get_userdata( $user );
   677 		$user = get_userdata( $user );
  1465 
   678 
  1471 
   684 
  1472 	return call_user_func_array( array( $user, 'has_cap' ), $args );
   685 	return call_user_func_array( array( $user, 'has_cap' ), $args );
  1473 }
   686 }
  1474 
   687 
  1475 /**
   688 /**
       
   689  * Retrieves the global WP_Roles instance and instantiates it if necessary.
       
   690  *
       
   691  * @since 4.3.0
       
   692  *
       
   693  * @global WP_Roles $wp_roles WP_Roles global instance.
       
   694  *
       
   695  * @return WP_Roles WP_Roles global instance if not already instantiated.
       
   696  */
       
   697 function wp_roles() {
       
   698 	global $wp_roles;
       
   699 
       
   700 	if ( ! isset( $wp_roles ) ) {
       
   701 		$wp_roles = new WP_Roles();
       
   702 	}
       
   703 	return $wp_roles;
       
   704 }
       
   705 
       
   706 /**
  1476  * Retrieve role object.
   707  * Retrieve role object.
  1477  *
   708  *
  1478  * @see WP_Roles::get_role() Uses method to retrieve role object.
       
  1479  * @since 2.0.0
   709  * @since 2.0.0
  1480  *
   710  *
  1481  * @param string $role Role name.
   711  * @param string $role Role name.
  1482  * @return WP_Role|null WP_Role object if found, null if the role does not exist.
   712  * @return WP_Role|null WP_Role object if found, null if the role does not exist.
  1483  */
   713  */
  1484 function get_role( $role ) {
   714 function get_role( $role ) {
  1485 	global $wp_roles;
   715 	return wp_roles()->get_role( $role );
  1486 
       
  1487 	if ( ! isset( $wp_roles ) )
       
  1488 		$wp_roles = new WP_Roles();
       
  1489 
       
  1490 	return $wp_roles->get_role( $role );
       
  1491 }
   716 }
  1492 
   717 
  1493 /**
   718 /**
  1494  * Add role, if it does not exist.
   719  * Add role, if it does not exist.
  1495  *
   720  *
  1496  * @see WP_Roles::add_role() Uses method to add role.
       
  1497  * @since 2.0.0
   721  * @since 2.0.0
  1498  *
   722  *
  1499  * @param string $role Role name.
   723  * @param string $role Role name.
  1500  * @param string $display_name Display name for role.
   724  * @param string $display_name Display name for role.
  1501  * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false );
   725  * @param array $capabilities List of capabilities, e.g. array( 'edit_posts' => true, 'delete_posts' => false );
  1502  * @return WP_Role|null WP_Role object if role is added, null if already exists.
   726  * @return WP_Role|null WP_Role object if role is added, null if already exists.
  1503  */
   727  */
  1504 function add_role( $role, $display_name, $capabilities = array() ) {
   728 function add_role( $role, $display_name, $capabilities = array() ) {
  1505 	global $wp_roles;
   729 	if ( empty( $role ) ) {
  1506 
   730 		return;
  1507 	if ( ! isset( $wp_roles ) )
   731 	}
  1508 		$wp_roles = new WP_Roles();
   732 	return wp_roles()->add_role( $role, $display_name, $capabilities );
  1509 
       
  1510 	return $wp_roles->add_role( $role, $display_name, $capabilities );
       
  1511 }
   733 }
  1512 
   734 
  1513 /**
   735 /**
  1514  * Remove role, if it exists.
   736  * Remove role, if it exists.
  1515  *
   737  *
  1516  * @see WP_Roles::remove_role() Uses method to remove role.
       
  1517  * @since 2.0.0
   738  * @since 2.0.0
  1518  *
   739  *
  1519  * @param string $role Role name.
   740  * @param string $role Role name.
  1520  */
   741  */
  1521 function remove_role( $role ) {
   742 function remove_role( $role ) {
  1522 	global $wp_roles;
   743 	wp_roles()->remove_role( $role );
  1523 
       
  1524 	if ( ! isset( $wp_roles ) )
       
  1525 		$wp_roles = new WP_Roles();
       
  1526 
       
  1527 	$wp_roles->remove_role( $role );
       
  1528 }
   744 }
  1529 
   745 
  1530 /**
   746 /**
  1531  * Retrieve a list of super admins.
   747  * Retrieve a list of super admins.
  1532  *
   748  *
  1533  * @since 3.0.0
   749  * @since 3.0.0
  1534  *
   750  *
  1535  * @uses $super_admins Super admins global variable, if set.
   751  * @global array $super_admins
  1536  *
   752  *
  1537  * @return array List of super admin logins
   753  * @return array List of super admin logins
  1538  */
   754  */
  1539 function get_super_admins() {
   755 function get_super_admins() {
  1540 	global $super_admins;
   756 	global $super_admins;
  1571 			return true;
   787 			return true;
  1572 	}
   788 	}
  1573 
   789 
  1574 	return false;
   790 	return false;
  1575 }
   791 }
       
   792 
       
   793 /**
       
   794  * Grants Super Admin privileges.
       
   795  *
       
   796  * @since 3.0.0
       
   797  *
       
   798  * @global array $super_admins
       
   799  *
       
   800  * @param int $user_id ID of the user to be granted Super Admin privileges.
       
   801  * @return bool True on success, false on failure. This can fail when the user is
       
   802  *              already a super admin or when the `$super_admins` global is defined.
       
   803  */
       
   804 function grant_super_admin( $user_id ) {
       
   805 	// If global super_admins override is defined, there is nothing to do here.
       
   806 	if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
       
   807 		return false;
       
   808 	}
       
   809 
       
   810 	/**
       
   811 	 * Fires before the user is granted Super Admin privileges.
       
   812 	 *
       
   813 	 * @since 3.0.0
       
   814 	 *
       
   815 	 * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
       
   816 	 */
       
   817 	do_action( 'grant_super_admin', $user_id );
       
   818 
       
   819 	// Directly fetch site_admins instead of using get_super_admins()
       
   820 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
       
   821 
       
   822 	$user = get_userdata( $user_id );
       
   823 	if ( $user && ! in_array( $user->user_login, $super_admins ) ) {
       
   824 		$super_admins[] = $user->user_login;
       
   825 		update_site_option( 'site_admins' , $super_admins );
       
   826 
       
   827 		/**
       
   828 		 * Fires after the user is granted Super Admin privileges.
       
   829 		 *
       
   830 		 * @since 3.0.0
       
   831 		 *
       
   832 		 * @param int $user_id ID of the user that was granted Super Admin privileges.
       
   833 		 */
       
   834 		do_action( 'granted_super_admin', $user_id );
       
   835 		return true;
       
   836 	}
       
   837 	return false;
       
   838 }
       
   839 
       
   840 /**
       
   841  * Revokes Super Admin privileges.
       
   842  *
       
   843  * @since 3.0.0
       
   844  *
       
   845  * @global array $super_admins
       
   846  *
       
   847  * @param int $user_id ID of the user Super Admin privileges to be revoked from.
       
   848  * @return bool True on success, false on failure. This can fail when the user's email
       
   849  *              is the network admin email or when the `$super_admins` global is defined.
       
   850  */
       
   851 function revoke_super_admin( $user_id ) {
       
   852 	// If global super_admins override is defined, there is nothing to do here.
       
   853 	if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
       
   854 		return false;
       
   855 	}
       
   856 
       
   857 	/**
       
   858 	 * Fires before the user's Super Admin privileges are revoked.
       
   859 	 *
       
   860 	 * @since 3.0.0
       
   861 	 *
       
   862 	 * @param int $user_id ID of the user Super Admin privileges are being revoked from.
       
   863 	 */
       
   864 	do_action( 'revoke_super_admin', $user_id );
       
   865 
       
   866 	// Directly fetch site_admins instead of using get_super_admins()
       
   867 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
       
   868 
       
   869 	$user = get_userdata( $user_id );
       
   870 	if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) {
       
   871 		if ( false !== ( $key = array_search( $user->user_login, $super_admins ) ) ) {
       
   872 			unset( $super_admins[$key] );
       
   873 			update_site_option( 'site_admins', $super_admins );
       
   874 
       
   875 			/**
       
   876 			 * Fires after the user's Super Admin privileges are revoked.
       
   877 			 *
       
   878 			 * @since 3.0.0
       
   879 			 *
       
   880 			 * @param int $user_id ID of the user Super Admin privileges were revoked from.
       
   881 			 */
       
   882 			do_action( 'revoked_super_admin', $user_id );
       
   883 			return true;
       
   884 		}
       
   885 	}
       
   886 	return false;
       
   887 }
       
   888 
       
   889 /**
       
   890  * Filters the user capabilities to grant the 'install_languages' capability as necessary.
       
   891  *
       
   892  * A user must have at least one out of the 'update_core', 'install_plugins', and
       
   893  * 'install_themes' capabilities to qualify for 'install_languages'.
       
   894  *
       
   895  * @since 4.9.0
       
   896  *
       
   897  * @param array $allcaps An array of all the user's capabilities.
       
   898  * @return array Filtered array of the user's capabilities.
       
   899  */
       
   900 function wp_maybe_grant_install_languages_cap( $allcaps ) {
       
   901 	if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) {
       
   902 		$allcaps['install_languages'] = true;
       
   903 	}
       
   904 
       
   905 	return $allcaps;
       
   906 }