angelovcom.net

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

capabilities.php (35758B)


      1 <?php
      2 /**
      3  * Core User Role & Capabilities API
      4  *
      5  * @package WordPress
      6  * @subpackage Users
      7  */
      8 
      9 /**
     10  * Maps a capability to the primitive capabilities required of the given user to
     11  * satisfy the capability being checked.
     12  *
     13  * This function also accepts an ID of an object to map against if the capability is a meta capability. Meta
     14  * capabilities such as `edit_post` and `edit_user` are capabilities used by this function to map to primitive
     15  * capabilities that a user or role requires, such as `edit_posts` and `edit_others_posts`.
     16  *
     17  * Example usage:
     18  *
     19  *     map_meta_cap( 'edit_posts', $user->ID );
     20  *     map_meta_cap( 'edit_post', $user->ID, $post->ID );
     21  *     map_meta_cap( 'edit_post_meta', $user->ID, $post->ID, $meta_key );
     22  *
     23  * This function does not check whether the user has the required capabilities,
     24  * it just returns what the required capabilities are.
     25  *
     26  * @since 2.0.0
     27  * @since 4.9.6 Added the `export_others_personal_data`, `erase_others_personal_data`,
     28  *              and `manage_privacy_options` capabilities.
     29  * @since 5.1.0 Added the `update_php` capability.
     30  * @since 5.2.0 Added the `resume_plugin` and `resume_theme` capabilities.
     31  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
     32  *              by adding it to the function signature.
     33  * @since 5.7.0 Added the `create_app_password`, `list_app_passwords`, `read_app_password`,
     34  *              `edit_app_password`, `delete_app_passwords`, `delete_app_password`,
     35  *              and `update_https` capabilities.
     36  *
     37  * @global array $post_type_meta_caps Used to get post type meta capabilities.
     38  *
     39  * @param string $cap     Capability being checked.
     40  * @param int    $user_id User ID.
     41  * @param mixed  ...$args Optional further parameters, typically starting with an object ID.
     42  * @return string[] Primitive capabilities required of the user.
     43  */
     44 function map_meta_cap( $cap, $user_id, ...$args ) {
     45 	$caps = array();
     46 
     47 	switch ( $cap ) {
     48 		case 'remove_user':
     49 			// In multisite the user must be a super admin to remove themselves.
     50 			if ( isset( $args[0] ) && $user_id == $args[0] && ! is_super_admin( $user_id ) ) {
     51 				$caps[] = 'do_not_allow';
     52 			} else {
     53 				$caps[] = 'remove_users';
     54 			}
     55 			break;
     56 		case 'promote_user':
     57 		case 'add_users':
     58 			$caps[] = 'promote_users';
     59 			break;
     60 		case 'edit_user':
     61 		case 'edit_users':
     62 			// Allow user to edit themselves.
     63 			if ( 'edit_user' === $cap && isset( $args[0] ) && $user_id == $args[0] ) {
     64 				break;
     65 			}
     66 
     67 			// In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
     68 			if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
     69 				$caps[] = 'do_not_allow';
     70 			} else {
     71 				$caps[] = 'edit_users'; // edit_user maps to edit_users.
     72 			}
     73 			break;
     74 		case 'delete_post':
     75 		case 'delete_page':
     76 			$post = get_post( $args[0] );
     77 			if ( ! $post ) {
     78 				$caps[] = 'do_not_allow';
     79 				break;
     80 			}
     81 
     82 			if ( 'revision' === $post->post_type ) {
     83 				$caps[] = 'do_not_allow';
     84 				break;
     85 			}
     86 
     87 			if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) {
     88 				$caps[] = 'manage_options';
     89 				break;
     90 			}
     91 
     92 			$post_type = get_post_type_object( $post->post_type );
     93 			if ( ! $post_type ) {
     94 				/* translators: 1: Post type, 2: Capability name. */
     95 				_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' );
     96 				$caps[] = 'edit_others_posts';
     97 				break;
     98 			}
     99 
    100 			if ( ! $post_type->map_meta_cap ) {
    101 				$caps[] = $post_type->cap->$cap;
    102 				// Prior to 3.1 we would re-call map_meta_cap here.
    103 				if ( 'delete_post' === $cap ) {
    104 					$cap = $post_type->cap->$cap;
    105 				}
    106 				break;
    107 			}
    108 
    109 			// If the post author is set and the user is the author...
    110 			if ( $post->post_author && $user_id == $post->post_author ) {
    111 				// If the post is published or scheduled...
    112 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
    113 					$caps[] = $post_type->cap->delete_published_posts;
    114 				} elseif ( 'trash' === $post->post_status ) {
    115 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
    116 					if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
    117 						$caps[] = $post_type->cap->delete_published_posts;
    118 					} else {
    119 						$caps[] = $post_type->cap->delete_posts;
    120 					}
    121 				} else {
    122 					// If the post is draft...
    123 					$caps[] = $post_type->cap->delete_posts;
    124 				}
    125 			} else {
    126 				// The user is trying to edit someone else's post.
    127 				$caps[] = $post_type->cap->delete_others_posts;
    128 				// The post is published or scheduled, extra cap required.
    129 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
    130 					$caps[] = $post_type->cap->delete_published_posts;
    131 				} elseif ( 'private' === $post->post_status ) {
    132 					$caps[] = $post_type->cap->delete_private_posts;
    133 				}
    134 			}
    135 
    136 			/*
    137 			 * Setting the privacy policy page requires `manage_privacy_options`,
    138 			 * so deleting it should require that too.
    139 			 */
    140 			if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
    141 				$caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
    142 			}
    143 
    144 			break;
    145 		// edit_post breaks down to edit_posts, edit_published_posts, or
    146 		// edit_others_posts.
    147 		case 'edit_post':
    148 		case 'edit_page':
    149 			$post = get_post( $args[0] );
    150 			if ( ! $post ) {
    151 				$caps[] = 'do_not_allow';
    152 				break;
    153 			}
    154 
    155 			if ( 'revision' === $post->post_type ) {
    156 				$post = get_post( $post->post_parent );
    157 				if ( ! $post ) {
    158 					$caps[] = 'do_not_allow';
    159 					break;
    160 				}
    161 			}
    162 
    163 			$post_type = get_post_type_object( $post->post_type );
    164 			if ( ! $post_type ) {
    165 				/* translators: 1: Post type, 2: Capability name. */
    166 				_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' );
    167 				$caps[] = 'edit_others_posts';
    168 				break;
    169 			}
    170 
    171 			if ( ! $post_type->map_meta_cap ) {
    172 				$caps[] = $post_type->cap->$cap;
    173 				// Prior to 3.1 we would re-call map_meta_cap here.
    174 				if ( 'edit_post' === $cap ) {
    175 					$cap = $post_type->cap->$cap;
    176 				}
    177 				break;
    178 			}
    179 
    180 			// If the post author is set and the user is the author...
    181 			if ( $post->post_author && $user_id == $post->post_author ) {
    182 				// If the post is published or scheduled...
    183 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
    184 					$caps[] = $post_type->cap->edit_published_posts;
    185 				} elseif ( 'trash' === $post->post_status ) {
    186 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
    187 					if ( in_array( $status, array( 'publish', 'future' ), true ) ) {
    188 						$caps[] = $post_type->cap->edit_published_posts;
    189 					} else {
    190 						$caps[] = $post_type->cap->edit_posts;
    191 					}
    192 				} else {
    193 					// If the post is draft...
    194 					$caps[] = $post_type->cap->edit_posts;
    195 				}
    196 			} else {
    197 				// The user is trying to edit someone else's post.
    198 				$caps[] = $post_type->cap->edit_others_posts;
    199 				// The post is published or scheduled, extra cap required.
    200 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
    201 					$caps[] = $post_type->cap->edit_published_posts;
    202 				} elseif ( 'private' === $post->post_status ) {
    203 					$caps[] = $post_type->cap->edit_private_posts;
    204 				}
    205 			}
    206 
    207 			/*
    208 			 * Setting the privacy policy page requires `manage_privacy_options`,
    209 			 * so editing it should require that too.
    210 			 */
    211 			if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
    212 				$caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
    213 			}
    214 
    215 			break;
    216 		case 'read_post':
    217 		case 'read_page':
    218 			$post = get_post( $args[0] );
    219 			if ( ! $post ) {
    220 				$caps[] = 'do_not_allow';
    221 				break;
    222 			}
    223 
    224 			if ( 'revision' === $post->post_type ) {
    225 				$post = get_post( $post->post_parent );
    226 				if ( ! $post ) {
    227 					$caps[] = 'do_not_allow';
    228 					break;
    229 				}
    230 			}
    231 
    232 			$post_type = get_post_type_object( $post->post_type );
    233 			if ( ! $post_type ) {
    234 				/* translators: 1: Post type, 2: Capability name. */
    235 				_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' );
    236 				$caps[] = 'edit_others_posts';
    237 				break;
    238 			}
    239 
    240 			if ( ! $post_type->map_meta_cap ) {
    241 				$caps[] = $post_type->cap->$cap;
    242 				// Prior to 3.1 we would re-call map_meta_cap here.
    243 				if ( 'read_post' === $cap ) {
    244 					$cap = $post_type->cap->$cap;
    245 				}
    246 				break;
    247 			}
    248 
    249 			$status_obj = get_post_status_object( get_post_status( $post ) );
    250 			if ( ! $status_obj ) {
    251 				/* translators: 1: Post status, 2: Capability name. */
    252 				_doing_it_wrong( __FUNCTION__, sprintf( __( 'The post status %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post with that status.' ), get_post_status( $post ), $cap ), '5.4.0' );
    253 				$caps[] = 'edit_others_posts';
    254 				break;
    255 			}
    256 
    257 			if ( $status_obj->public ) {
    258 				$caps[] = $post_type->cap->read;
    259 				break;
    260 			}
    261 
    262 			if ( $post->post_author && $user_id == $post->post_author ) {
    263 				$caps[] = $post_type->cap->read;
    264 			} elseif ( $status_obj->private ) {
    265 				$caps[] = $post_type->cap->read_private_posts;
    266 			} else {
    267 				$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
    268 			}
    269 			break;
    270 		case 'publish_post':
    271 			$post = get_post( $args[0] );
    272 			if ( ! $post ) {
    273 				$caps[] = 'do_not_allow';
    274 				break;
    275 			}
    276 
    277 			$post_type = get_post_type_object( $post->post_type );
    278 			if ( ! $post_type ) {
    279 				/* translators: 1: Post type, 2: Capability name. */
    280 				_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' );
    281 				$caps[] = 'edit_others_posts';
    282 				break;
    283 			}
    284 
    285 			$caps[] = $post_type->cap->publish_posts;
    286 			break;
    287 		case 'edit_post_meta':
    288 		case 'delete_post_meta':
    289 		case 'add_post_meta':
    290 		case 'edit_comment_meta':
    291 		case 'delete_comment_meta':
    292 		case 'add_comment_meta':
    293 		case 'edit_term_meta':
    294 		case 'delete_term_meta':
    295 		case 'add_term_meta':
    296 		case 'edit_user_meta':
    297 		case 'delete_user_meta':
    298 		case 'add_user_meta':
    299 			$object_type = explode( '_', $cap )[1];
    300 			$object_id   = (int) $args[0];
    301 
    302 			$object_subtype = get_object_subtype( $object_type, $object_id );
    303 
    304 			if ( empty( $object_subtype ) ) {
    305 				$caps[] = 'do_not_allow';
    306 				break;
    307 			}
    308 
    309 			$caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id );
    310 
    311 			$meta_key = isset( $args[1] ) ? $args[1] : false;
    312 
    313 			if ( $meta_key ) {
    314 				$allowed = ! is_protected_meta( $meta_key, $object_type );
    315 
    316 				if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
    317 
    318 					/**
    319 					 * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
    320 					 *
    321 					 * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
    322 					 * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
    323 					 * the meta key value, and the object subtype respectively.
    324 					 *
    325 					 * @since 4.9.8
    326 					 *
    327 					 * @param bool     $allowed   Whether the user can add the object meta. Default false.
    328 					 * @param string   $meta_key  The meta key.
    329 					 * @param int      $object_id Object ID.
    330 					 * @param int      $user_id   User ID.
    331 					 * @param string   $cap       Capability name.
    332 					 * @param string[] $caps      Array of the user's capabilities.
    333 					 */
    334 					$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
    335 				} else {
    336 
    337 					/**
    338 					 * Filters whether the user is allowed to edit a specific meta key of a specific object type.
    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, `$meta_key`, refers to the meta key passed to map_meta_cap().
    344 					 *
    345 					 * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
    346 					 * @since 4.6.0
    347 					 *
    348 					 * @param bool     $allowed   Whether the user can add the object meta. Default false.
    349 					 * @param string   $meta_key  The meta key.
    350 					 * @param int      $object_id Object ID.
    351 					 * @param int      $user_id   User ID.
    352 					 * @param string   $cap       Capability name.
    353 					 * @param string[] $caps      Array of the user's capabilities.
    354 					 */
    355 					$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
    356 				}
    357 
    358 				if ( ! empty( $object_subtype ) ) {
    359 
    360 					/**
    361 					 * Filters whether the user is allowed to edit meta for specific object types/subtypes.
    362 					 *
    363 					 * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
    364 					 *
    365 					 * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
    366 					 * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
    367 					 * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
    368 					 *
    369 					 * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
    370 					 * @since 4.7.0 Renamed from `auth_post_{$post_type}_meta_{$meta_key}` to
    371 					 *              `auth_{$object_type}_{$object_subtype}_meta_{$meta_key}`.
    372 					 * @deprecated 4.9.8 Use {@see 'auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}'} instead.
    373 					 *
    374 					 * @param bool     $allowed   Whether the user can add the object meta. Default false.
    375 					 * @param string   $meta_key  The meta key.
    376 					 * @param int      $object_id Object ID.
    377 					 * @param int      $user_id   User ID.
    378 					 * @param string   $cap       Capability name.
    379 					 * @param string[] $caps      Array of the user's capabilities.
    380 					 */
    381 					$allowed = apply_filters_deprecated(
    382 						"auth_{$object_type}_{$object_subtype}_meta_{$meta_key}",
    383 						array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ),
    384 						'4.9.8',
    385 						"auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}"
    386 					);
    387 				}
    388 
    389 				if ( ! $allowed ) {
    390 					$caps[] = $cap;
    391 				}
    392 			}
    393 			break;
    394 		case 'edit_comment':
    395 			$comment = get_comment( $args[0] );
    396 			if ( ! $comment ) {
    397 				$caps[] = 'do_not_allow';
    398 				break;
    399 			}
    400 
    401 			$post = get_post( $comment->comment_post_ID );
    402 
    403 			/*
    404 			 * If the post doesn't exist, we have an orphaned comment.
    405 			 * Fall back to the edit_posts capability, instead.
    406 			 */
    407 			if ( $post ) {
    408 				$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
    409 			} else {
    410 				$caps = map_meta_cap( 'edit_posts', $user_id );
    411 			}
    412 			break;
    413 		case 'unfiltered_upload':
    414 			if ( defined( 'ALLOW_UNFILTERED_UPLOADS' ) && ALLOW_UNFILTERED_UPLOADS && ( ! is_multisite() || is_super_admin( $user_id ) ) ) {
    415 				$caps[] = $cap;
    416 			} else {
    417 				$caps[] = 'do_not_allow';
    418 			}
    419 			break;
    420 		case 'edit_css':
    421 		case 'unfiltered_html':
    422 			// Disallow unfiltered_html for all users, even admins and super admins.
    423 			if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
    424 				$caps[] = 'do_not_allow';
    425 			} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
    426 				$caps[] = 'do_not_allow';
    427 			} else {
    428 				$caps[] = 'unfiltered_html';
    429 			}
    430 			break;
    431 		case 'edit_files':
    432 		case 'edit_plugins':
    433 		case 'edit_themes':
    434 			// Disallow the file editors.
    435 			if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) {
    436 				$caps[] = 'do_not_allow';
    437 			} elseif ( ! wp_is_file_mod_allowed( 'capability_edit_themes' ) ) {
    438 				$caps[] = 'do_not_allow';
    439 			} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
    440 				$caps[] = 'do_not_allow';
    441 			} else {
    442 				$caps[] = $cap;
    443 			}
    444 			break;
    445 		case 'update_plugins':
    446 		case 'delete_plugins':
    447 		case 'install_plugins':
    448 		case 'upload_plugins':
    449 		case 'update_themes':
    450 		case 'delete_themes':
    451 		case 'install_themes':
    452 		case 'upload_themes':
    453 		case 'update_core':
    454 			// Disallow anything that creates, deletes, or updates core, plugin, or theme files.
    455 			// Files in uploads are excepted.
    456 			if ( ! wp_is_file_mod_allowed( 'capability_update_core' ) ) {
    457 				$caps[] = 'do_not_allow';
    458 			} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
    459 				$caps[] = 'do_not_allow';
    460 			} elseif ( 'upload_themes' === $cap ) {
    461 				$caps[] = 'install_themes';
    462 			} elseif ( 'upload_plugins' === $cap ) {
    463 				$caps[] = 'install_plugins';
    464 			} else {
    465 				$caps[] = $cap;
    466 			}
    467 			break;
    468 		case 'install_languages':
    469 		case 'update_languages':
    470 			if ( ! wp_is_file_mod_allowed( 'can_install_language_pack' ) ) {
    471 				$caps[] = 'do_not_allow';
    472 			} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
    473 				$caps[] = 'do_not_allow';
    474 			} else {
    475 				$caps[] = 'install_languages';
    476 			}
    477 			break;
    478 		case 'activate_plugins':
    479 		case 'deactivate_plugins':
    480 		case 'activate_plugin':
    481 		case 'deactivate_plugin':
    482 			$caps[] = 'activate_plugins';
    483 			if ( is_multisite() ) {
    484 				// update_, install_, and delete_ are handled above with is_super_admin().
    485 				$menu_perms = get_site_option( 'menu_items', array() );
    486 				if ( empty( $menu_perms['plugins'] ) ) {
    487 					$caps[] = 'manage_network_plugins';
    488 				}
    489 			}
    490 			break;
    491 		case 'resume_plugin':
    492 			$caps[] = 'resume_plugins';
    493 			break;
    494 		case 'resume_theme':
    495 			$caps[] = 'resume_themes';
    496 			break;
    497 		case 'delete_user':
    498 		case 'delete_users':
    499 			// If multisite only super admins can delete users.
    500 			if ( is_multisite() && ! is_super_admin( $user_id ) ) {
    501 				$caps[] = 'do_not_allow';
    502 			} else {
    503 				$caps[] = 'delete_users'; // delete_user maps to delete_users.
    504 			}
    505 			break;
    506 		case 'create_users':
    507 			if ( ! is_multisite() ) {
    508 				$caps[] = $cap;
    509 			} elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) ) {
    510 				$caps[] = $cap;
    511 			} else {
    512 				$caps[] = 'do_not_allow';
    513 			}
    514 			break;
    515 		case 'manage_links':
    516 			if ( get_option( 'link_manager_enabled' ) ) {
    517 				$caps[] = $cap;
    518 			} else {
    519 				$caps[] = 'do_not_allow';
    520 			}
    521 			break;
    522 		case 'customize':
    523 			$caps[] = 'edit_theme_options';
    524 			break;
    525 		case 'delete_site':
    526 			if ( is_multisite() ) {
    527 				$caps[] = 'manage_options';
    528 			} else {
    529 				$caps[] = 'do_not_allow';
    530 			}
    531 			break;
    532 		case 'edit_term':
    533 		case 'delete_term':
    534 		case 'assign_term':
    535 			$term_id = (int) $args[0];
    536 			$term    = get_term( $term_id );
    537 			if ( ! $term || is_wp_error( $term ) ) {
    538 				$caps[] = 'do_not_allow';
    539 				break;
    540 			}
    541 
    542 			$tax = get_taxonomy( $term->taxonomy );
    543 			if ( ! $tax ) {
    544 				$caps[] = 'do_not_allow';
    545 				break;
    546 			}
    547 
    548 			if ( 'delete_term' === $cap
    549 				&& ( get_option( 'default_' . $term->taxonomy ) == $term->term_id
    550 					|| get_option( 'default_term_' . $term->taxonomy ) == $term->term_id )
    551 			) {
    552 				$caps[] = 'do_not_allow';
    553 				break;
    554 			}
    555 
    556 			$taxo_cap = $cap . 's';
    557 
    558 			$caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id );
    559 
    560 			break;
    561 		case 'manage_post_tags':
    562 		case 'edit_categories':
    563 		case 'edit_post_tags':
    564 		case 'delete_categories':
    565 		case 'delete_post_tags':
    566 			$caps[] = 'manage_categories';
    567 			break;
    568 		case 'assign_categories':
    569 		case 'assign_post_tags':
    570 			$caps[] = 'edit_posts';
    571 			break;
    572 		case 'create_sites':
    573 		case 'delete_sites':
    574 		case 'manage_network':
    575 		case 'manage_sites':
    576 		case 'manage_network_users':
    577 		case 'manage_network_plugins':
    578 		case 'manage_network_themes':
    579 		case 'manage_network_options':
    580 		case 'upgrade_network':
    581 			$caps[] = $cap;
    582 			break;
    583 		case 'setup_network':
    584 			if ( is_multisite() ) {
    585 				$caps[] = 'manage_network_options';
    586 			} else {
    587 				$caps[] = 'manage_options';
    588 			}
    589 			break;
    590 		case 'update_php':
    591 			if ( is_multisite() && ! is_super_admin( $user_id ) ) {
    592 				$caps[] = 'do_not_allow';
    593 			} else {
    594 				$caps[] = 'update_core';
    595 			}
    596 			break;
    597 		case 'update_https':
    598 			if ( is_multisite() && ! is_super_admin( $user_id ) ) {
    599 				$caps[] = 'do_not_allow';
    600 			} else {
    601 				$caps[] = 'manage_options';
    602 				$caps[] = 'update_core';
    603 			}
    604 			break;
    605 		case 'export_others_personal_data':
    606 		case 'erase_others_personal_data':
    607 		case 'manage_privacy_options':
    608 			$caps[] = is_multisite() ? 'manage_network' : 'manage_options';
    609 			break;
    610 		case 'create_app_password':
    611 		case 'list_app_passwords':
    612 		case 'read_app_password':
    613 		case 'edit_app_password':
    614 		case 'delete_app_passwords':
    615 		case 'delete_app_password':
    616 			$caps = map_meta_cap( 'edit_user', $user_id, $args[0] );
    617 			break;
    618 		default:
    619 			// Handle meta capabilities for custom post types.
    620 			global $post_type_meta_caps;
    621 			if ( isset( $post_type_meta_caps[ $cap ] ) ) {
    622 				return map_meta_cap( $post_type_meta_caps[ $cap ], $user_id, ...$args );
    623 			}
    624 
    625 			// Block capabilities map to their post equivalent.
    626 			$block_caps = array(
    627 				'edit_blocks',
    628 				'edit_others_blocks',
    629 				'publish_blocks',
    630 				'read_private_blocks',
    631 				'delete_blocks',
    632 				'delete_private_blocks',
    633 				'delete_published_blocks',
    634 				'delete_others_blocks',
    635 				'edit_private_blocks',
    636 				'edit_published_blocks',
    637 			);
    638 			if ( in_array( $cap, $block_caps, true ) ) {
    639 				$cap = str_replace( '_blocks', '_posts', $cap );
    640 			}
    641 
    642 			// If no meta caps match, return the original cap.
    643 			$caps[] = $cap;
    644 	}
    645 
    646 	/**
    647 	 * Filters the primitive capabilities required of the given user to satisfy the
    648 	 * capability being checked.
    649 	 *
    650 	 * @since 2.8.0
    651 	 *
    652 	 * @param string[] $caps    Primitive capabilities required of the user.
    653 	 * @param string   $cap     Capability being checked.
    654 	 * @param int      $user_id The user ID.
    655 	 * @param array    $args    Adds context to the capability check, typically
    656 	 *                          starting with an object ID.
    657 	 */
    658 	return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
    659 }
    660 
    661 /**
    662  * Returns whether the current user has the specified capability.
    663  *
    664  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
    665  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
    666  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
    667  *
    668  * Example usage:
    669  *
    670  *     current_user_can( 'edit_posts' );
    671  *     current_user_can( 'edit_post', $post->ID );
    672  *     current_user_can( 'edit_post_meta', $post->ID, $meta_key );
    673  *
    674  * While checking against particular roles in place of a capability is supported
    675  * in part, this practice is discouraged as it may produce unreliable results.
    676  *
    677  * Note: Will always return true if the current user is a super admin, unless specifically denied.
    678  *
    679  * @since 2.0.0
    680  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    681  *              by adding it to the function signature.
    682  * @since 5.8.0 Converted to wrapper for the user_can() function.
    683  *
    684  * @see WP_User::has_cap()
    685  * @see map_meta_cap()
    686  *
    687  * @param string $capability Capability name.
    688  * @param mixed  ...$args    Optional further parameters, typically starting with an object ID.
    689  * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is
    690  *              passed, whether the current user has the given meta capability for the given object.
    691  */
    692 function current_user_can( $capability, ...$args ) {
    693 	return user_can( wp_get_current_user(), $capability, ...$args );
    694 }
    695 
    696 /**
    697  * Returns whether the current user has the specified capability for a given site.
    698  *
    699  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
    700  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
    701  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
    702  *
    703  * Example usage:
    704  *
    705  *     current_user_can_for_blog( $blog_id, 'edit_posts' );
    706  *     current_user_can_for_blog( $blog_id, 'edit_post', $post->ID );
    707  *     current_user_can_for_blog( $blog_id, 'edit_post_meta', $post->ID, $meta_key );
    708  *
    709  * @since 3.0.0
    710  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    711  *              by adding it to the function signature.
    712  * @since 5.8.0 Wraps current_user_can() after switching to blog.
    713  *
    714  * @param int    $blog_id    Site ID.
    715  * @param string $capability Capability name.
    716  * @param mixed  ...$args    Optional further parameters, typically starting with an object ID.
    717  * @return bool Whether the user has the given capability.
    718  */
    719 function current_user_can_for_blog( $blog_id, $capability, ...$args ) {
    720 	$switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
    721 
    722 	$can = current_user_can( $capability, ...$args );
    723 
    724 	if ( $switched ) {
    725 		restore_current_blog();
    726 	}
    727 
    728 	return $can;
    729 }
    730 
    731 /**
    732  * Returns whether the author of the supplied post has the specified capability.
    733  *
    734  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
    735  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
    736  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
    737  *
    738  * Example usage:
    739  *
    740  *     author_can( $post, 'edit_posts' );
    741  *     author_can( $post, 'edit_post', $post->ID );
    742  *     author_can( $post, 'edit_post_meta', $post->ID, $meta_key );
    743  *
    744  * @since 2.9.0
    745  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    746  *              by adding it to the function signature.
    747  *
    748  * @param int|WP_Post $post       Post ID or post object.
    749  * @param string      $capability Capability name.
    750  * @param mixed       ...$args    Optional further parameters, typically starting with an object ID.
    751  * @return bool Whether the post author has the given capability.
    752  */
    753 function author_can( $post, $capability, ...$args ) {
    754 	$post = get_post( $post );
    755 	if ( ! $post ) {
    756 		return false;
    757 	}
    758 
    759 	$author = get_userdata( $post->post_author );
    760 
    761 	if ( ! $author ) {
    762 		return false;
    763 	}
    764 
    765 	return $author->has_cap( $capability, ...$args );
    766 }
    767 
    768 /**
    769  * Returns whether a particular user has the specified capability.
    770  *
    771  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
    772  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
    773  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
    774  *
    775  * Example usage:
    776  *
    777  *     user_can( $user->ID, 'edit_posts' );
    778  *     user_can( $user->ID, 'edit_post', $post->ID );
    779  *     user_can( $user->ID, 'edit_post_meta', $post->ID, $meta_key );
    780  *
    781  * @since 3.1.0
    782  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    783  *              by adding it to the function signature.
    784  *
    785  * @param int|WP_User $user       User ID or object.
    786  * @param string      $capability Capability name.
    787  * @param mixed       ...$args    Optional further parameters, typically starting with an object ID.
    788  * @return bool Whether the user has the given capability.
    789  */
    790 function user_can( $user, $capability, ...$args ) {
    791 	if ( ! is_object( $user ) ) {
    792 		$user = get_userdata( $user );
    793 	}
    794 
    795 	if ( empty( $user ) ) {
    796 		// User is logged out, create anonymous user object.
    797 		$user = new WP_User( 0 );
    798 		$user->init( new stdClass );
    799 	}
    800 
    801 	return $user->has_cap( $capability, ...$args );
    802 }
    803 
    804 /**
    805  * Retrieves the global WP_Roles instance and instantiates it if necessary.
    806  *
    807  * @since 4.3.0
    808  *
    809  * @global WP_Roles $wp_roles WordPress role management object.
    810  *
    811  * @return WP_Roles WP_Roles global instance if not already instantiated.
    812  */
    813 function wp_roles() {
    814 	global $wp_roles;
    815 
    816 	if ( ! isset( $wp_roles ) ) {
    817 		$wp_roles = new WP_Roles();
    818 	}
    819 	return $wp_roles;
    820 }
    821 
    822 /**
    823  * Retrieve role object.
    824  *
    825  * @since 2.0.0
    826  *
    827  * @param string $role Role name.
    828  * @return WP_Role|null WP_Role object if found, null if the role does not exist.
    829  */
    830 function get_role( $role ) {
    831 	return wp_roles()->get_role( $role );
    832 }
    833 
    834 /**
    835  * Add role, if it does not exist.
    836  *
    837  * @since 2.0.0
    838  *
    839  * @param string $role         Role name.
    840  * @param string $display_name Display name for role.
    841  * @param bool[] $capabilities List of capabilities keyed by the capability name,
    842  *                             e.g. array( 'edit_posts' => true, 'delete_posts' => false ).
    843  * @return WP_Role|null WP_Role object if role is added, null if already exists.
    844  */
    845 function add_role( $role, $display_name, $capabilities = array() ) {
    846 	if ( empty( $role ) ) {
    847 		return;
    848 	}
    849 	return wp_roles()->add_role( $role, $display_name, $capabilities );
    850 }
    851 
    852 /**
    853  * Remove role, if it exists.
    854  *
    855  * @since 2.0.0
    856  *
    857  * @param string $role Role name.
    858  */
    859 function remove_role( $role ) {
    860 	wp_roles()->remove_role( $role );
    861 }
    862 
    863 /**
    864  * Retrieve a list of super admins.
    865  *
    866  * @since 3.0.0
    867  *
    868  * @global array $super_admins
    869  *
    870  * @return string[] List of super admin logins.
    871  */
    872 function get_super_admins() {
    873 	global $super_admins;
    874 
    875 	if ( isset( $super_admins ) ) {
    876 		return $super_admins;
    877 	} else {
    878 		return get_site_option( 'site_admins', array( 'admin' ) );
    879 	}
    880 }
    881 
    882 /**
    883  * Determine if user is a site admin.
    884  *
    885  * @since 3.0.0
    886  *
    887  * @param int|false $user_id Optional. The ID of a user. Defaults to false, to check the current user.
    888  * @return bool Whether the user is a site admin.
    889  */
    890 function is_super_admin( $user_id = false ) {
    891 	if ( ! $user_id || get_current_user_id() == $user_id ) {
    892 		$user = wp_get_current_user();
    893 	} else {
    894 		$user = get_userdata( $user_id );
    895 	}
    896 
    897 	if ( ! $user || ! $user->exists() ) {
    898 		return false;
    899 	}
    900 
    901 	if ( is_multisite() ) {
    902 		$super_admins = get_super_admins();
    903 		if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins, true ) ) {
    904 			return true;
    905 		}
    906 	} else {
    907 		if ( $user->has_cap( 'delete_users' ) ) {
    908 			return true;
    909 		}
    910 	}
    911 
    912 	return false;
    913 }
    914 
    915 /**
    916  * Grants Super Admin privileges.
    917  *
    918  * @since 3.0.0
    919  *
    920  * @global array $super_admins
    921  *
    922  * @param int $user_id ID of the user to be granted Super Admin privileges.
    923  * @return bool True on success, false on failure. This can fail when the user is
    924  *              already a super admin or when the `$super_admins` global is defined.
    925  */
    926 function grant_super_admin( $user_id ) {
    927 	// If global super_admins override is defined, there is nothing to do here.
    928 	if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
    929 		return false;
    930 	}
    931 
    932 	/**
    933 	 * Fires before the user is granted Super Admin privileges.
    934 	 *
    935 	 * @since 3.0.0
    936 	 *
    937 	 * @param int $user_id ID of the user that is about to be granted Super Admin privileges.
    938 	 */
    939 	do_action( 'grant_super_admin', $user_id );
    940 
    941 	// Directly fetch site_admins instead of using get_super_admins().
    942 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
    943 
    944 	$user = get_userdata( $user_id );
    945 	if ( $user && ! in_array( $user->user_login, $super_admins, true ) ) {
    946 		$super_admins[] = $user->user_login;
    947 		update_site_option( 'site_admins', $super_admins );
    948 
    949 		/**
    950 		 * Fires after the user is granted Super Admin privileges.
    951 		 *
    952 		 * @since 3.0.0
    953 		 *
    954 		 * @param int $user_id ID of the user that was granted Super Admin privileges.
    955 		 */
    956 		do_action( 'granted_super_admin', $user_id );
    957 		return true;
    958 	}
    959 	return false;
    960 }
    961 
    962 /**
    963  * Revokes Super Admin privileges.
    964  *
    965  * @since 3.0.0
    966  *
    967  * @global array $super_admins
    968  *
    969  * @param int $user_id ID of the user Super Admin privileges to be revoked from.
    970  * @return bool True on success, false on failure. This can fail when the user's email
    971  *              is the network admin email or when the `$super_admins` global is defined.
    972  */
    973 function revoke_super_admin( $user_id ) {
    974 	// If global super_admins override is defined, there is nothing to do here.
    975 	if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) {
    976 		return false;
    977 	}
    978 
    979 	/**
    980 	 * Fires before the user's Super Admin privileges are revoked.
    981 	 *
    982 	 * @since 3.0.0
    983 	 *
    984 	 * @param int $user_id ID of the user Super Admin privileges are being revoked from.
    985 	 */
    986 	do_action( 'revoke_super_admin', $user_id );
    987 
    988 	// Directly fetch site_admins instead of using get_super_admins().
    989 	$super_admins = get_site_option( 'site_admins', array( 'admin' ) );
    990 
    991 	$user = get_userdata( $user_id );
    992 	if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) {
    993 		$key = array_search( $user->user_login, $super_admins, true );
    994 		if ( false !== $key ) {
    995 			unset( $super_admins[ $key ] );
    996 			update_site_option( 'site_admins', $super_admins );
    997 
    998 			/**
    999 			 * Fires after the user's Super Admin privileges are revoked.
   1000 			 *
   1001 			 * @since 3.0.0
   1002 			 *
   1003 			 * @param int $user_id ID of the user Super Admin privileges were revoked from.
   1004 			 */
   1005 			do_action( 'revoked_super_admin', $user_id );
   1006 			return true;
   1007 		}
   1008 	}
   1009 	return false;
   1010 }
   1011 
   1012 /**
   1013  * Filters the user capabilities to grant the 'install_languages' capability as necessary.
   1014  *
   1015  * A user must have at least one out of the 'update_core', 'install_plugins', and
   1016  * 'install_themes' capabilities to qualify for 'install_languages'.
   1017  *
   1018  * @since 4.9.0
   1019  *
   1020  * @param bool[] $allcaps An array of all the user's capabilities.
   1021  * @return bool[] Filtered array of the user's capabilities.
   1022  */
   1023 function wp_maybe_grant_install_languages_cap( $allcaps ) {
   1024 	if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) {
   1025 		$allcaps['install_languages'] = true;
   1026 	}
   1027 
   1028 	return $allcaps;
   1029 }
   1030 
   1031 /**
   1032  * Filters the user capabilities to grant the 'resume_plugins' and 'resume_themes' capabilities as necessary.
   1033  *
   1034  * @since 5.2.0
   1035  *
   1036  * @param bool[] $allcaps An array of all the user's capabilities.
   1037  * @return bool[] Filtered array of the user's capabilities.
   1038  */
   1039 function wp_maybe_grant_resume_extensions_caps( $allcaps ) {
   1040 	// Even in a multisite, regular administrators should be able to resume plugins.
   1041 	if ( ! empty( $allcaps['activate_plugins'] ) ) {
   1042 		$allcaps['resume_plugins'] = true;
   1043 	}
   1044 
   1045 	// Even in a multisite, regular administrators should be able to resume themes.
   1046 	if ( ! empty( $allcaps['switch_themes'] ) ) {
   1047 		$allcaps['resume_themes'] = true;
   1048 	}
   1049 
   1050 	return $allcaps;
   1051 }
   1052 
   1053 /**
   1054  * Filters the user capabilities to grant the 'view_site_health_checks' capabilities as necessary.
   1055  *
   1056  * @since 5.2.2
   1057  *
   1058  * @param bool[]   $allcaps An array of all the user's capabilities.
   1059  * @param string[] $caps    Required primitive capabilities for the requested capability.
   1060  * @param array    $args {
   1061  *     Arguments that accompany the requested capability check.
   1062  *
   1063  *     @type string    $0 Requested capability.
   1064  *     @type int       $1 Concerned user ID.
   1065  *     @type mixed  ...$2 Optional second and further parameters, typically object ID.
   1066  * }
   1067  * @param WP_User  $user    The user object.
   1068  * @return bool[] Filtered array of the user's capabilities.
   1069  */
   1070 function wp_maybe_grant_site_health_caps( $allcaps, $caps, $args, $user ) {
   1071 	if ( ! empty( $allcaps['install_plugins'] ) && ( ! is_multisite() || is_super_admin( $user->ID ) ) ) {
   1072 		$allcaps['view_site_health_checks'] = true;
   1073 	}
   1074 
   1075 	return $allcaps;
   1076 }
   1077 
   1078 return;
   1079 
   1080 // Dummy gettext calls to get strings in the catalog.
   1081 /* translators: User role for administrators. */
   1082 _x( 'Administrator', 'User role' );
   1083 /* translators: User role for editors. */
   1084 _x( 'Editor', 'User role' );
   1085 /* translators: User role for authors. */
   1086 _x( 'Author', 'User role' );
   1087 /* translators: User role for contributors. */
   1088 _x( 'Contributor', 'User role' );
   1089 /* translators: User role for subscribers. */
   1090 _x( 'Subscriber', 'User role' );