Rough first pass on map_meta_cap for custom post types. see #14122.
git-svn-id: http://svn.automattic.com/wordpress/trunk@15890 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
c202d85e48
commit
d27f272247
|
@ -817,11 +817,12 @@ function map_meta_cap( $cap, $user_id ) {
|
||||||
$caps[] = 'edit_users'; // Explicit due to primitive fall through
|
$caps[] = 'edit_users'; // Explicit due to primitive fall through
|
||||||
break;
|
break;
|
||||||
case 'delete_post':
|
case 'delete_post':
|
||||||
|
case 'delete_page':
|
||||||
$author_data = get_userdata( $user_id );
|
$author_data = get_userdata( $user_id );
|
||||||
//echo "post ID: {$args[0]}<br />";
|
//echo "post ID: {$args[0]}<br />";
|
||||||
$post = get_post( $args[0] );
|
$post = get_post( $args[0] );
|
||||||
$post_type = get_post_type_object( $post->post_type );
|
$post_type = get_post_type_object( $post->post_type );
|
||||||
if ( $post_type && 'post' != $post_type->capability_type ) {
|
if ( 'delete_post' == $cap && $post_type && 'post' != $post_type->capability_type && ! $post_type->map_meta_cap ) {
|
||||||
$args = array_merge( array( $post_type->cap->delete_post, $user_id ), $args );
|
$args = array_merge( array( $post_type->cap->delete_post, $user_id ), $args );
|
||||||
return call_user_func_array( 'map_meta_cap', $args );
|
return call_user_func_array( 'map_meta_cap', $args );
|
||||||
}
|
}
|
||||||
|
@ -837,69 +838,34 @@ function map_meta_cap( $cap, $user_id ) {
|
||||||
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
|
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
|
||||||
// If the post is published...
|
// If the post is published...
|
||||||
if ( 'publish' == $post->post_status ) {
|
if ( 'publish' == $post->post_status ) {
|
||||||
$caps[] = 'delete_published_posts';
|
$caps[] = $post_type->cap->delete_published_posts;
|
||||||
} elseif ( 'trash' == $post->post_status ) {
|
} elseif ( 'trash' == $post->post_status ) {
|
||||||
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
|
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
|
||||||
$caps[] = 'delete_published_posts';
|
$caps[] = $post_type->cap->delete_published_posts;
|
||||||
} else {
|
} else {
|
||||||
// If the post is draft...
|
// If the post is draft...
|
||||||
$caps[] = 'delete_posts';
|
$caps[] = $post_type->cap->delete_posts;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The user is trying to edit someone else's post.
|
// The user is trying to edit someone else's post.
|
||||||
$caps[] = 'delete_others_posts';
|
$caps[] = $post_type->cap->delete_others_posts;
|
||||||
// The post is published, extra cap required.
|
// The post is published, extra cap required.
|
||||||
if ( 'publish' == $post->post_status )
|
if ( 'publish' == $post->post_status )
|
||||||
$caps[] = 'delete_published_posts';
|
$caps[] = $post_type->cap->delete_published_posts;
|
||||||
elseif ( 'private' == $post->post_status )
|
elseif ( 'private' == $post->post_status )
|
||||||
$caps[] = 'delete_private_posts';
|
$caps[] = $post_type->cap->delete_private_posts;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'delete_page':
|
|
||||||
$author_data = get_userdata( $user_id );
|
|
||||||
//echo "post ID: {$args[0]}<br />";
|
|
||||||
$page = get_page( $args[0] );
|
|
||||||
$page_author_data = get_userdata( $page->post_author );
|
|
||||||
//echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
|
|
||||||
// If the user is the author...
|
|
||||||
|
|
||||||
if ('' != $page->post_author) {
|
|
||||||
$page_author_data = get_userdata( $page->post_author );
|
|
||||||
} else {
|
|
||||||
//No author set yet so default to current user for cap checks
|
|
||||||
$page_author_data = $author_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) {
|
|
||||||
// If the page is published...
|
|
||||||
if ( $page->post_status == 'publish' ) {
|
|
||||||
$caps[] = 'delete_published_pages';
|
|
||||||
} elseif ( 'trash' == $page->post_status ) {
|
|
||||||
if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) )
|
|
||||||
$caps[] = 'delete_published_pages';
|
|
||||||
} else {
|
|
||||||
// If the page is draft...
|
|
||||||
$caps[] = 'delete_pages';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The user is trying to edit someone else's page.
|
|
||||||
$caps[] = 'delete_others_pages';
|
|
||||||
// The page is published, extra cap required.
|
|
||||||
if ( $page->post_status == 'publish' )
|
|
||||||
$caps[] = 'delete_published_pages';
|
|
||||||
elseif ( $page->post_status == 'private' )
|
|
||||||
$caps[] = 'delete_private_pages';
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// edit_post breaks down to edit_posts, edit_published_posts, or
|
// edit_post breaks down to edit_posts, edit_published_posts, or
|
||||||
// edit_others_posts
|
// edit_others_posts
|
||||||
case 'edit_post':
|
case 'edit_post':
|
||||||
|
case 'edit_page':
|
||||||
$author_data = get_userdata( $user_id );
|
$author_data = get_userdata( $user_id );
|
||||||
//echo "post ID: {$args[0]}<br />";
|
//echo "post ID: {$args[0]}<br />";
|
||||||
$post = get_post( $args[0] );
|
$post = get_post( $args[0] );
|
||||||
|
|
||||||
$post_type = get_post_type_object( $post->post_type );
|
$post_type = get_post_type_object( $post->post_type );
|
||||||
if ( $post_type && 'post' != $post_type->capability_type ) {
|
if ( 'edit_post' == $cap && $post_type && 'post' != $post_type->capability_type && ! $post_type->map_meta_cap ) {
|
||||||
$args = array_merge( array( $post_type->cap->edit_post, $user_id ), $args );
|
$args = array_merge( array( $post_type->cap->edit_post, $user_id ), $args );
|
||||||
return call_user_func_array( 'map_meta_cap', $args );
|
return call_user_func_array( 'map_meta_cap', $args );
|
||||||
}
|
}
|
||||||
|
@ -909,86 +875,44 @@ function map_meta_cap( $cap, $user_id ) {
|
||||||
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
|
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID ) {
|
||||||
// If the post is published...
|
// If the post is published...
|
||||||
if ( 'publish' == $post->post_status ) {
|
if ( 'publish' == $post->post_status ) {
|
||||||
$caps[] = 'edit_published_posts';
|
$caps[] = $post_type->cap->edit_published_posts;
|
||||||
} elseif ( 'trash' == $post->post_status ) {
|
} elseif ( 'trash' == $post->post_status ) {
|
||||||
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
|
if ('publish' == get_post_meta($post->ID, '_wp_trash_meta_status', true) )
|
||||||
$caps[] = 'edit_published_posts';
|
$caps[] = $post_type->cap->edit_published_posts;
|
||||||
} else {
|
} else {
|
||||||
// If the post is draft...
|
// If the post is draft...
|
||||||
$caps[] = 'edit_posts';
|
$caps[] = $post_type->cap->edit_posts;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The user is trying to edit someone else's post.
|
// The user is trying to edit someone else's post.
|
||||||
$caps[] = 'edit_others_posts';
|
$caps[] = $post_type->cap->edit_others_posts;
|
||||||
// The post is published, extra cap required.
|
// The post is published, extra cap required.
|
||||||
if ( 'publish' == $post->post_status )
|
if ( 'publish' == $post->post_status )
|
||||||
$caps[] = 'edit_published_posts';
|
$caps[] = $post_type->cap->edit_published_posts;
|
||||||
elseif ( 'private' == $post->post_status )
|
elseif ( 'private' == $post->post_status )
|
||||||
$caps[] = 'edit_private_posts';
|
$caps[] = $post_type->cap->edit_private_posts;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'edit_page':
|
|
||||||
$author_data = get_userdata( $user_id );
|
|
||||||
//echo "post ID: {$args[0]}<br />";
|
|
||||||
$page = get_page( $args[0] );
|
|
||||||
$page_author_data = get_userdata( $page->post_author );
|
|
||||||
//echo "current user id : $user_id, page author id: " . $page_author_data->ID . "<br />";
|
|
||||||
// If the user is the author...
|
|
||||||
if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID ) {
|
|
||||||
// If the page is published...
|
|
||||||
if ( 'publish' == $page->post_status ) {
|
|
||||||
$caps[] = 'edit_published_pages';
|
|
||||||
} elseif ( 'trash' == $page->post_status ) {
|
|
||||||
if ('publish' == get_post_meta($page->ID, '_wp_trash_meta_status', true) )
|
|
||||||
$caps[] = 'edit_published_pages';
|
|
||||||
} else {
|
|
||||||
// If the page is draft...
|
|
||||||
$caps[] = 'edit_pages';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The user is trying to edit someone else's page.
|
|
||||||
$caps[] = 'edit_others_pages';
|
|
||||||
// The page is published, extra cap required.
|
|
||||||
if ( 'publish' == $page->post_status )
|
|
||||||
$caps[] = 'edit_published_pages';
|
|
||||||
elseif ( 'private' == $page->post_status )
|
|
||||||
$caps[] = 'edit_private_pages';
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'read_post':
|
case 'read_post':
|
||||||
|
case 'read_page':
|
||||||
$post = get_post( $args[0] );
|
$post = get_post( $args[0] );
|
||||||
$post_type = get_post_type_object( $post->post_type );
|
$post_type = get_post_type_object( $post->post_type );
|
||||||
if ( $post_type && 'post' != $post_type->capability_type ) {
|
if ( 'read_post' == $cap && $post_type && 'post' != $post_type->capability_type && ! $post_type->map_meta_cap ) {
|
||||||
$args = array_merge( array( $post_type->cap->read_post, $user_id ), $args );
|
$args = array_merge( array( $post_type->cap->read_post, $user_id ), $args );
|
||||||
return call_user_func_array( 'map_meta_cap', $args );
|
return call_user_func_array( 'map_meta_cap', $args );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 'private' != $post->post_status ) {
|
if ( 'private' != $post->post_status ) {
|
||||||
$caps[] = 'read';
|
$caps[] = $post_type->cap->read;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$author_data = get_userdata( $user_id );
|
$author_data = get_userdata( $user_id );
|
||||||
$post_author_data = get_userdata( $post->post_author );
|
$post_author_data = get_userdata( $post->post_author );
|
||||||
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID )
|
if ( is_object( $post_author_data ) && $user_id == $post_author_data->ID )
|
||||||
$caps[] = 'read';
|
$caps[] = $post_type->cap->read;
|
||||||
else
|
else
|
||||||
$caps[] = 'read_private_posts';
|
$caps[] = $post_type->cap->read_private_posts;
|
||||||
break;
|
|
||||||
case 'read_page':
|
|
||||||
$page = get_page( $args[0] );
|
|
||||||
|
|
||||||
if ( 'private' != $page->post_status ) {
|
|
||||||
$caps[] = 'read';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$author_data = get_userdata( $user_id );
|
|
||||||
$page_author_data = get_userdata( $page->post_author );
|
|
||||||
if ( is_object( $page_author_data ) && $user_id == $page_author_data->ID )
|
|
||||||
$caps[] = 'read';
|
|
||||||
else
|
|
||||||
$caps[] = 'read_private_pages';
|
|
||||||
break;
|
break;
|
||||||
case 'edit_comment':
|
case 'edit_comment':
|
||||||
$comment = get_comment( $args[0] );
|
$comment = get_comment( $args[0] );
|
||||||
|
@ -1050,6 +974,13 @@ function map_meta_cap( $cap, $user_id ) {
|
||||||
$caps[] = $cap;
|
$caps[] = $cap;
|
||||||
break;
|
break;
|
||||||
default:
|
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.
|
// If no meta caps match, return the original cap.
|
||||||
$caps[] = $cap;
|
$caps[] = $cap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ function create_initial_post_types() {
|
||||||
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
|
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
|
||||||
'_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
|
'_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
|
||||||
'capability_type' => 'post',
|
'capability_type' => 'post',
|
||||||
|
'map_meta_cap' => true,
|
||||||
'hierarchical' => false,
|
'hierarchical' => false,
|
||||||
'rewrite' => false,
|
'rewrite' => false,
|
||||||
'query_var' => false,
|
'query_var' => false,
|
||||||
|
@ -31,6 +32,7 @@ function create_initial_post_types() {
|
||||||
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
|
'_builtin' => true, /* internal use only. don't use this when registering your own post type. */
|
||||||
'_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
|
'_edit_link' => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
|
||||||
'capability_type' => 'page',
|
'capability_type' => 'page',
|
||||||
|
'map_meta_cap' => true,
|
||||||
'hierarchical' => true,
|
'hierarchical' => true,
|
||||||
'rewrite' => false,
|
'rewrite' => false,
|
||||||
'query_var' => false,
|
'query_var' => false,
|
||||||
|
@ -836,7 +838,8 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' )
|
||||||
* - menu_position - The position in the menu order the post type should appear. Defaults to the bottom.
|
* - menu_position - The position in the menu order the post type should appear. Defaults to the bottom.
|
||||||
* - menu_icon - The url to the icon to be used for this menu. Defaults to use the posts icon.
|
* - menu_icon - The url to the icon to be used for this menu. Defaults to use the posts icon.
|
||||||
* - capability_type - The post type to use for checking read, edit, and delete capabilities. Defaults to "post".
|
* - capability_type - The post type to use for checking read, edit, and delete capabilities. Defaults to "post".
|
||||||
* - capabilities - Array of capabilities for this post type. You can see accepted values in {@link get_post_type_capabilities()}. By default the capability_type is used to construct capabilities.
|
* - capabilities - Array of capabilities for this post type. You can see accepted values in {@link get_post_type_capabilities()}. By default the capability_type is used as a base to construct capabilities.
|
||||||
|
* - map_meta_cap - Whether to use the internal default meta capability handling. Defaults to false.
|
||||||
* - hierarchical - Whether the post type is hierarchical. Defaults to false.
|
* - hierarchical - Whether the post type is hierarchical. Defaults to false.
|
||||||
* - supports - An alias for calling add_post_type_support() directly. See add_post_type_support() for Documentation. Defaults to none.
|
* - supports - An alias for calling add_post_type_support() directly. See add_post_type_support() for Documentation. Defaults to none.
|
||||||
* - register_meta_box_cb - Provide a callback function that will be called when setting up the meta boxes for the edit form. Do remove_meta_box() and add_meta_box() calls in the callback.
|
* - register_meta_box_cb - Provide a callback function that will be called when setting up the meta boxes for the edit form. Do remove_meta_box() and add_meta_box() calls in the callback.
|
||||||
|
@ -866,7 +869,8 @@ function register_post_type($post_type, $args = array()) {
|
||||||
// Args prefixed with an underscore are reserved for internal use.
|
// Args prefixed with an underscore are reserved for internal use.
|
||||||
$defaults = array(
|
$defaults = array(
|
||||||
'labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null,
|
'labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null,
|
||||||
'_builtin' => false, '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'capabilities' => array(), 'hierarchical' => false,
|
'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => false,
|
||||||
|
'_builtin' => false, '_edit_link' => 'post.php?post=%d', 'hierarchical' => false,
|
||||||
'public' => false, 'rewrite' => true, 'query_var' => true, 'supports' => array(), 'register_meta_box_cb' => null,
|
'public' => false, 'rewrite' => true, 'query_var' => true, 'supports' => array(), 'register_meta_box_cb' => null,
|
||||||
'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
|
'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
|
||||||
'permalink_epmask' => EP_PERMALINK, 'can_export' => true, 'show_in_nav_menus' => null, 'show_in_menu' => null,
|
'permalink_epmask' => EP_PERMALINK, 'can_export' => true, 'show_in_nav_menus' => null, 'show_in_menu' => null,
|
||||||
|
@ -978,22 +982,60 @@ function register_post_type($post_type, $args = array()) {
|
||||||
* - read_private_posts - The capability that controls reading private posts. Defaults to "read_private . $capability_type . s" (read_private_posts).
|
* - read_private_posts - The capability that controls reading private posts. Defaults to "read_private . $capability_type . s" (read_private_posts).
|
||||||
* - delete_post - The meta capability that controls deleting a particular object of this post type. Defaults to "delete_ . $capability_type" (delete_post).
|
* - delete_post - The meta capability that controls deleting a particular object of this post type. Defaults to "delete_ . $capability_type" (delete_post).
|
||||||
*
|
*
|
||||||
|
* @see map_meta_cap()
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
|
*
|
||||||
* @param object $args
|
* @param object $args
|
||||||
* @return object object with all the capabilities as member variables
|
* @return object object with all the capabilities as member variables
|
||||||
*/
|
*/
|
||||||
function get_post_type_capabilities( $args ) {
|
function get_post_type_capabilities( $args ) {
|
||||||
$defaults = array(
|
global $_post_type_meta_capabilities;
|
||||||
|
|
||||||
|
$default_capabilities = array(
|
||||||
|
// Meta capabilities are generally mapped to primitive capabilities depending on the context
|
||||||
|
// (which would be the post being edited/deleted/read), instead of granted to users or roles:
|
||||||
'edit_post' => 'edit_' . $args->capability_type,
|
'edit_post' => 'edit_' . $args->capability_type,
|
||||||
|
'read_post' => 'read_' . $args->capability_type,
|
||||||
|
'delete_post' => 'delete_' . $args->capability_type,
|
||||||
|
// Primitive capabilities that are used outside of map_meta_cap():
|
||||||
'edit_posts' => 'edit_' . $args->capability_type . 's',
|
'edit_posts' => 'edit_' . $args->capability_type . 's',
|
||||||
'edit_others_posts' => 'edit_others_' . $args->capability_type . 's',
|
'edit_others_posts' => 'edit_others_' . $args->capability_type . 's',
|
||||||
'publish_posts' => 'publish_' . $args->capability_type . 's',
|
'publish_posts' => 'publish_' . $args->capability_type . 's',
|
||||||
'read_post' => 'read_' . $args->capability_type,
|
|
||||||
'read_private_posts' => 'read_private_' . $args->capability_type . 's',
|
'read_private_posts' => 'read_private_' . $args->capability_type . 's',
|
||||||
'delete_post' => 'delete_' . $args->capability_type,
|
|
||||||
);
|
);
|
||||||
$labels = array_merge( $defaults, $args->capabilities );
|
// Primitive capabilities that are used within map_meta_cap():
|
||||||
return (object) $labels;
|
if ( $args->map_meta_cap ) {
|
||||||
|
$default_capabilities_for_mapping = array(
|
||||||
|
'read' => 'read',
|
||||||
|
'delete_posts' => 'delete_' . $args->capability_type . 's',
|
||||||
|
'delete_private_posts' => 'delete_private_' . $args->capability_type . 's',
|
||||||
|
'delete_published_posts' => 'delete_published_' . $args->capability_type . 's',
|
||||||
|
'delete_others_posts' => 'delete_others_' . $args->capability_type . 's',
|
||||||
|
'edit_private_posts' => 'edit_private_' . $args->capability_type . 's',
|
||||||
|
'edit_published_posts' => 'edit_published_' . $args->capability_type . 's',
|
||||||
|
);
|
||||||
|
$default_capabilities = array_merge( $default_capabilities, $default_capabilities_for_mapping );
|
||||||
|
}
|
||||||
|
$capabilities = array_merge( $default_capabilities, $args->capabilities );
|
||||||
|
if ( $args->map_meta_cap )
|
||||||
|
_post_type_meta_capabilities( $capabilities );
|
||||||
|
return (object) $capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores or returns a list of post type meta caps for map_meta_cap().
|
||||||
|
*
|
||||||
|
* @since 3.1.0
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
function _post_type_meta_capabilities( $capabilities = null ) {
|
||||||
|
static $meta_caps = array();
|
||||||
|
if ( null === $capabilities )
|
||||||
|
return $meta_caps;
|
||||||
|
foreach ( $capabilities as $core => $custom ) {
|
||||||
|
if ( in_array( $core, array( 'read_post', 'delete_post', 'edit_post' ) ) )
|
||||||
|
$meta_caps[ $custom ] = $core;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue