/** * Builds an object with all post type capabilities out of a post type object * * Post type capabilities use the 'capability_type' argument as a base, if the * capability is not set in the 'capabilities' argument array or if the * 'capabilities' argument is not supplied. * * The capability_type argument can optionally be registered as an array, with * the first value being singular and the second plural, e.g. array('story, 'stories') * Otherwise, an 's' will be added to the value for the plural form. After * registration, capability_type will always be a string of the singular value. * * By default, seven keys are accepted as part of the capabilities array: * * - edit_post, read_post, and delete_post are meta capabilities, which are then * generally mapped to corresponding primitive capabilities depending on the * context, which would be the post being edited/read/deleted and the user or * role being checked. Thus these capabilities would generally not be granted * directly to users or roles. * * - edit_posts - Controls whether objects of this post type can be edited. * - edit_others_posts - Controls whether objects of this type owned by other users * can be edited. If the post type does not support an author, then this will * behave like edit_posts. * - publish_posts - Controls publishing objects of this post type. * - read_private_posts - Controls whether private objects can be read. * These four primitive capabilities are checked in core in various locations. * There are also seven other primitive capabilities which are not referenced * directly in core, except in map_meta_cap(), which takes the three aforementioned * meta capabilities and translates them into one or more primitive capabilities * that must then be checked against the user or role, depending on the context. * * - read - Controls whether objects of this post type can be read. * - delete_posts - Controls whether objects of this post type can be deleted. * - delete_private_posts - Controls whether private objects can be deleted. * - delete_published_posts - Controls whether published objects can be deleted. * - delete_others_posts - Controls whether objects owned by other users can be * can be deleted. If the post type does not support an author, then this will * behave like delete_posts. * - edit_private_posts - Controls whether private objects can be edited. * - edit_published_posts - Controls whether published objects can be deleted. * * These additional capabilities are only used in map_meta_cap(). Thus, they are * only assigned by default if the post type is registered with the 'map_meta_cap' * argument set to true (default is false). * * @see map_meta_cap() * @since 3.0.0 * * @param object $args Post type registration arguments * @return object object with all the capabilities as member variables */ function get_post_type_capabilities($args) { if (!is_array($args->capability_type)) { $args->capability_type = array($args->capability_type, $args->capability_type . 's'); } // Singular base for meta capabilities, plural base for primitive capabilities. list($singular_base, $plural_base) = $args->capability_type; $default_capabilities = array('edit_post' => 'edit_' . $singular_base, 'read_post' => 'read_' . $singular_base, 'delete_post' => 'delete_' . $singular_base, 'edit_posts' => 'edit_' . $plural_base, 'edit_others_posts' => 'edit_others_' . $plural_base, 'publish_posts' => 'publish_' . $plural_base, 'read_private_posts' => 'read_private_' . $plural_base); // Primitive capabilities used within map_meta_cap(): if ($args->map_meta_cap) { $default_capabilities_for_mapping = array('read' => 'read', 'delete_posts' => 'delete_' . $plural_base, 'delete_private_posts' => 'delete_private_' . $plural_base, 'delete_published_posts' => 'delete_published_' . $plural_base, 'delete_others_posts' => 'delete_others_' . $plural_base, 'edit_private_posts' => 'edit_private_' . $plural_base, 'edit_published_posts' => 'edit_published_' . $plural_base); $default_capabilities = array_merge($default_capabilities, $default_capabilities_for_mapping); } $capabilities = array_merge($default_capabilities, $args->capabilities); // Remember meta capabilities for future reference. if ($args->map_meta_cap) { _post_type_meta_capabilities($capabilities); } return (object) $capabilities; }
/** * Map meta capabilities to primitive capabilities. * * This does not actually compare whether the user ID has the actual capability, * just what the capability or capabilities are. Meta capability list value can * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. * * @since 2.0.0 * * @param string $cap Capability name. * @param int $user_id User ID. * @return array Actual capabilities for meta capability. */ function map_meta_cap($cap, $user_id) { $args = array_slice(func_get_args(), 2); $caps = array(); switch ($cap) { case 'remove_user': $caps[] = 'remove_users'; break; case 'promote_user': $caps[] = 'promote_users'; break; case 'edit_user': case 'edit_users': // Allow user to edit itself if ('edit_user' == $cap && isset($args[0]) && $user_id == $args[0]) { break; } // In multisite the user must have manage_network_users caps. If editing a super admin, the user must be a super admin. if (is_multisite() && (!is_super_admin($user_id) && 'edit_user' === $cap && is_super_admin($args[0]) || !user_can($user_id, 'manage_network_users'))) { $caps[] = 'do_not_allow'; } else { $caps[] = 'edit_users'; // edit_user maps to edit_users. } break; case 'delete_post': case 'delete_page': $post = get_post($args[0]); if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type) { /* translators: 1: post type, 2: capability name */ _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'); $caps[] = 'edit_others_posts'; break; } if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('delete_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } // If the post author is set and the user is the author... if ($post->post_author && $user_id == $post->post_author) { // If the post is published... if ('publish' == $post->post_status) { $caps[] = $post_type->cap->delete_published_posts; } elseif ('trash' == $post->post_status) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true)) { $caps[] = $post_type->cap->delete_published_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->delete_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->delete_others_posts; // The post is published, extra cap required. if ('publish' == $post->post_status) { $caps[] = $post_type->cap->delete_published_posts; } elseif ('private' == $post->post_status) { $caps[] = $post_type->cap->delete_private_posts; } } break; // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts case 'edit_post': case 'edit_page': $post = get_post($args[0]); if (empty($post)) { $caps[] = 'do_not_allow'; break; } if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type) { /* translators: 1: post type, 2: capability name */ _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'); $caps[] = 'edit_others_posts'; break; } if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('edit_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } // If the post author is set and the user is the author... if ($post->post_author && $user_id == $post->post_author) { // If the post is published... if ('publish' == $post->post_status) { $caps[] = $post_type->cap->edit_published_posts; } elseif ('trash' == $post->post_status) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true)) { $caps[] = $post_type->cap->edit_published_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->edit_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; // The post is published, extra cap required. if ('publish' == $post->post_status) { $caps[] = $post_type->cap->edit_published_posts; } elseif ('private' == $post->post_status) { $caps[] = $post_type->cap->edit_private_posts; } } break; case 'read_post': case 'read_page': $post = get_post($args[0]); if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type) { /* translators: 1: post type, 2: capability name */ _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'); $caps[] = 'edit_others_posts'; break; } if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('read_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } $status_obj = get_post_status_object($post->post_status); if ($status_obj->public) { $caps[] = $post_type->cap->read; break; } if ($post->post_author && $user_id == $post->post_author) { $caps[] = $post_type->cap->read; } elseif ($status_obj->private) { $caps[] = $post_type->cap->read_private_posts; } else { $caps = map_meta_cap('edit_post', $user_id, $post->ID); } break; case 'publish_post': $post = get_post($args[0]); $post_type = get_post_type_object($post->post_type); if (!$post_type) { /* translators: 1: post type, 2: capability name */ _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'); $caps[] = 'edit_others_posts'; break; } $caps[] = $post_type->cap->publish_posts; break; case 'edit_post_meta': case 'delete_post_meta': case 'add_post_meta': $post = get_post($args[0]); $caps = map_meta_cap('edit_post', $user_id, $post->ID); $meta_key = isset($args[1]) ? $args[1] : false; if ($meta_key && has_filter("auth_post_meta_{$meta_key}")) { /** * Filter whether the user is allowed to add post meta to a post. * * The dynamic portion of the hook name, `$meta_key`, refers to the * meta key passed to {@see map_meta_cap()}. * * @since 3.3.0 * * @param bool $allowed Whether the user can add the post meta. Default false. * @param string $meta_key The meta key. * @param int $post_id Post ID. * @param int $user_id User ID. * @param string $cap Capability name. * @param array $caps User capabilities. */ $allowed = apply_filters("auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps); if (!$allowed) { $caps[] = $cap; } } elseif ($meta_key && is_protected_meta($meta_key, 'post')) { $caps[] = $cap; } break; case 'edit_comment': $comment = get_comment($args[0]); if (empty($comment)) { break; } $post = get_post($comment->comment_post_ID); /* * If the post doesn't exist, we have an orphaned comment. * Fall back to the edit_posts capability, instead. */ if ($post) { $caps = map_meta_cap('edit_post', $user_id, $post->ID); } else { $caps = map_meta_cap('edit_posts', $user_id); } break; case 'unfiltered_upload': if (defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && (!is_multisite() || is_super_admin($user_id))) { $caps[] = $cap; } else { $caps[] = 'do_not_allow'; } break; case 'unfiltered_html': // Disallow unfiltered_html for all users, even admins and super admins. if (defined('DISALLOW_UNFILTERED_HTML') && DISALLOW_UNFILTERED_HTML) { $caps[] = 'do_not_allow'; } elseif (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } else { $caps[] = $cap; } break; case 'edit_files': case 'edit_plugins': case 'edit_themes': // Disallow the file editors. if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT) { $caps[] = 'do_not_allow'; } elseif (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { $caps[] = 'do_not_allow'; } elseif (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } else { $caps[] = $cap; } break; case 'update_plugins': case 'delete_plugins': case 'install_plugins': case 'upload_plugins': case 'update_themes': case 'delete_themes': case 'install_themes': case 'upload_themes': case 'update_core': // Disallow anything that creates, deletes, or updates core, plugin, or theme files. // Files in uploads are excepted. if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { $caps[] = 'do_not_allow'; } elseif (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } elseif ('upload_themes' === $cap) { $caps[] = 'install_themes'; } elseif ('upload_plugins' === $cap) { $caps[] = 'install_plugins'; } else { $caps[] = $cap; } break; case 'activate_plugins': $caps[] = $cap; if (is_multisite()) { // update_, install_, and delete_ are handled above with is_super_admin(). $menu_perms = get_site_option('menu_items', array()); if (empty($menu_perms['plugins'])) { $caps[] = 'manage_network_plugins'; } } break; case 'delete_user': case 'delete_users': // If multisite only super admins can delete users. if (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } else { $caps[] = 'delete_users'; } // delete_user maps to delete_users. break; case 'create_users': if (!is_multisite()) { $caps[] = $cap; } elseif (is_super_admin($user_id) || get_site_option('add_new_users')) { $caps[] = $cap; } else { $caps[] = 'do_not_allow'; } break; case 'manage_links': if (get_option('link_manager_enabled')) { $caps[] = $cap; } else { $caps[] = 'do_not_allow'; } break; case 'customize': $caps[] = 'edit_theme_options'; break; case 'delete_site': $caps[] = 'manage_options'; break; default: // Handle meta capabilities for custom post types. $post_type_meta_caps = _post_type_meta_capabilities(); if (isset($post_type_meta_caps[$cap])) { $args = array_merge(array($post_type_meta_caps[$cap], $user_id), $args); return call_user_func_array('map_meta_cap', $args); } // If no meta caps match, return the original cap. $caps[] = $cap; } /** * Filter a user's capabilities depending on specific context and/or privilege. * * @since 2.8.0 * * @param array $caps Returns the user's actual capabilities. * @param string $cap Capability name. * @param int $user_id The user ID. * @param array $args Adds the context to the cap. Typically the object ID. */ return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args); }
/** * Build an object with all post type capabilities out of a post type object * * Post type capabilities use the 'capability_type' argument as a base, if the * capability is not set in the 'capabilities' argument array or if the * 'capabilities' argument is not supplied. * * The capability_type argument can optionally be registered as an array, with * the first value being singular and the second plural, e.g. array('story, 'stories') * Otherwise, an 's' will be added to the value for the plural form. After * registration, capability_type will always be a string of the singular value. * * By default, seven keys are accepted as part of the capabilities array: * * - edit_post, read_post, and delete_post are meta capabilities, which are then * generally mapped to corresponding primitive capabilities depending on the * context, which would be the post being edited/read/deleted and the user or * role being checked. Thus these capabilities would generally not be granted * directly to users or roles. * * - edit_posts - Controls whether objects of this post type can be edited. * - edit_others_posts - Controls whether objects of this type owned by other users * can be edited. If the post type does not support an author, then this will * behave like edit_posts. * - publish_posts - Controls publishing objects of this post type. * - read_private_posts - Controls whether private objects can be read. * * These four primitive capabilities are checked in core in various locations. * There are also seven other primitive capabilities which are not referenced * directly in core, except in map_meta_cap(), which takes the three aforementioned * meta capabilities and translates them into one or more primitive capabilities * that must then be checked against the user or role, depending on the context. * * - read - Controls whether objects of this post type can be read. * - delete_posts - Controls whether objects of this post type can be deleted. * - delete_private_posts - Controls whether private objects can be deleted. * - delete_published_posts - Controls whether published objects can be deleted. * - delete_others_posts - Controls whether objects owned by other users can be * can be deleted. If the post type does not support an author, then this will * behave like delete_posts. * - edit_private_posts - Controls whether private objects can be edited. * - edit_published_posts - Controls whether published objects can be edited. * * These additional capabilities are only used in map_meta_cap(). Thus, they are * only assigned by default if the post type is registered with the 'map_meta_cap' * argument set to true (default is false). * * @since 3.0.0 * * @see register_post_type() * @see map_meta_cap() * * @param object $args Post type registration arguments. * @return object object with all the capabilities as member variables. */ function get_post_type_capabilities( $args ) { if ( ! is_array( $args->capability_type ) ) $args->capability_type = array( $args->capability_type, $args->capability_type . 's' ); // Singular base for meta capabilities, plural base for primitive capabilities. list( $singular_base, $plural_base ) = $args->capability_type; $default_capabilities = array( // Meta capabilities 'edit_post' => 'edit_' . $singular_base, 'read_post' => 'read_' . $singular_base, 'delete_post' => 'delete_' . $singular_base, // Primitive capabilities used outside of map_meta_cap(): 'edit_posts' => 'edit_' . $plural_base, 'edit_others_posts' => 'edit_others_' . $plural_base, 'publish_posts' => 'publish_' . $plural_base, 'read_private_posts' => 'read_private_' . $plural_base, ); // Primitive capabilities used within map_meta_cap(): if ( $args->map_meta_cap ) { $default_capabilities_for_mapping = array( 'read' => 'read', 'delete_posts' => 'delete_' . $plural_base, 'delete_private_posts' => 'delete_private_' . $plural_base, 'delete_published_posts' => 'delete_published_' . $plural_base, 'delete_others_posts' => 'delete_others_' . $plural_base, 'edit_private_posts' => 'edit_private_' . $plural_base, 'edit_published_posts' => 'edit_published_' . $plural_base, ); $default_capabilities = array_merge( $default_capabilities, $default_capabilities_for_mapping ); } $capabilities = array_merge( $default_capabilities, $args->capabilities ); // Post creation capability simply maps to edit_posts by default: if ( ! isset( $capabilities['create_posts'] ) ) $capabilities['create_posts'] = $capabilities['edit_posts']; // Remember meta capabilities for future reference. if ( $args->map_meta_cap ) _post_type_meta_capabilities( $capabilities ); return (object) $capabilities; }
/** * Map meta capabilities to primitive capabilities. * * This does not actually compare whether the user ID has the actual capability, * just what the capability or capabilities are. Meta capability list value can * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. * * @since 2.0.0 * * @param string $cap Capability name. * @param int $user_id User ID. * @return array Actual capabilities for meta capability. */ function map_meta_cap($cap, $user_id) { $args = array_slice(func_get_args(), 2); $caps = array(); switch ($cap) { case 'remove_user': $caps[] = 'remove_users'; break; case 'promote_user': $caps[] = 'promote_users'; break; case 'edit_user': // Allow user to edit itself if (isset($args[0]) && $user_id == $args[0]) { break; } // Fall through // Fall through case 'edit_users': // If multisite these caps are allowed only for super admins. if (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } else { $caps[] = 'edit_users'; } // Explicit due to primitive fall through break; case 'delete_post': case 'delete_page': $author_data = get_userdata($user_id); $post = get_post($args[0]); if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('delete_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } if ('' != $post->post_author) { $post_author_data = get_userdata($post->post_author); } else { // No author set yet, so default to current user for cap checks. $post_author_data = $author_data; } // If the user is the author... if (is_object($post_author_data) && $user_id == $post_author_data->ID) { // If the post is published... if ('publish' == $post->post_status) { $caps[] = $post_type->cap->delete_published_posts; } elseif ('trash' == $post->post_status) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true)) { $caps[] = $post_type->cap->delete_published_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->delete_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->delete_others_posts; // The post is published, extra cap required. if ('publish' == $post->post_status) { $caps[] = $post_type->cap->delete_published_posts; } elseif ('private' == $post->post_status) { $caps[] = $post_type->cap->delete_private_posts; } } break; // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts case 'edit_post': case 'edit_page': $author_data = get_userdata($user_id); $post = get_post($args[0]); if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('edit_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } if ('' != $post->post_author) { $post_author_data = get_userdata($post->post_author); } else { // No author set yet, so default to current user for cap checks. $post_author_data = $author_data; } //echo "current user id : $user_id, post author id: " . $post_author_data->ID . "<br />"; // If the user is the author... if (is_object($post_author_data) && $user_id == $post_author_data->ID) { // If the post is published... if ('publish' == $post->post_status) { $caps[] = $post_type->cap->edit_published_posts; } elseif ('trash' == $post->post_status) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true)) { $caps[] = $post_type->cap->edit_published_posts; } } else { // If the post is draft... $caps[] = $post_type->cap->edit_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; // The post is published, extra cap required. if ('publish' == $post->post_status) { $caps[] = $post_type->cap->edit_published_posts; } elseif ('private' == $post->post_status) { $caps[] = $post_type->cap->edit_private_posts; } } break; case 'read_post': case 'read_page': $author_data = get_userdata($user_id); $post = get_post($args[0]); if ('revision' == $post->post_type) { $post = get_post($post->post_parent); } $post_type = get_post_type_object($post->post_type); if (!$post_type->map_meta_cap) { $caps[] = $post_type->cap->{$cap}; // Prior to 3.1 we would re-call map_meta_cap here. if ('read_post' == $cap) { $cap = $post_type->cap->{$cap}; } break; } $status_obj = get_post_status_object($post->post_status); if ($status_obj->public) { $caps[] = $post_type->cap->read; break; } if ('' != $post->post_author) { $post_author_data = get_userdata($post->post_author); } else { // No author set yet, so default to current user for cap checks. $post_author_data = $author_data; } if (is_object($post_author_data) && $user_id == $post_author_data->ID) { $caps[] = $post_type->cap->read; } elseif ($status_obj->private) { $caps[] = $post_type->cap->read_private_posts; } else { $caps = map_meta_cap('edit_post', $user_id, $post->ID); } break; case 'edit_post_meta': case 'delete_post_meta': case 'add_post_meta': $post = get_post($args[0]); $post_type_object = get_post_type_object($post->post_type); $caps = map_meta_cap($post_type_object->cap->edit_post, $user_id, $post->ID); $meta_key = isset($args[1]) ? $args[1] : false; if ($meta_key && has_filter("auth_post_meta_{$meta_key}")) { $allowed = apply_filters("auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps); if (!$allowed) { $caps[] = $cap; } } elseif ($meta_key && is_protected_meta($meta_key, 'post')) { $caps[] = $cap; } break; case 'edit_comment': $comment = get_comment($args[0]); $post = get_post($comment->comment_post_ID); $post_type_object = get_post_type_object($post->post_type); $caps = map_meta_cap($post_type_object->cap->edit_post, $user_id, $post->ID); break; case 'unfiltered_upload': if (defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && (!is_multisite() || is_super_admin($user_id))) { $caps[] = $cap; } else { $caps[] = 'do_not_allow'; } break; case 'edit_files': case 'edit_plugins': case 'edit_themes': if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT) { $caps[] = 'do_not_allow'; break; } // Fall through if not DISALLOW_FILE_EDIT. // Fall through if not DISALLOW_FILE_EDIT. case 'update_plugins': case 'delete_plugins': case 'install_plugins': case 'update_themes': case 'delete_themes': case 'install_themes': case 'update_core': // Disallow anything that creates, deletes, or edits core, plugin, or theme files. // Files in uploads are excepted. if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) { $caps[] = 'do_not_allow'; break; } // Fall through if not DISALLOW_FILE_MODS. // Fall through if not DISALLOW_FILE_MODS. case 'unfiltered_html': // Disallow unfiltered_html for all users, even admins and super admins. if (defined('DISALLOW_UNFILTERED_HTML') && DISALLOW_UNFILTERED_HTML) { $caps[] = 'do_not_allow'; break; } // Fall through if not DISALLOW_UNFILTERED_HTML // Fall through if not DISALLOW_UNFILTERED_HTML case 'delete_user': case 'delete_users': // If multisite these caps are allowed only for super admins. if (is_multisite() && !is_super_admin($user_id)) { $caps[] = 'do_not_allow'; } else { if ('delete_user' == $cap) { $cap = 'delete_users'; } $caps[] = $cap; } break; case 'create_users': if (!is_multisite()) { $caps[] = $cap; } elseif (is_super_admin() || get_site_option('add_new_users')) { $caps[] = $cap; } else { $caps[] = 'do_not_allow'; } break; default: // Handle meta capabilities for custom post types. $post_type_meta_caps = _post_type_meta_capabilities(); if (isset($post_type_meta_caps[$cap])) { $args = array_merge(array($post_type_meta_caps[$cap], $user_id), $args); return call_user_func_array('map_meta_cap', $args); } // If no meta caps match, return the original cap. $caps[] = $cap; } return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args); }
/** * Map meta capabilities to primitive capabilities. * * This does not actually compare whether the user ID has the actual capability, * just what the capability or capabilities are. Meta capability list value can * be 'delete_user', 'edit_user', 'remove_user', 'promote_user', 'delete_post', * 'delete_page', 'edit_post', 'edit_page', 'read_post', or 'read_page'. * * @since 2.0.0 * * @param string $cap Capability name. * @param int $user_id User ID. * @return array Actual capabilities for meta capability. */ function map_meta_cap( $cap, $user_id ) { $args = array_slice( func_get_args(), 2 ); $caps = array(); switch ( $cap ) { case 'remove_user': $caps[] = 'remove_users'; break; case 'promote_user': $caps[] = 'promote_users'; break; case 'edit_user': case 'edit_users': // Allow user to edit itself if ( 'edit_user' == $cap && isset( $args[0] ) && $user_id == $args[0] ) break; // If multisite these caps are allowed only for super admins. if ( is_multisite() && !is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = 'edit_users'; // edit_user maps to edit_users. break; case 'delete_post': case 'delete_page': $post = get_post( $args[0] ); if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'delete_post' == $cap ) $cap = $post_type->cap->$cap; break; } $post_author_id = $post->post_author; // If no author set yet, default to current user for cap checks. if ( ! $post_author_id ) $post_author_id = $user_id; // If the user is the author... if ( $user_id == $post_author_id ) { // If the post is published... if ( 'publish' == $post->post_status ) { $caps[] = $post_type->cap->delete_published_posts; } elseif ( 'trash' == $post->post_status ) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) $caps[] = $post_type->cap->delete_published_posts; } else { // If the post is draft... $caps[] = $post_type->cap->delete_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->delete_others_posts; // The post is published, extra cap required. if ( 'publish' == $post->post_status ) $caps[] = $post_type->cap->delete_published_posts; elseif ( 'private' == $post->post_status ) $caps[] = $post_type->cap->delete_private_posts; } break; // edit_post breaks down to edit_posts, edit_published_posts, or // edit_others_posts case 'edit_post': case 'edit_page': $post = get_post( $args[0] ); if ( empty( $post ) ) break; if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'edit_post' == $cap ) $cap = $post_type->cap->$cap; break; } $post_author_id = $post->post_author; // If no author set yet, default to current user for cap checks. if ( ! $post_author_id ) $post_author_id = $user_id; // If the user is the author... if ( $user_id == $post_author_id ) { // If the post is published... if ( 'publish' == $post->post_status ) { $caps[] = $post_type->cap->edit_published_posts; } elseif ( 'trash' == $post->post_status ) { if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) ) $caps[] = $post_type->cap->edit_published_posts; } else { // If the post is draft... $caps[] = $post_type->cap->edit_posts; } } else { // The user is trying to edit someone else's post. $caps[] = $post_type->cap->edit_others_posts; // The post is published, extra cap required. if ( 'publish' == $post->post_status ) $caps[] = $post_type->cap->edit_published_posts; elseif ( 'private' == $post->post_status ) $caps[] = $post_type->cap->edit_private_posts; } break; case 'read_post': case 'read_page': $post = get_post( $args[0] ); if ( 'revision' == $post->post_type ) { $post = get_post( $post->post_parent ); } $post_type = get_post_type_object( $post->post_type ); if ( ! $post_type->map_meta_cap ) { $caps[] = $post_type->cap->$cap; // Prior to 3.1 we would re-call map_meta_cap here. if ( 'read_post' == $cap ) $cap = $post_type->cap->$cap; break; } $status_obj = get_post_status_object( $post->post_status ); if ( $status_obj->public ) { $caps[] = $post_type->cap->read; break; } $post_author_id = $post->post_author; // If no author set yet, default to current user for cap checks. if ( ! $post_author_id ) $post_author_id = $user_id; if ( $user_id == $post_author_id ) $caps[] = $post_type->cap->read; elseif ( $status_obj->private ) $caps[] = $post_type->cap->read_private_posts; else $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); break; case 'publish_post': $post = get_post( $args[0] ); $post_type = get_post_type_object( $post->post_type ); $caps[] = $post_type->cap->publish_posts; break; case 'edit_post_meta': case 'delete_post_meta': case 'add_post_meta': $post = get_post( $args[0] ); $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); $meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false; if ( $meta_key && has_filter( "auth_post_meta_{$meta_key}" ) ) { $allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps ); if ( ! $allowed ) $caps[] = $cap; } elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) { $caps[] = $cap; } break; case 'edit_comment': $comment = get_comment( $args[0] ); if ( empty( $comment ) ) break; $post = get_post( $comment->comment_post_ID ); $caps = map_meta_cap( 'edit_post', $user_id, $post->ID ); break; case 'unfiltered_upload': if ( defined('ALLOW_UNFILTERED_UPLOADS') && ALLOW_UNFILTERED_UPLOADS && ( !is_multisite() || is_super_admin( $user_id ) ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; case 'unfiltered_html' : // Disallow unfiltered_html for all users, even admins and super admins. if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) $caps[] = 'do_not_allow'; elseif ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = $cap; break; case 'edit_files': case 'edit_plugins': case 'edit_themes': // Disallow the file editors. if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) $caps[] = 'do_not_allow'; elseif ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) $caps[] = 'do_not_allow'; elseif ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = $cap; break; case 'update_plugins': case 'delete_plugins': case 'install_plugins': case 'update_themes': case 'delete_themes': case 'install_themes': case 'update_core': // Disallow anything that creates, deletes, or updates core, plugin, or theme files. // Files in uploads are excepted. if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) $caps[] = 'do_not_allow'; elseif ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = $cap; break; case 'activate_plugins': $caps[] = $cap; if ( is_multisite() ) { // update_, install_, and delete_ are handled above with is_super_admin(). $menu_perms = get_site_option( 'menu_items', array() ); if ( empty( $menu_perms['plugins'] ) ) $caps[] = 'manage_network_plugins'; } break; case 'delete_user': case 'delete_users': // If multisite only super admins can delete users. if ( is_multisite() && ! is_super_admin( $user_id ) ) $caps[] = 'do_not_allow'; else $caps[] = 'delete_users'; // delete_user maps to delete_users. break; case 'create_users': if ( !is_multisite() ) $caps[] = $cap; elseif ( is_super_admin() || get_site_option( 'add_new_users' ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; case 'manage_links' : if ( get_option( 'link_manager_enabled' ) ) $caps[] = $cap; else $caps[] = 'do_not_allow'; break; default: // Handle meta capabilities for custom post types. $post_type_meta_caps = _post_type_meta_capabilities(); if ( isset( $post_type_meta_caps[ $cap ] ) ) { $args = array_merge( array( $post_type_meta_caps[ $cap ], $user_id ), $args ); return call_user_func_array( 'map_meta_cap', $args ); } // If no meta caps match, return the original cap. $caps[] = $cap; } return apply_filters('map_meta_cap', $caps, $cap, $user_id, $args); }