Make WordPress Core

Opened 14 years ago

Closed 14 years ago

Last modified 13 years ago

#15779 closed defect (bug) (fixed)

Can't add featured images to custom post types

Reported by: somatic's profile somatic Owned by: nacin's profile nacin
Milestone: 3.1 Priority: normal
Severity: critical Version: 3.1
Component: Post Thumbnails Keywords:
Focuses: Cc:

Description

In all the 3.1 beta builds, up to 3.1-beta1-16723, whenever I try to add a featured image to a custom post type item, through the media uploader thickbox, clicking "use as featured image", the Featured Image metabox content shows "-1", and no image.

This is with a custom post type whose 'capability_type' is set to a custom value (not "post").

I've tracked the "-1" output down to wp-admin/admin-ajax.php, line 1425

if ( !current_user_can( 'edit_post', $post_ID ) )
	die( '-1' );

This code seems unchanged from WP 3.0 - 3.0.3, where I didn't have this problem. I'm assuming something has changed in 3.1 with regards to map_meta_cap or other custom post type capability checking.

AFAIK, the conditional is failing because the $post_ID being checked isn't "post" type, and so the capability "edit_post" doesn't apply.

If I manually change "edit_post" to "edit_mycustomtype", the test works, and the featured image thumbnail shows up in the proper metabox.

I don't know that this is a proper solution, as a custom post type's capability type could technically be set to anything, but this fix at least checks the capability against the post type's name (which is how I usually do it):

$post_type = get_post_type( $post_ID );
if ( !current_user_can( 'edit_' . $post_type, $post_ID ) )
die( '-1' );

Change History (15)

#1 @nacin
14 years ago

  • Milestone changed from Awaiting Review to 3.1
  • Owner set to nacin
  • Status changed from new to reviewing

Please show us the code you are using to register your post type.

If you are using the map_meta_cap filter, post the callback as well.

Presumably #14122 is the culprit here but I need more info.

#2 @nacin
14 years ago

  • Keywords reporter-feedback added

#3 @somatic
14 years ago

post type register:

$labels = array(
	'name' => _x('Videos', 'post type general name'),
	'singular_name' => _x('Video', 'post type singular name'),
	'add_new' => _x('Add New', 'Video'),
	'add_new_item' => __('Add New Video'),
	'edit_item' => __('Edit Video'),
	'edit' => _x('Edit', 'video'),
	'new_item' => __('New Video'),
	'view_item' => __('View Video'),
	'search_items' => __('Search Videos'),
	'not_found' =>  __('No Videos found'),
	'not_found_in_trash' => __('No Videos found in Trash'),
	'view' =>  __('View Video')
);

$args = array(
	'public' => true,
	'publicly_queryable' => true,
	'menu_icon' => SMAM_IMG .'/videos-menu-icon.png',
	'show_ui' => true,
	'capability_type' => 'video',
	'capabilities' => array(
		'publish_posts' => 'publish_videos',
		'edit_posts' => 'edit_videos',
		'edit_others_posts' => 'edit_others_videos',
		'delete_posts' => 'delete_videos',
		'delete_others_posts' => 'delete_others_videos',
		'read_private_posts' => 'read_private_videos',
		'edit_post' => 'edit_video',
		'delete_post' => 'delete_video',
		'read_post' => 'read_video',
	),
	'has_archive' => 'videos',
	'hierarchical' => true,
	'query_var' => true,
	'menu_position' => 6,
	'show_in_nav_menus' => true,
	'supports' => array('thumbnail','comments'),
	'rewrite' => array( 'slug' => 'videos', 'with_front' => false ),
	'register_meta_box_cb' => array('smamMetaboxes','add_custom_boxes'),type
	'labels' => $labels
);

register_post_type('videos', $args);

and function used with add_filter('map_meta_cap'):

function smam_map_meta_cap( $caps, $cap, $user_id, $args ) {

	/* If editing, deleting, or reading an asset, get the post and post type object. */
	if ( 'edit_video' == $cap || 'delete_video' == $cap || 'read_video' == $cap) {
		$post = get_post( $args[0] );
		$post_type = get_post_type_object( $post->post_type );

		/* Set an empty array for the caps. */
		$caps = array();
	}

	/* If editing an item, assign the required capability. */
	if ( 'edit_video' == $cap ) {
		if ( $user_id == $post->post_author )
			$caps[] = $post_type->cap->edit_posts;
		else
			$caps[] = $post_type->cap->edit_others_posts;
	}

	/* If deleting an item, assign the required capability. */
	elseif ('delete_video' == $cap ) {
		if ( $user_id == $post->post_author )
			$caps[] = $post_type->cap->delete_posts;
		else
			$caps[] = $post_type->cap->delete_others_posts;
	}

	/* If reading a private item, assign the required capability. */
	elseif ( 'read_video' == $cap ) {

		if ( 'private' != $post->post_status )
			$caps[] = 'read';
		elseif ( $user_id == $post->post_author )
			$caps[] = 'read';
		else
			$caps[] = $post_type->cap->read_private_posts;
	}

	/* Return the capabilities required by the user. */
	return $caps;
}

#5 @somatic
14 years ago

  • Cc israel@… added

So I went digging for what's different about custom post type capabilities in 3.1, and discovered that I can solve the featured image "-1" error problem without changing wp-admin/admin-ajax.php.

I got rid of this code:

	'capabilities' => array(
		'publish_posts' => 'publish_videos',
		'edit_posts' => 'edit_videos',
		'edit_others_posts' => 'edit_others_videos',
		'delete_posts' => 'delete_videos',
		'delete_others_posts' => 'delete_others_videos',
		'read_private_posts' => 'read_private_videos',
		'edit_post' => 'edit_video',
		'delete_post' => 'delete_video',
		'read_post' => 'read_video',
	),

and added the new

'map_meta_cap' => true,

to my args for register_post_type(), which the new docs say controls "Whether to use the internal default meta capability handling". This made me wonder if I needed justin tadlocks custom map_meta_cap filter anymore, so I disabled that as well.

So basically, it would seem that the 3.0 behavior for CPT required a lot more specificity, both in the capabilities array and the map_meta_cap. Though I don't know where exactly, 3.1 appears to take care of all that automatically, so I can simply declare in the CPT args:

'capability_type' => 'video',
'map_meta_cap' => true,
'has_archive' => 'videos',

I'm not sure how, but there should be a notice somewhere about how the code needed to make CPT's capabilities work properly in 3.0 actually *breaks* functionality in 3.1.

I'm also not 100% sure that these using these new args (and deleting the old 3.0 ones) isn't going to break something else... got to test some more...

#7 @nacin
14 years ago

  • Keywords reporter-feedback removed

Correct, the new map_meta_cap flag renders the code from Justin unnecessary.

That your code is breaking means I misjudged some logic in #14122. I'll be writing up a set of unit tests so I can make appropriate adjustments. Thanks for posting everything, this is exactly what I need.

#8 @somatic
14 years ago

Glad to help.

I just stumbled on a problem with the new args, however - whatever is happening now with 3.1 map_meta_cap doesn't seem to cover all the capabilities that my 3.0 code did. I am not able to edit other's items anymore. I had been using this to add the custom post type capability to a role:

$admin = get_role('administrator');

$admin->add_cap('edit_videos');
$admin->add_cap('edit_others_videos');
$admin->add_cap('publish_videos');
$admin->add_cap('read_private_videos');
$admin->add_cap('delete_videos');
$admin->add_cap('delete_others_videos');

I can create new items in my CPT just fine, but not others (admin lists show "view" but not "edit, trash, preview"). Even more strange is that I can edit other's drafts, but not published items...

#9 follow-up: @somatic
14 years ago

wait - I can't edit anyone's published items, not even my own!

what am I missing here?

#10 in reply to: ↑ 9 @duck_
14 years ago

Replying to somatic:

wait - I can't edit anyone's published items, not even my own!

what am I missing here?

edit_published_videos? You might also want to add edit_private_videos, delete_published_videos and delete_private_videos.

#11 follow-up: @somatic
14 years ago

it seems I needed one more add_cap (that I didn't seem to need before the new 3.1 map_meta_cap...

$admin->add_cap('edit_published_videos');

Is there a comprehensive list of all the capabilities that must be enabled to replicate typical role behavior with custom post types?

Seems like it would be easier (and less prone to failure) if there was a single add_cap that could relate to the 'capability_type' => 'video' declaration when registering CPT's...

#12 in reply to: ↑ 11 @duck_
14 years ago

Replying to somatic:

it seems I needed one more add_cap (that I didn't seem to need before the new 3.1 map_meta_cap...

$admin->add_cap('edit_published_videos');

Is there a comprehensive list of all the capabilities that must be enabled to replicate typical role behavior with custom post types?

Take a look at the source of map_meta_cap and at the Roles and Capabilities page on the codex. Also, it worked for you pre-3.1 because the filter you were using mapped to either edit_* or edit_others_* and didn't ever look at post status.

Any further questions should probably go through a support channel... the bug here is being investigated by nacin :)

#13 @nacin
14 years ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

(In [16909]) Ensure the map_meta_cap filter receives the right cap when the map_meta_cap flag is false. fixes #15779.

#14 @nacin
14 years ago

(In [16910]) I have CDO. see #15779.

Note: See TracTickets for help on using tickets.