WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 6 weeks ago

#29009 reopened enhancement

There should be a capability for "publish private posts"

Reported by: t.schwarz Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.9.1
Component: Role/Capability Keywords: dev-feedback
Focuses: administration Cc:

Description

I've been working on a simple membership site with only two membership levels: logged in and logged out, which is a situation that theoretically could be easily managed in WP without any plugins. However, logged in members should not be able o post publicly, while they are allowed to post whatever they want inside the membership walls, so the review system doesn't help in this situation either.

Currently, I have to use a custom post type and force the status to private on publishing with a plugin to achieve the intended scenario.

But I think the most parsimonious solution would be to include a capability that would allow people to "publish_private_posts" yet not "publish_posts".

Change History (4)

#1 @DrewAPicture
5 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed

But I think the most parsimonious solution would be to include a capability that would allow people to "publish_private_posts" yet not "publish_posts".

I don't think we need another capability for this.

I'd suggest taking a look at the map_meta_cap filter for granting publish_posts in the case where they're set to private, as that seems to be the ultimate goal of your suggestion.

#2 @jfarthing84
5 years ago

  • Keywords dev-feedback added
  • Resolution wontfix deleted
  • Status changed from closed to reopened

+1. The map_meta_cap solution is not really feasible, considering the context in which the status is forcibly changed. Have a look at _wp_translate_postdata():

if ( isset( $post_data['post_status'] ) && 'private' == $post_data['post_status'] && ! current_user_can( $ptype->cap->publish_posts ) ) {
	$post_data['post_status'] = $previous_status ? $previous_status : 'pending';
}

Of course, _wp_translate_postdata() simply works with the global $_POST data. So, it would take some pretty silly logic (inside a map_meta_cap filter callback) to determine the current page, the current action and the desired post status.

#3 @jfarthing84
5 years ago

FWIW, here's my current solution:

function map_publish_private_posts_to_edit_posts( $caps, $cap ) {
	global $pagenow;

	if ( 'publish_posts' == $cap && 'post.php' == $pagenow &&
		isset( $_POST['action'] ) && 'editpost' == $_POST['action'] &&
		isset( $_POST['post_status'] ) && 'private' == $_POST['post_status']
	) {
		$caps = array( 'edit_posts' );
	}

	return $caps;
}
add_filter( 'map_meta_cap', 'map_publish_private_posts_to_edit_posts', 10, 2 );

#4 @SergeyBiryukov
5 years ago

  • Milestone set to Awaiting Review
Note: See TracTickets for help on using tickets.