[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

title

Body

[close]

/wp-includes/ -> capabilities.php (source)

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


Generated: Sat Nov 23 20:47:33 2019 Cross-referenced by PHPXref 0.7