[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 * @since 6.7.0 Added the `edit_block_binding` capability. 37 * 38 * @global array $post_type_meta_caps Used to get post type meta capabilities. 39 * 40 * @param string $cap Capability being checked. 41 * @param int $user_id User ID. 42 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 43 * @return string[] Primitive capabilities required of the user. 44 */ 45 function map_meta_cap( $cap, $user_id, ...$args ) { 46 $caps = array(); 47 48 switch ( $cap ) { 49 case 'remove_user': 50 // In multisite the user must be a super admin to remove themselves. 51 if ( isset( $args[0] ) && $user_id === (int) $args[0] && ! is_super_admin( $user_id ) ) { 52 $caps[] = 'do_not_allow'; 53 } else { 54 $caps[] = 'remove_users'; 55 } 56 break; 57 case 'promote_user': 58 case 'add_users': 59 $caps[] = 'promote_users'; 60 break; 61 case 'edit_user': 62 case 'edit_users': 63 // Non-existent users can't edit users, not even themselves. 64 if ( $user_id < 1 ) { 65 $caps[] = 'do_not_allow'; 66 break; 67 } 68 69 // Allow user to edit themselves. 70 if ( 'edit_user' === $cap && isset( $args[0] ) && $user_id === (int) $args[0] ) { 71 break; 72 } 73 74 // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin. 75 if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) { 76 $caps[] = 'do_not_allow'; 77 } else { 78 $caps[] = 'edit_users'; // edit_user maps to edit_users. 79 } 80 break; 81 case 'delete_post': 82 case 'delete_page': 83 if ( ! isset( $args[0] ) ) { 84 if ( 'delete_post' === $cap ) { 85 /* translators: %s: Capability name. */ 86 $message = __( 'When checking for the %s capability, you must always check it against a specific post.' ); 87 } else { 88 /* translators: %s: Capability name. */ 89 $message = __( 'When checking for the %s capability, you must always check it against a specific page.' ); 90 } 91 92 _doing_it_wrong( 93 __FUNCTION__, 94 sprintf( $message, '<code>' . $cap . '</code>' ), 95 '6.1.0' 96 ); 97 98 $caps[] = 'do_not_allow'; 99 break; 100 } 101 102 $post = get_post( $args[0] ); 103 if ( ! $post ) { 104 $caps[] = 'do_not_allow'; 105 break; 106 } 107 108 if ( 'revision' === $post->post_type ) { 109 $caps[] = 'do_not_allow'; 110 break; 111 } 112 113 if ( (int) get_option( 'page_for_posts' ) === $post->ID 114 || (int) get_option( 'page_on_front' ) === $post->ID 115 ) { 116 $caps[] = 'manage_options'; 117 break; 118 } 119 120 $post_type = get_post_type_object( $post->post_type ); 121 if ( ! $post_type ) { 122 /* translators: 1: Post type, 2: Capability name. */ 123 $message = __( '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.' ); 124 125 _doing_it_wrong( 126 __FUNCTION__, 127 sprintf( 128 $message, 129 '<code>' . $post->post_type . '</code>', 130 '<code>' . $cap . '</code>' 131 ), 132 '4.4.0' 133 ); 134 135 $caps[] = 'edit_others_posts'; 136 break; 137 } 138 139 if ( ! $post_type->map_meta_cap ) { 140 $caps[] = $post_type->cap->$cap; 141 // Prior to 3.1 we would re-call map_meta_cap here. 142 if ( 'delete_post' === $cap ) { 143 $cap = $post_type->cap->$cap; 144 } 145 break; 146 } 147 148 // If the post author is set and the user is the author... 149 if ( $post->post_author && $user_id === (int) $post->post_author ) { 150 // If the post is published or scheduled... 151 if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 152 $caps[] = $post_type->cap->delete_published_posts; 153 } elseif ( 'trash' === $post->post_status ) { 154 $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); 155 if ( in_array( $status, array( 'publish', 'future' ), true ) ) { 156 $caps[] = $post_type->cap->delete_published_posts; 157 } else { 158 $caps[] = $post_type->cap->delete_posts; 159 } 160 } else { 161 // If the post is draft... 162 $caps[] = $post_type->cap->delete_posts; 163 } 164 } else { 165 // The user is trying to edit someone else's post. 166 $caps[] = $post_type->cap->delete_others_posts; 167 // The post is published or scheduled, extra cap required. 168 if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 169 $caps[] = $post_type->cap->delete_published_posts; 170 } elseif ( 'private' === $post->post_status ) { 171 $caps[] = $post_type->cap->delete_private_posts; 172 } 173 } 174 175 /* 176 * Setting the privacy policy page requires `manage_privacy_options`, 177 * so deleting it should require that too. 178 */ 179 if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) { 180 $caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) ); 181 } 182 183 break; 184 /* 185 * edit_post breaks down to edit_posts, edit_published_posts, or 186 * edit_others_posts. 187 */ 188 case 'edit_post': 189 case 'edit_page': 190 if ( ! isset( $args[0] ) ) { 191 if ( 'edit_post' === $cap ) { 192 /* translators: %s: Capability name. */ 193 $message = __( 'When checking for the %s capability, you must always check it against a specific post.' ); 194 } else { 195 /* translators: %s: Capability name. */ 196 $message = __( 'When checking for the %s capability, you must always check it against a specific page.' ); 197 } 198 199 _doing_it_wrong( 200 __FUNCTION__, 201 sprintf( $message, '<code>' . $cap . '</code>' ), 202 '6.1.0' 203 ); 204 205 $caps[] = 'do_not_allow'; 206 break; 207 } 208 209 $post = get_post( $args[0] ); 210 if ( ! $post ) { 211 $caps[] = 'do_not_allow'; 212 break; 213 } 214 215 if ( 'revision' === $post->post_type ) { 216 $post = get_post( $post->post_parent ); 217 if ( ! $post ) { 218 $caps[] = 'do_not_allow'; 219 break; 220 } 221 } 222 223 $post_type = get_post_type_object( $post->post_type ); 224 if ( ! $post_type ) { 225 /* translators: 1: Post type, 2: Capability name. */ 226 $message = __( '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.' ); 227 228 _doing_it_wrong( 229 __FUNCTION__, 230 sprintf( 231 $message, 232 '<code>' . $post->post_type . '</code>', 233 '<code>' . $cap . '</code>' 234 ), 235 '4.4.0' 236 ); 237 238 $caps[] = 'edit_others_posts'; 239 break; 240 } 241 242 if ( ! $post_type->map_meta_cap ) { 243 $caps[] = $post_type->cap->$cap; 244 // Prior to 3.1 we would re-call map_meta_cap here. 245 if ( 'edit_post' === $cap ) { 246 $cap = $post_type->cap->$cap; 247 } 248 break; 249 } 250 251 // If the post author is set and the user is the author... 252 if ( $post->post_author && $user_id === (int) $post->post_author ) { 253 // If the post is published or scheduled... 254 if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 255 $caps[] = $post_type->cap->edit_published_posts; 256 } elseif ( 'trash' === $post->post_status ) { 257 $status = get_post_meta( $post->ID, '_wp_trash_meta_status', true ); 258 if ( in_array( $status, array( 'publish', 'future' ), true ) ) { 259 $caps[] = $post_type->cap->edit_published_posts; 260 } else { 261 $caps[] = $post_type->cap->edit_posts; 262 } 263 } else { 264 // If the post is draft... 265 $caps[] = $post_type->cap->edit_posts; 266 } 267 } else { 268 // The user is trying to edit someone else's post. 269 $caps[] = $post_type->cap->edit_others_posts; 270 // The post is published or scheduled, extra cap required. 271 if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) { 272 $caps[] = $post_type->cap->edit_published_posts; 273 } elseif ( 'private' === $post->post_status ) { 274 $caps[] = $post_type->cap->edit_private_posts; 275 } 276 } 277 278 /* 279 * Setting the privacy policy page requires `manage_privacy_options`, 280 * so editing it should require that too. 281 */ 282 if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) { 283 $caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) ); 284 } 285 286 break; 287 case 'read_post': 288 case 'read_page': 289 if ( ! isset( $args[0] ) ) { 290 if ( 'read_post' === $cap ) { 291 /* translators: %s: Capability name. */ 292 $message = __( 'When checking for the %s capability, you must always check it against a specific post.' ); 293 } else { 294 /* translators: %s: Capability name. */ 295 $message = __( 'When checking for the %s capability, you must always check it against a specific page.' ); 296 } 297 298 _doing_it_wrong( 299 __FUNCTION__, 300 sprintf( $message, '<code>' . $cap . '</code>' ), 301 '6.1.0' 302 ); 303 304 $caps[] = 'do_not_allow'; 305 break; 306 } 307 308 $post = get_post( $args[0] ); 309 if ( ! $post ) { 310 $caps[] = 'do_not_allow'; 311 break; 312 } 313 314 if ( 'revision' === $post->post_type ) { 315 $post = get_post( $post->post_parent ); 316 if ( ! $post ) { 317 $caps[] = 'do_not_allow'; 318 break; 319 } 320 } 321 322 $post_type = get_post_type_object( $post->post_type ); 323 if ( ! $post_type ) { 324 /* translators: 1: Post type, 2: Capability name. */ 325 $message = __( '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.' ); 326 327 _doing_it_wrong( 328 __FUNCTION__, 329 sprintf( 330 $message, 331 '<code>' . $post->post_type . '</code>', 332 '<code>' . $cap . '</code>' 333 ), 334 '4.4.0' 335 ); 336 337 $caps[] = 'edit_others_posts'; 338 break; 339 } 340 341 if ( ! $post_type->map_meta_cap ) { 342 $caps[] = $post_type->cap->$cap; 343 // Prior to 3.1 we would re-call map_meta_cap here. 344 if ( 'read_post' === $cap ) { 345 $cap = $post_type->cap->$cap; 346 } 347 break; 348 } 349 350 $status_obj = get_post_status_object( get_post_status( $post ) ); 351 if ( ! $status_obj ) { 352 /* translators: 1: Post status, 2: Capability name. */ 353 $message = __( '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.' ); 354 355 _doing_it_wrong( 356 __FUNCTION__, 357 sprintf( 358 $message, 359 '<code>' . get_post_status( $post ) . '</code>', 360 '<code>' . $cap . '</code>' 361 ), 362 '5.4.0' 363 ); 364 365 $caps[] = 'edit_others_posts'; 366 break; 367 } 368 369 if ( $status_obj->public ) { 370 $caps[] = $post_type->cap->read; 371 break; 372 } 373 374 if ( $post->post_author && $user_id === (int) $post->post_author ) { 375 $caps[] = $post_type->cap->read; 376 } elseif ( $status_obj->private ) { 377 $caps[] = $post_type->cap->read_private_posts; 378 } else { 379 $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); 380 } 381 break; 382 case 'publish_post': 383 if ( ! isset( $args[0] ) ) { 384 /* translators: %s: Capability name. */ 385 $message = __( 'When checking for the %s capability, you must always check it against a specific post.' ); 386 387 _doing_it_wrong( 388 __FUNCTION__, 389 sprintf( $message, '<code>' . $cap . '</code>' ), 390 '6.1.0' 391 ); 392 393 $caps[] = 'do_not_allow'; 394 break; 395 } 396 397 $post = get_post( $args[0] ); 398 if ( ! $post ) { 399 $caps[] = 'do_not_allow'; 400 break; 401 } 402 403 $post_type = get_post_type_object( $post->post_type ); 404 if ( ! $post_type ) { 405 /* translators: 1: Post type, 2: Capability name. */ 406 $message = __( '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.' ); 407 408 _doing_it_wrong( 409 __FUNCTION__, 410 sprintf( 411 $message, 412 '<code>' . $post->post_type . '</code>', 413 '<code>' . $cap . '</code>' 414 ), 415 '4.4.0' 416 ); 417 418 $caps[] = 'edit_others_posts'; 419 break; 420 } 421 422 $caps[] = $post_type->cap->publish_posts; 423 break; 424 case 'edit_post_meta': 425 case 'delete_post_meta': 426 case 'add_post_meta': 427 case 'edit_comment_meta': 428 case 'delete_comment_meta': 429 case 'add_comment_meta': 430 case 'edit_term_meta': 431 case 'delete_term_meta': 432 case 'add_term_meta': 433 case 'edit_user_meta': 434 case 'delete_user_meta': 435 case 'add_user_meta': 436 $object_type = explode( '_', $cap )[1]; 437 438 if ( ! isset( $args[0] ) ) { 439 if ( 'post' === $object_type ) { 440 /* translators: %s: Capability name. */ 441 $message = __( 'When checking for the %s capability, you must always check it against a specific post.' ); 442 } elseif ( 'comment' === $object_type ) { 443 /* translators: %s: Capability name. */ 444 $message = __( 'When checking for the %s capability, you must always check it against a specific comment.' ); 445 } elseif ( 'term' === $object_type ) { 446 /* translators: %s: Capability name. */ 447 $message = __( 'When checking for the %s capability, you must always check it against a specific term.' ); 448 } else { 449 /* translators: %s: Capability name. */ 450 $message = __( 'When checking for the %s capability, you must always check it against a specific user.' ); 451 } 452 453 _doing_it_wrong( 454 __FUNCTION__, 455 sprintf( $message, '<code>' . $cap . '</code>' ), 456 '6.1.0' 457 ); 458 459 $caps[] = 'do_not_allow'; 460 break; 461 } 462 463 $object_id = (int) $args[0]; 464 465 $object_subtype = get_object_subtype( $object_type, $object_id ); 466 467 if ( empty( $object_subtype ) ) { 468 $caps[] = 'do_not_allow'; 469 break; 470 } 471 472 $caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id ); 473 474 $meta_key = isset( $args[1] ) ? $args[1] : false; 475 476 if ( $meta_key ) { 477 $allowed = ! is_protected_meta( $meta_key, $object_type ); 478 479 if ( has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) { 480 481 /** 482 * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype. 483 * 484 * The dynamic portions of the hook name, `$object_type`, `$meta_key`, 485 * and `$object_subtype`, refer to the metadata object type (comment, post, term or user), 486 * the meta key value, and the object subtype respectively. 487 * 488 * @since 4.9.8 489 * 490 * @param bool $allowed Whether the user can add the object meta. Default false. 491 * @param string $meta_key The meta key. 492 * @param int $object_id Object ID. 493 * @param int $user_id User ID. 494 * @param string $cap Capability name. 495 * @param string[] $caps Array of the user's capabilities. 496 */ 497 $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps ); 498 } else { 499 500 /** 501 * Filters whether the user is allowed to edit a specific meta key of a specific object type. 502 * 503 * Return true to have the mapped meta caps from `edit_{$object_type}` apply. 504 * 505 * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered. 506 * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap(). 507 * 508 * @since 3.3.0 As `auth_post_meta_{$meta_key}`. 509 * @since 4.6.0 510 * 511 * @param bool $allowed Whether the user can add the object meta. Default false. 512 * @param string $meta_key The meta key. 513 * @param int $object_id Object ID. 514 * @param int $user_id User ID. 515 * @param string $cap Capability name. 516 * @param string[] $caps Array of the user's capabilities. 517 */ 518 $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps ); 519 } 520 521 /** 522 * Filters whether the user is allowed to edit meta for specific object types/subtypes. 523 * 524 * Return true to have the mapped meta caps from `edit_{$object_type}` apply. 525 * 526 * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered. 527 * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered. 528 * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap(). 529 * 530 * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`. 531 * @since 4.7.0 Renamed from `auth_post_{$post_type}_meta_{$meta_key}` to 532 * `auth_{$object_type}_{$object_subtype}_meta_{$meta_key}`. 533 * @deprecated 4.9.8 Use {@see 'auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}'} instead. 534 * 535 * @param bool $allowed Whether the user can add the object meta. Default false. 536 * @param string $meta_key The meta key. 537 * @param int $object_id Object ID. 538 * @param int $user_id User ID. 539 * @param string $cap Capability name. 540 * @param string[] $caps Array of the user's capabilities. 541 */ 542 $allowed = apply_filters_deprecated( 543 "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", 544 array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ), 545 '4.9.8', 546 "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" 547 ); 548 549 if ( ! $allowed ) { 550 $caps[] = $cap; 551 } 552 } 553 break; 554 case 'edit_comment': 555 if ( ! isset( $args[0] ) ) { 556 /* translators: %s: Capability name. */ 557 $message = __( 'When checking for the %s capability, you must always check it against a specific comment.' ); 558 559 _doing_it_wrong( 560 __FUNCTION__, 561 sprintf( $message, '<code>' . $cap . '</code>' ), 562 '6.1.0' 563 ); 564 565 $caps[] = 'do_not_allow'; 566 break; 567 } 568 569 $comment = get_comment( $args[0] ); 570 if ( ! $comment ) { 571 $caps[] = 'do_not_allow'; 572 break; 573 } 574 575 $post = get_post( $comment->comment_post_ID ); 576 577 /* 578 * If the post doesn't exist, we have an orphaned comment. 579 * Fall back to the edit_posts capability, instead. 580 */ 581 if ( $post ) { 582 $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); 583 } else { 584 $caps = map_meta_cap( 'edit_posts', $user_id ); 585 } 586 break; 587 case 'unfiltered_upload': 588 if ( defined( 'ALLOW_UNFILTERED_UPLOADS' ) && ALLOW_UNFILTERED_UPLOADS && ( ! is_multisite() || is_super_admin( $user_id ) ) ) { 589 $caps[] = $cap; 590 } else { 591 $caps[] = 'do_not_allow'; 592 } 593 break; 594 case 'edit_css': 595 case 'unfiltered_html': 596 // Disallow unfiltered_html for all users, even admins and super admins. 597 if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) { 598 $caps[] = 'do_not_allow'; 599 } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { 600 $caps[] = 'do_not_allow'; 601 } else { 602 $caps[] = 'unfiltered_html'; 603 } 604 break; 605 case 'edit_files': 606 case 'edit_plugins': 607 case 'edit_themes': 608 // Disallow the file editors. 609 if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) { 610 $caps[] = 'do_not_allow'; 611 } elseif ( ! wp_is_file_mod_allowed( 'capability_edit_themes' ) ) { 612 $caps[] = 'do_not_allow'; 613 } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { 614 $caps[] = 'do_not_allow'; 615 } else { 616 $caps[] = $cap; 617 } 618 break; 619 case 'update_plugins': 620 case 'delete_plugins': 621 case 'install_plugins': 622 case 'upload_plugins': 623 case 'update_themes': 624 case 'delete_themes': 625 case 'install_themes': 626 case 'upload_themes': 627 case 'update_core': 628 /* 629 * Disallow anything that creates, deletes, or updates core, plugin, or theme files. 630 * Files in uploads are excepted. 631 */ 632 if ( ! wp_is_file_mod_allowed( 'capability_update_core' ) ) { 633 $caps[] = 'do_not_allow'; 634 } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { 635 $caps[] = 'do_not_allow'; 636 } elseif ( 'upload_themes' === $cap ) { 637 $caps[] = 'install_themes'; 638 } elseif ( 'upload_plugins' === $cap ) { 639 $caps[] = 'install_plugins'; 640 } else { 641 $caps[] = $cap; 642 } 643 break; 644 case 'install_languages': 645 case 'update_languages': 646 if ( ! wp_is_file_mod_allowed( 'can_install_language_pack' ) ) { 647 $caps[] = 'do_not_allow'; 648 } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) { 649 $caps[] = 'do_not_allow'; 650 } else { 651 $caps[] = 'install_languages'; 652 } 653 break; 654 case 'activate_plugins': 655 case 'deactivate_plugins': 656 case 'activate_plugin': 657 case 'deactivate_plugin': 658 $caps[] = 'activate_plugins'; 659 if ( is_multisite() ) { 660 // update_, install_, and delete_ are handled above with is_super_admin(). 661 $menu_perms = get_site_option( 'menu_items', array() ); 662 if ( empty( $menu_perms['plugins'] ) ) { 663 $caps[] = 'manage_network_plugins'; 664 } 665 } 666 break; 667 case 'resume_plugin': 668 $caps[] = 'resume_plugins'; 669 break; 670 case 'resume_theme': 671 $caps[] = 'resume_themes'; 672 break; 673 case 'delete_user': 674 case 'delete_users': 675 // If multisite only super admins can delete users. 676 if ( is_multisite() && ! is_super_admin( $user_id ) ) { 677 $caps[] = 'do_not_allow'; 678 } else { 679 $caps[] = 'delete_users'; // delete_user maps to delete_users. 680 } 681 break; 682 case 'create_users': 683 if ( ! is_multisite() ) { 684 $caps[] = $cap; 685 } elseif ( is_super_admin( $user_id ) || get_site_option( 'add_new_users' ) ) { 686 $caps[] = $cap; 687 } else { 688 $caps[] = 'do_not_allow'; 689 } 690 break; 691 case 'manage_links': 692 if ( get_option( 'link_manager_enabled' ) ) { 693 $caps[] = $cap; 694 } else { 695 $caps[] = 'do_not_allow'; 696 } 697 break; 698 case 'customize': 699 $caps[] = 'edit_theme_options'; 700 break; 701 case 'delete_site': 702 if ( is_multisite() ) { 703 $caps[] = 'manage_options'; 704 } else { 705 $caps[] = 'do_not_allow'; 706 } 707 break; 708 case 'edit_term': 709 case 'delete_term': 710 case 'assign_term': 711 if ( ! isset( $args[0] ) ) { 712 /* translators: %s: Capability name. */ 713 $message = __( 'When checking for the %s capability, you must always check it against a specific term.' ); 714 715 _doing_it_wrong( 716 __FUNCTION__, 717 sprintf( $message, '<code>' . $cap . '</code>' ), 718 '6.1.0' 719 ); 720 721 $caps[] = 'do_not_allow'; 722 break; 723 } 724 725 $term_id = (int) $args[0]; 726 $term = get_term( $term_id ); 727 if ( ! $term || is_wp_error( $term ) ) { 728 $caps[] = 'do_not_allow'; 729 break; 730 } 731 732 $tax = get_taxonomy( $term->taxonomy ); 733 if ( ! $tax ) { 734 $caps[] = 'do_not_allow'; 735 break; 736 } 737 738 if ( 'delete_term' === $cap 739 && ( (int) get_option( 'default_' . $term->taxonomy ) === $term->term_id 740 || (int) get_option( 'default_term_' . $term->taxonomy ) === $term->term_id ) 741 ) { 742 $caps[] = 'do_not_allow'; 743 break; 744 } 745 746 $taxo_cap = $cap . 's'; 747 748 $caps = map_meta_cap( $tax->cap->$taxo_cap, $user_id, $term_id ); 749 750 break; 751 case 'manage_post_tags': 752 case 'edit_categories': 753 case 'edit_post_tags': 754 case 'delete_categories': 755 case 'delete_post_tags': 756 $caps[] = 'manage_categories'; 757 break; 758 case 'assign_categories': 759 case 'assign_post_tags': 760 $caps[] = 'edit_posts'; 761 break; 762 case 'create_sites': 763 case 'delete_sites': 764 case 'manage_network': 765 case 'manage_sites': 766 case 'manage_network_users': 767 case 'manage_network_plugins': 768 case 'manage_network_themes': 769 case 'manage_network_options': 770 case 'upgrade_network': 771 $caps[] = $cap; 772 break; 773 case 'setup_network': 774 if ( is_multisite() ) { 775 $caps[] = 'manage_network_options'; 776 } else { 777 $caps[] = 'manage_options'; 778 } 779 break; 780 case 'update_php': 781 if ( is_multisite() && ! is_super_admin( $user_id ) ) { 782 $caps[] = 'do_not_allow'; 783 } else { 784 $caps[] = 'update_core'; 785 } 786 break; 787 case 'update_https': 788 if ( is_multisite() && ! is_super_admin( $user_id ) ) { 789 $caps[] = 'do_not_allow'; 790 } else { 791 $caps[] = 'manage_options'; 792 $caps[] = 'update_core'; 793 } 794 break; 795 case 'export_others_personal_data': 796 case 'erase_others_personal_data': 797 case 'manage_privacy_options': 798 $caps[] = is_multisite() ? 'manage_network' : 'manage_options'; 799 break; 800 case 'create_app_password': 801 case 'list_app_passwords': 802 case 'read_app_password': 803 case 'edit_app_password': 804 case 'delete_app_passwords': 805 case 'delete_app_password': 806 $caps = map_meta_cap( 'edit_user', $user_id, $args[0] ); 807 break; 808 case 'edit_block_binding': 809 $block_editor_context = $args[0]; 810 if ( isset( $block_editor_context->post ) ) { 811 $object_id = $block_editor_context->post->ID; 812 } 813 /* 814 * If the post ID is null, check if the context is the site editor. 815 * Fall back to the edit_theme_options in that case. 816 */ 817 if ( ! isset( $object_id ) ) { 818 if ( ! isset( $block_editor_context->name ) || 'core/edit-site' !== $block_editor_context->name ) { 819 $caps[] = 'do_not_allow'; 820 break; 821 } 822 $caps = map_meta_cap( 'edit_theme_options', $user_id ); 823 break; 824 } 825 826 $object_subtype = get_object_subtype( 'post', (int) $object_id ); 827 if ( empty( $object_subtype ) ) { 828 $caps[] = 'do_not_allow'; 829 break; 830 } 831 $post_type_object = get_post_type_object( $object_subtype ); 832 // Initialize empty array if it doesn't exist. 833 if ( ! isset( $post_type_object->capabilities ) ) { 834 $post_type_object->capabilities = array(); 835 } 836 $post_type_capabilities = get_post_type_capabilities( $post_type_object ); 837 $caps = map_meta_cap( $post_type_capabilities->edit_post, $user_id, $object_id ); 838 break; 839 default: 840 // Handle meta capabilities for custom post types. 841 global $post_type_meta_caps; 842 if ( isset( $post_type_meta_caps[ $cap ] ) ) { 843 return map_meta_cap( $post_type_meta_caps[ $cap ], $user_id, ...$args ); 844 } 845 846 // Block capabilities map to their post equivalent. 847 $block_caps = array( 848 'edit_blocks', 849 'edit_others_blocks', 850 'publish_blocks', 851 'read_private_blocks', 852 'delete_blocks', 853 'delete_private_blocks', 854 'delete_published_blocks', 855 'delete_others_blocks', 856 'edit_private_blocks', 857 'edit_published_blocks', 858 ); 859 if ( in_array( $cap, $block_caps, true ) ) { 860 $cap = str_replace( '_blocks', '_posts', $cap ); 861 } 862 863 // If no meta caps match, return the original cap. 864 $caps[] = $cap; 865 } 866 867 /** 868 * Filters the primitive capabilities required of the given user to satisfy the 869 * capability being checked. 870 * 871 * @since 2.8.0 872 * 873 * @param string[] $caps Primitive capabilities required of the user. 874 * @param string $cap Capability being checked. 875 * @param int $user_id The user ID. 876 * @param array $args Adds context to the capability check, typically 877 * starting with an object ID. 878 */ 879 return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args ); 880 } 881 882 /** 883 * Returns whether the current user has the specified capability. 884 * 885 * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta 886 * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to 887 * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. 888 * 889 * Example usage: 890 * 891 * current_user_can( 'edit_posts' ); 892 * current_user_can( 'edit_post', $post->ID ); 893 * current_user_can( 'edit_post_meta', $post->ID, $meta_key ); 894 * 895 * While checking against particular roles in place of a capability is supported 896 * in part, this practice is discouraged as it may produce unreliable results. 897 * 898 * Note: Will always return true if the current user is a super admin, unless specifically denied. 899 * 900 * @since 2.0.0 901 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter 902 * by adding it to the function signature. 903 * @since 5.8.0 Converted to wrapper for the user_can() function. 904 * 905 * @see WP_User::has_cap() 906 * @see map_meta_cap() 907 * 908 * @param string $capability Capability name. 909 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 910 * @return bool Whether the current user has the given capability. If `$capability` is a meta cap and `$object_id` is 911 * passed, whether the current user has the given meta capability for the given object. 912 */ 913 function current_user_can( $capability, ...$args ) { 914 return user_can( wp_get_current_user(), $capability, ...$args ); 915 } 916 917 /** 918 * Returns whether the current user has the specified capability for a given site. 919 * 920 * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta 921 * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to 922 * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. 923 * 924 * This function replaces the current_user_can_for_blog() function. 925 * 926 * Example usage: 927 * 928 * current_user_can_for_site( $site_id, 'edit_posts' ); 929 * current_user_can_for_site( $site_id, 'edit_post', $post->ID ); 930 * current_user_can_for_site( $site_id, 'edit_post_meta', $post->ID, $meta_key ); 931 * 932 * @since 6.7.0 933 * 934 * @param int $site_id Site ID. 935 * @param string $capability Capability name. 936 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 937 * @return bool Whether the user has the given capability. 938 */ 939 function current_user_can_for_site( $site_id, $capability, ...$args ) { 940 $switched = is_multisite() ? switch_to_blog( $site_id ) : false; 941 942 $can = current_user_can( $capability, ...$args ); 943 944 if ( $switched ) { 945 restore_current_blog(); 946 } 947 948 return $can; 949 } 950 951 /** 952 * Returns whether the author of the supplied post has the specified capability. 953 * 954 * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta 955 * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to 956 * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. 957 * 958 * Example usage: 959 * 960 * author_can( $post, 'edit_posts' ); 961 * author_can( $post, 'edit_post', $post->ID ); 962 * author_can( $post, 'edit_post_meta', $post->ID, $meta_key ); 963 * 964 * @since 2.9.0 965 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter 966 * by adding it to the function signature. 967 * 968 * @param int|WP_Post $post Post ID or post object. 969 * @param string $capability Capability name. 970 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 971 * @return bool Whether the post author has the given capability. 972 */ 973 function author_can( $post, $capability, ...$args ) { 974 $post = get_post( $post ); 975 if ( ! $post ) { 976 return false; 977 } 978 979 $author = get_userdata( $post->post_author ); 980 981 if ( ! $author ) { 982 return false; 983 } 984 985 return $author->has_cap( $capability, ...$args ); 986 } 987 988 /** 989 * Returns whether a particular user has the specified capability. 990 * 991 * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta 992 * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to 993 * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. 994 * 995 * Example usage: 996 * 997 * user_can( $user->ID, 'edit_posts' ); 998 * user_can( $user->ID, 'edit_post', $post->ID ); 999 * user_can( $user->ID, 'edit_post_meta', $post->ID, $meta_key ); 1000 * 1001 * @since 3.1.0 1002 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter 1003 * by adding it to the function signature. 1004 * 1005 * @param int|WP_User $user User ID or object. 1006 * @param string $capability Capability name. 1007 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 1008 * @return bool Whether the user has the given capability. 1009 */ 1010 function user_can( $user, $capability, ...$args ) { 1011 if ( ! is_object( $user ) ) { 1012 $user = get_userdata( $user ); 1013 } 1014 1015 if ( empty( $user ) ) { 1016 // User is logged out, create anonymous user object. 1017 $user = new WP_User( 0 ); 1018 $user->init( new stdClass() ); 1019 } 1020 1021 return $user->has_cap( $capability, ...$args ); 1022 } 1023 1024 /** 1025 * Returns whether a particular user has the specified capability for a given site. 1026 * 1027 * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta 1028 * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to 1029 * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`. 1030 * 1031 * Example usage: 1032 * 1033 * user_can_for_site( $user->ID, $site_id, 'edit_posts' ); 1034 * user_can_for_site( $user->ID, $site_id, 'edit_post', $post->ID ); 1035 * user_can_for_site( $user->ID, $site_id, 'edit_post_meta', $post->ID, $meta_key ); 1036 * 1037 * @since 6.7.0 1038 * 1039 * @param int|WP_User $user User ID or object. 1040 * @param int $site_id Site ID. 1041 * @param string $capability Capability name. 1042 * @param mixed ...$args Optional further parameters, typically starting with an object ID. 1043 * @return bool Whether the user has the given capability. 1044 */ 1045 function user_can_for_site( $user, $site_id, $capability, ...$args ) { 1046 if ( ! is_object( $user ) ) { 1047 $user = get_userdata( $user ); 1048 } 1049 1050 if ( empty( $user ) ) { 1051 // User is logged out, create anonymous user object. 1052 $user = new WP_User( 0 ); 1053 $user->init( new stdClass() ); 1054 } 1055 1056 // Check if the blog ID is valid. 1057 if ( ! is_numeric( $site_id ) || $site_id <= 0 ) { 1058 return false; 1059 } 1060 1061 $switched = is_multisite() ? switch_to_blog( $site_id ) : false; 1062 1063 $can = user_can( $user->ID, $capability, ...$args ); 1064 1065 if ( $switched ) { 1066 restore_current_blog(); 1067 } 1068 1069 return $can; 1070 } 1071 1072 /** 1073 * Retrieves the global WP_Roles instance and instantiates it if necessary. 1074 * 1075 * @since 4.3.0 1076 * 1077 * @global WP_Roles $wp_roles WordPress role management object. 1078 * 1079 * @return WP_Roles WP_Roles global instance if not already instantiated. 1080 */ 1081 function wp_roles() { 1082 global $wp_roles; 1083 1084 if ( ! isset( $wp_roles ) ) { 1085 $wp_roles = new WP_Roles(); 1086 } 1087 return $wp_roles; 1088 } 1089 1090 /** 1091 * Retrieves role object. 1092 * 1093 * @since 2.0.0 1094 * 1095 * @param string $role Role name. 1096 * @return WP_Role|null WP_Role object if found, null if the role does not exist. 1097 */ 1098 function get_role( $role ) { 1099 return wp_roles()->get_role( $role ); 1100 } 1101 1102 /** 1103 * Adds a role, if it does not exist. 1104 * 1105 * The list of capabilities can be passed either as a numerically indexed array of capability names, or an 1106 * associative array of boolean values keyed by the capability name. To explicitly deny the role a capability, set 1107 * the value for that capability to false. 1108 * 1109 * Examples: 1110 * 1111 * // Add a role that can edit posts. 1112 * add_role( 'custom_role', 'Custom Role', array( 1113 * 'read', 1114 * 'edit_posts', 1115 * ) ); 1116 * 1117 * Or, using an associative array: 1118 * 1119 * // Add a role that can edit posts but explicitly cannot not delete them. 1120 * add_role( 'custom_role', 'Custom Role', array( 1121 * 'read' => true, 1122 * 'edit_posts' => true, 1123 * 'delete_posts' => false, 1124 * ) ); 1125 * 1126 * @since 2.0.0 1127 * @since x.y.z Support was added for a numerically indexed array of strings for the capabilities array. 1128 * 1129 * @param string $role Role name. 1130 * @param string $display_name Display name for role. 1131 * @param array<string,bool>|array<int,string> $capabilities Capabilities to be added to the role. 1132 * Default empty array. 1133 * @return WP_Role|void WP_Role object, if the role is added. 1134 */ 1135 function add_role( $role, $display_name, $capabilities = array() ) { 1136 if ( empty( $role ) ) { 1137 return; 1138 } 1139 1140 return wp_roles()->add_role( $role, $display_name, $capabilities ); 1141 } 1142 1143 /** 1144 * Removes a role, if it exists. 1145 * 1146 * @since 2.0.0 1147 * 1148 * @param string $role Role name. 1149 */ 1150 function remove_role( $role ) { 1151 wp_roles()->remove_role( $role ); 1152 } 1153 1154 /** 1155 * Retrieves a list of super admins. 1156 * 1157 * @since 3.0.0 1158 * 1159 * @global array $super_admins 1160 * 1161 * @return string[] List of super admin logins. 1162 */ 1163 function get_super_admins() { 1164 global $super_admins; 1165 1166 if ( isset( $super_admins ) ) { 1167 return $super_admins; 1168 } else { 1169 return get_site_option( 'site_admins', array( 'admin' ) ); 1170 } 1171 } 1172 1173 /** 1174 * Determines whether user is a site admin. 1175 * 1176 * @since 3.0.0 1177 * 1178 * @param int|false $user_id Optional. The ID of a user. Defaults to false, to check the current user. 1179 * @return bool Whether the user is a site admin. 1180 */ 1181 function is_super_admin( $user_id = false ) { 1182 if ( ! $user_id ) { 1183 $user = wp_get_current_user(); 1184 } else { 1185 $user = get_userdata( $user_id ); 1186 } 1187 1188 if ( ! $user || ! $user->exists() ) { 1189 return false; 1190 } 1191 1192 if ( is_multisite() ) { 1193 $super_admins = get_super_admins(); 1194 if ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins, true ) ) { 1195 return true; 1196 } 1197 } elseif ( $user->has_cap( 'delete_users' ) ) { 1198 return true; 1199 } 1200 1201 return false; 1202 } 1203 1204 /** 1205 * Grants Super Admin privileges. 1206 * 1207 * @since 3.0.0 1208 * 1209 * @global array $super_admins 1210 * 1211 * @param int $user_id ID of the user to be granted Super Admin privileges. 1212 * @return bool True on success, false on failure. This can fail when the user is 1213 * already a super admin or when the `$super_admins` global is defined. 1214 */ 1215 function grant_super_admin( $user_id ) { 1216 // If global super_admins override is defined, there is nothing to do here. 1217 if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) { 1218 return false; 1219 } 1220 1221 /** 1222 * Fires before the user is granted Super Admin privileges. 1223 * 1224 * @since 3.0.0 1225 * 1226 * @param int $user_id ID of the user that is about to be granted Super Admin privileges. 1227 */ 1228 do_action( 'grant_super_admin', $user_id ); 1229 1230 // Directly fetch site_admins instead of using get_super_admins(). 1231 $super_admins = get_site_option( 'site_admins', array( 'admin' ) ); 1232 1233 $user = get_userdata( $user_id ); 1234 if ( $user && ! in_array( $user->user_login, $super_admins, true ) ) { 1235 $super_admins[] = $user->user_login; 1236 update_site_option( 'site_admins', $super_admins ); 1237 1238 /** 1239 * Fires after the user is granted Super Admin privileges. 1240 * 1241 * @since 3.0.0 1242 * 1243 * @param int $user_id ID of the user that was granted Super Admin privileges. 1244 */ 1245 do_action( 'granted_super_admin', $user_id ); 1246 return true; 1247 } 1248 return false; 1249 } 1250 1251 /** 1252 * Revokes Super Admin privileges. 1253 * 1254 * @since 3.0.0 1255 * 1256 * @global array $super_admins 1257 * 1258 * @param int $user_id ID of the user Super Admin privileges to be revoked from. 1259 * @return bool True on success, false on failure. This can fail when the user's email 1260 * is the network admin email or when the `$super_admins` global is defined. 1261 */ 1262 function revoke_super_admin( $user_id ) { 1263 // If global super_admins override is defined, there is nothing to do here. 1264 if ( isset( $GLOBALS['super_admins'] ) || ! is_multisite() ) { 1265 return false; 1266 } 1267 1268 /** 1269 * Fires before the user's Super Admin privileges are revoked. 1270 * 1271 * @since 3.0.0 1272 * 1273 * @param int $user_id ID of the user Super Admin privileges are being revoked from. 1274 */ 1275 do_action( 'revoke_super_admin', $user_id ); 1276 1277 // Directly fetch site_admins instead of using get_super_admins(). 1278 $super_admins = get_site_option( 'site_admins', array( 'admin' ) ); 1279 1280 $user = get_userdata( $user_id ); 1281 if ( $user && 0 !== strcasecmp( $user->user_email, get_site_option( 'admin_email' ) ) ) { 1282 $key = array_search( $user->user_login, $super_admins, true ); 1283 if ( false !== $key ) { 1284 unset( $super_admins[ $key ] ); 1285 update_site_option( 'site_admins', $super_admins ); 1286 1287 /** 1288 * Fires after the user's Super Admin privileges are revoked. 1289 * 1290 * @since 3.0.0 1291 * 1292 * @param int $user_id ID of the user Super Admin privileges were revoked from. 1293 */ 1294 do_action( 'revoked_super_admin', $user_id ); 1295 return true; 1296 } 1297 } 1298 return false; 1299 } 1300 1301 /** 1302 * Filters the user capabilities to grant the 'install_languages' capability as necessary. 1303 * 1304 * A user must have at least one out of the 'update_core', 'install_plugins', and 1305 * 'install_themes' capabilities to qualify for 'install_languages'. 1306 * 1307 * @since 4.9.0 1308 * 1309 * @param bool[] $allcaps An array of all the user's capabilities. 1310 * @return bool[] Filtered array of the user's capabilities. 1311 */ 1312 function wp_maybe_grant_install_languages_cap( $allcaps ) { 1313 if ( ! empty( $allcaps['update_core'] ) || ! empty( $allcaps['install_plugins'] ) || ! empty( $allcaps['install_themes'] ) ) { 1314 $allcaps['install_languages'] = true; 1315 } 1316 1317 return $allcaps; 1318 } 1319 1320 /** 1321 * Filters the user capabilities to grant the 'resume_plugins' and 'resume_themes' capabilities as necessary. 1322 * 1323 * @since 5.2.0 1324 * 1325 * @param bool[] $allcaps An array of all the user's capabilities. 1326 * @return bool[] Filtered array of the user's capabilities. 1327 */ 1328 function wp_maybe_grant_resume_extensions_caps( $allcaps ) { 1329 // Even in a multisite, regular administrators should be able to resume plugins. 1330 if ( ! empty( $allcaps['activate_plugins'] ) ) { 1331 $allcaps['resume_plugins'] = true; 1332 } 1333 1334 // Even in a multisite, regular administrators should be able to resume themes. 1335 if ( ! empty( $allcaps['switch_themes'] ) ) { 1336 $allcaps['resume_themes'] = true; 1337 } 1338 1339 return $allcaps; 1340 } 1341 1342 /** 1343 * Filters the user capabilities to grant the 'view_site_health_checks' capabilities as necessary. 1344 * 1345 * @since 5.2.2 1346 * 1347 * @param bool[] $allcaps An array of all the user's capabilities. 1348 * @param string[] $caps Required primitive capabilities for the requested capability. 1349 * @param array $args { 1350 * Arguments that accompany the requested capability check. 1351 * 1352 * @type string $0 Requested capability. 1353 * @type int $1 Concerned user ID. 1354 * @type mixed ...$2 Optional second and further parameters, typically object ID. 1355 * } 1356 * @param WP_User $user The user object. 1357 * @return bool[] Filtered array of the user's capabilities. 1358 */ 1359 function wp_maybe_grant_site_health_caps( $allcaps, $caps, $args, $user ) { 1360 if ( ! empty( $allcaps['install_plugins'] ) && ( ! is_multisite() || is_super_admin( $user->ID ) ) ) { 1361 $allcaps['view_site_health_checks'] = true; 1362 } 1363 1364 return $allcaps; 1365 } 1366 1367 return; 1368 1369 // Dummy gettext calls to get strings in the catalog. 1370 /* translators: User role for administrators. */ 1371 _x( 'Administrator', 'User role' ); 1372 /* translators: User role for editors. */ 1373 _x( 'Editor', 'User role' ); 1374 /* translators: User role for authors. */ 1375 _x( 'Author', 'User role' ); 1376 /* translators: User role for contributors. */ 1377 _x( 'Contributor', 'User role' ); 1378 /* translators: User role for subscribers. */ 1379 _x( 'Subscriber', 'User role' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Aug 13 08:20:01 2025 | Cross-referenced by PHPXref |