Example #1
0
/**
 * 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);
}
Example #3
0
/**
 * 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);
}