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. |
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 * |