wp/wp-includes/capabilities.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
    31  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    31  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
    32  *              by adding it to the function signature.
    32  *              by adding it to the function signature.
    33  * @since 5.7.0 Added the `create_app_password`, `list_app_passwords`, `read_app_password`,
    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`,
    34  *              `edit_app_password`, `delete_app_passwords`, `delete_app_password`,
    35  *              and `update_https` capabilities.
    35  *              and `update_https` capabilities.
       
    36  * @since 6.7.0 Added the `edit_block_binding` capability.
    36  *
    37  *
    37  * @global array $post_type_meta_caps Used to get post type meta capabilities.
    38  * @global array $post_type_meta_caps Used to get post type meta capabilities.
    38  *
    39  *
    39  * @param string $cap     Capability being checked.
    40  * @param string $cap     Capability being checked.
    40  * @param int    $user_id User ID.
    41  * @param int    $user_id User ID.
    45 	$caps = array();
    46 	$caps = array();
    46 
    47 
    47 	switch ( $cap ) {
    48 	switch ( $cap ) {
    48 		case 'remove_user':
    49 		case 'remove_user':
    49 			// In multisite the user must be a super admin to remove themselves.
    50 			// In multisite the user must be a super admin to remove themselves.
    50 			if ( isset( $args[0] ) && $user_id == $args[0] && ! is_super_admin( $user_id ) ) {
    51 			if ( isset( $args[0] ) && $user_id === (int) $args[0] && ! is_super_admin( $user_id ) ) {
    51 				$caps[] = 'do_not_allow';
    52 				$caps[] = 'do_not_allow';
    52 			} else {
    53 			} else {
    53 				$caps[] = 'remove_users';
    54 				$caps[] = 'remove_users';
    54 			}
    55 			}
    55 			break;
    56 			break;
    58 			$caps[] = 'promote_users';
    59 			$caps[] = 'promote_users';
    59 			break;
    60 			break;
    60 		case 'edit_user':
    61 		case 'edit_user':
    61 		case 'edit_users':
    62 		case 'edit_users':
    62 			// Allow user to edit themselves.
    63 			// Allow user to edit themselves.
    63 			if ( 'edit_user' === $cap && isset( $args[0] ) && $user_id == $args[0] ) {
    64 			if ( 'edit_user' === $cap && isset( $args[0] ) && $user_id === (int) $args[0] ) {
    64 				break;
    65 				break;
    65 			}
    66 			}
    66 
    67 
    67 			// In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
    68 			// In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin.
    68 			if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
    69 			if ( is_multisite() && ( ( ! is_super_admin( $user_id ) && 'edit_user' === $cap && is_super_admin( $args[0] ) ) || ! user_can( $user_id, 'manage_network_users' ) ) ) {
   101 			if ( 'revision' === $post->post_type ) {
   102 			if ( 'revision' === $post->post_type ) {
   102 				$caps[] = 'do_not_allow';
   103 				$caps[] = 'do_not_allow';
   103 				break;
   104 				break;
   104 			}
   105 			}
   105 
   106 
   106 			if ( ( get_option( 'page_for_posts' ) == $post->ID ) || ( get_option( 'page_on_front' ) == $post->ID ) ) {
   107 			if ( (int) get_option( 'page_for_posts' ) === $post->ID
       
   108 				|| (int) get_option( 'page_on_front' ) === $post->ID
       
   109 			) {
   107 				$caps[] = 'manage_options';
   110 				$caps[] = 'manage_options';
   108 				break;
   111 				break;
   109 			}
   112 			}
   110 
   113 
   111 			$post_type = get_post_type_object( $post->post_type );
   114 			$post_type = get_post_type_object( $post->post_type );
   135 				}
   138 				}
   136 				break;
   139 				break;
   137 			}
   140 			}
   138 
   141 
   139 			// If the post author is set and the user is the author...
   142 			// If the post author is set and the user is the author...
   140 			if ( $post->post_author && $user_id == $post->post_author ) {
   143 			if ( $post->post_author && $user_id === (int) $post->post_author ) {
   141 				// If the post is published or scheduled...
   144 				// If the post is published or scheduled...
   142 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
   145 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
   143 					$caps[] = $post_type->cap->delete_published_posts;
   146 					$caps[] = $post_type->cap->delete_published_posts;
   144 				} elseif ( 'trash' === $post->post_status ) {
   147 				} elseif ( 'trash' === $post->post_status ) {
   145 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
   148 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
   238 				}
   241 				}
   239 				break;
   242 				break;
   240 			}
   243 			}
   241 
   244 
   242 			// If the post author is set and the user is the author...
   245 			// If the post author is set and the user is the author...
   243 			if ( $post->post_author && $user_id == $post->post_author ) {
   246 			if ( $post->post_author && $user_id === (int) $post->post_author ) {
   244 				// If the post is published or scheduled...
   247 				// If the post is published or scheduled...
   245 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
   248 				if ( in_array( $post->post_status, array( 'publish', 'future' ), true ) ) {
   246 					$caps[] = $post_type->cap->edit_published_posts;
   249 					$caps[] = $post_type->cap->edit_published_posts;
   247 				} elseif ( 'trash' === $post->post_status ) {
   250 				} elseif ( 'trash' === $post->post_status ) {
   248 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
   251 					$status = get_post_meta( $post->ID, '_wp_trash_meta_status', true );
   360 			if ( $status_obj->public ) {
   363 			if ( $status_obj->public ) {
   361 				$caps[] = $post_type->cap->read;
   364 				$caps[] = $post_type->cap->read;
   362 				break;
   365 				break;
   363 			}
   366 			}
   364 
   367 
   365 			if ( $post->post_author && $user_id == $post->post_author ) {
   368 			if ( $post->post_author && $user_id === (int) $post->post_author ) {
   366 				$caps[] = $post_type->cap->read;
   369 				$caps[] = $post_type->cap->read;
   367 			} elseif ( $status_obj->private ) {
   370 			} elseif ( $status_obj->private ) {
   368 				$caps[] = $post_type->cap->read_private_posts;
   371 				$caps[] = $post_type->cap->read_private_posts;
   369 			} else {
   372 			} else {
   370 				$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
   373 				$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
   728 				$caps[] = 'do_not_allow';
   731 				$caps[] = 'do_not_allow';
   729 				break;
   732 				break;
   730 			}
   733 			}
   731 
   734 
   732 			if ( 'delete_term' === $cap
   735 			if ( 'delete_term' === $cap
   733 				&& ( get_option( 'default_' . $term->taxonomy ) == $term->term_id
   736 				&& ( (int) get_option( 'default_' . $term->taxonomy ) === $term->term_id
   734 					|| get_option( 'default_term_' . $term->taxonomy ) == $term->term_id )
   737 					|| (int) get_option( 'default_term_' . $term->taxonomy ) === $term->term_id )
   735 			) {
   738 			) {
   736 				$caps[] = 'do_not_allow';
   739 				$caps[] = 'do_not_allow';
   737 				break;
   740 				break;
   738 			}
   741 			}
   739 
   742 
   796 		case 'read_app_password':
   799 		case 'read_app_password':
   797 		case 'edit_app_password':
   800 		case 'edit_app_password':
   798 		case 'delete_app_passwords':
   801 		case 'delete_app_passwords':
   799 		case 'delete_app_password':
   802 		case 'delete_app_password':
   800 			$caps = map_meta_cap( 'edit_user', $user_id, $args[0] );
   803 			$caps = map_meta_cap( 'edit_user', $user_id, $args[0] );
       
   804 			break;
       
   805 		case 'edit_block_binding':
       
   806 			$block_editor_context = $args[0];
       
   807 			if ( isset( $block_editor_context->post ) ) {
       
   808 				$object_id = $block_editor_context->post->ID;
       
   809 			}
       
   810 			/*
       
   811 			 * If the post ID is null, check if the context is the site editor.
       
   812 			 * Fall back to the edit_theme_options in that case.
       
   813 			 */
       
   814 			if ( ! isset( $object_id ) ) {
       
   815 				if ( ! isset( $block_editor_context->name ) || 'core/edit-site' !== $block_editor_context->name ) {
       
   816 					$caps[] = 'do_not_allow';
       
   817 					break;
       
   818 				}
       
   819 				$caps = map_meta_cap( 'edit_theme_options', $user_id );
       
   820 				break;
       
   821 			}
       
   822 
       
   823 			$object_subtype = get_object_subtype( 'post', (int) $object_id );
       
   824 			if ( empty( $object_subtype ) ) {
       
   825 				$caps[] = 'do_not_allow';
       
   826 				break;
       
   827 			}
       
   828 			$post_type_object = get_post_type_object( $object_subtype );
       
   829 			// Initialize empty array if it doesn't exist.
       
   830 			if ( ! isset( $post_type_object->capabilities ) ) {
       
   831 				$post_type_object->capabilities = array();
       
   832 			}
       
   833 			$post_type_capabilities = get_post_type_capabilities( $post_type_object );
       
   834 			$caps                   = map_meta_cap( $post_type_capabilities->edit_post, $user_id, $object_id );
   801 			break;
   835 			break;
   802 		default:
   836 		default:
   803 			// Handle meta capabilities for custom post types.
   837 			// Handle meta capabilities for custom post types.
   804 			global $post_type_meta_caps;
   838 			global $post_type_meta_caps;
   805 			if ( isset( $post_type_meta_caps[ $cap ] ) ) {
   839 			if ( isset( $post_type_meta_caps[ $cap ] ) ) {
   882  *
   916  *
   883  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
   917  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
   884  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
   918  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
   885  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
   919  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
   886  *
   920  *
       
   921  * This function replaces the current_user_can_for_blog() function.
       
   922  *
   887  * Example usage:
   923  * Example usage:
   888  *
   924  *
   889  *     current_user_can_for_blog( $blog_id, 'edit_posts' );
   925  *     current_user_can_for_site( $site_id, 'edit_posts' );
   890  *     current_user_can_for_blog( $blog_id, 'edit_post', $post->ID );
   926  *     current_user_can_for_site( $site_id, 'edit_post', $post->ID );
   891  *     current_user_can_for_blog( $blog_id, 'edit_post_meta', $post->ID, $meta_key );
   927  *     current_user_can_for_site( $site_id, 'edit_post_meta', $post->ID, $meta_key );
   892  *
   928  *
   893  * @since 3.0.0
   929  * @since 6.7.0
   894  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
   930  *
   895  *              by adding it to the function signature.
   931  * @param int    $site_id    Site ID.
   896  * @since 5.8.0 Wraps current_user_can() after switching to blog.
       
   897  *
       
   898  * @param int    $blog_id    Site ID.
       
   899  * @param string $capability Capability name.
   932  * @param string $capability Capability name.
   900  * @param mixed  ...$args    Optional further parameters, typically starting with an object ID.
   933  * @param mixed  ...$args    Optional further parameters, typically starting with an object ID.
   901  * @return bool Whether the user has the given capability.
   934  * @return bool Whether the user has the given capability.
   902  */
   935  */
   903 function current_user_can_for_blog( $blog_id, $capability, ...$args ) {
   936 function current_user_can_for_site( $site_id, $capability, ...$args ) {
   904 	$switched = is_multisite() ? switch_to_blog( $blog_id ) : false;
   937 	$switched = is_multisite() ? switch_to_blog( $site_id ) : false;
   905 
   938 
   906 	$can = current_user_can( $capability, ...$args );
   939 	$can = current_user_can( $capability, ...$args );
   907 
   940 
   908 	if ( $switched ) {
   941 	if ( $switched ) {
   909 		restore_current_blog();
   942 		restore_current_blog();
   981 		$user = new WP_User( 0 );
  1014 		$user = new WP_User( 0 );
   982 		$user->init( new stdClass() );
  1015 		$user->init( new stdClass() );
   983 	}
  1016 	}
   984 
  1017 
   985 	return $user->has_cap( $capability, ...$args );
  1018 	return $user->has_cap( $capability, ...$args );
       
  1019 }
       
  1020 
       
  1021 /**
       
  1022  * Returns whether a particular user has the specified capability for a given site.
       
  1023  *
       
  1024  * This function also accepts an ID of an object to check against if the capability is a meta capability. Meta
       
  1025  * capabilities such as `edit_post` and `edit_user` are capabilities used by the `map_meta_cap()` function to
       
  1026  * map to primitive capabilities that a user or role has, such as `edit_posts` and `edit_others_posts`.
       
  1027  *
       
  1028  * Example usage:
       
  1029  *
       
  1030  *     user_can_for_site( $user->ID, $site_id, 'edit_posts' );
       
  1031  *     user_can_for_site( $user->ID, $site_id, 'edit_post', $post->ID );
       
  1032  *     user_can_for_site( $user->ID, $site_id, 'edit_post_meta', $post->ID, $meta_key );
       
  1033  *
       
  1034  * @since 6.7.0
       
  1035  *
       
  1036  * @param int|WP_User $user       User ID or object.
       
  1037  * @param int         $site_id    Site ID.
       
  1038  * @param string      $capability Capability name.
       
  1039  * @param mixed       ...$args    Optional further parameters, typically starting with an object ID.
       
  1040  * @return bool Whether the user has the given capability.
       
  1041  */
       
  1042 function user_can_for_site( $user, $site_id, $capability, ...$args ) {
       
  1043 	if ( ! is_object( $user ) ) {
       
  1044 		$user = get_userdata( $user );
       
  1045 	}
       
  1046 
       
  1047 	if ( empty( $user ) ) {
       
  1048 		// User is logged out, create anonymous user object.
       
  1049 		$user = new WP_User( 0 );
       
  1050 		$user->init( new stdClass() );
       
  1051 	}
       
  1052 
       
  1053 	// Check if the blog ID is valid.
       
  1054 	if ( ! is_numeric( $site_id ) || $site_id <= 0 ) {
       
  1055 		return false;
       
  1056 	}
       
  1057 
       
  1058 	$switched = is_multisite() ? switch_to_blog( $site_id ) : false;
       
  1059 
       
  1060 	$can = user_can( $user->ID, $capability, ...$args );
       
  1061 
       
  1062 	if ( $switched ) {
       
  1063 		restore_current_blog();
       
  1064 	}
       
  1065 
       
  1066 	return $can;
   986 }
  1067 }
   987 
  1068 
   988 /**
  1069 /**
   989  * Retrieves the global WP_Roles instance and instantiates it if necessary.
  1070  * Retrieves the global WP_Roles instance and instantiates it if necessary.
   990  *
  1071  *