WordPress.org

Make WordPress Core

Opened 3 years ago

Closed 15 months ago

#39725 closed defect (bug) (worksforme)

Post Type Capabilities Broken

Reported by: michael.ecklund Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.7.2
Component: Posts, Post Types Keywords: reporter-feedback
Focuses: Cc:
PR Number:

Description

It appears that specifying capabilities to a specific Post Type has little to no effect. When customizing the capabilities for a specific Post Type during registration it throws PHP errors and as far as I can tell, doesn't appear to be working at all.

I've got a Post Type which contains private posts only. I don't want posts to be: Created, Deleted, or Published. I thought this would be a simple task. Apparently not.

When registering a Post Type ... I've specified the following:

<?php

$args['public']              = false;
$args['publicly_queryable']  = false;
$args['show_ui']             = true;
$args['show_in_menu']        = false;
$args['query_var']           = false;
$args['rewrite']             = false;
$args['has_archive']         = false;
$args['hierarchical']        = false;
$args['exclude_from_search'] = true;

$args['map_meta_cap']    = true;
$args['capability_type'] = 'post';

I've tried this:

<?php

$args['capabilities']                           = array();
$args['capabilities']['edit_post']              = 'edit_post';
$args['capabilities']['read_post']              = 'do_not_allow';
$args['capabilities']['delete_post']            = 'do_not_allow';
$args['capabilities']['edit_posts']             = 'edit_posts';
$args['capabilities']['edit_others_posts']      = 'edit_others_posts';
$args['capabilities']['publish_posts']          = 'do_not_allow';
$args['capabilities']['read_private_posts']     = 'do_not_allow';
$args['capabilities']['read']                   = 'do_not_allow';
$args['capabilities']['delete_posts']           = 'do_not_allow';
$args['capabilities']['delete_private_posts']   = 'do_not_allow';
$args['capabilities']['delete_published_posts'] = 'do_not_allow';
$args['capabilities']['delete_others_posts']    = 'do_not_allow';
$args['capabilities']['edit_private_posts']     = 'edit_private_posts';
$args['capabilities']['edit_published_posts']   = 'do_not_allow';
$args['capabilities']['create_posts']           = 'do_not_allow';

I've also tried this:

<?php

$args['capabilities']                           = array();
$args['capabilities']['read_post']              = 'do_not_allow';
$args['capabilities']['delete_post']            = 'do_not_allow';
$args['capabilities']['publish_posts']          = 'do_not_allow';
$args['capabilities']['read']                   = 'do_not_allow';
$args['capabilities']['delete_posts']           = 'do_not_allow';
$args['capabilities']['delete_private_posts']   = 'do_not_allow';
$args['capabilities']['delete_published_posts'] = 'do_not_allow';
$args['capabilities']['delete_others_posts']    = 'do_not_allow';
$args['capabilities']['edit_published_posts']   = 'do_not_allow';
$args['capabilities']['create_posts']           = 'do_not_allow';

I've also tried this:

<?php

$args['capabilities']                           = array();
$args['capabilities']['delete_post']            = 'do_not_allow';
$args['capabilities']['publish_posts']          = 'do_not_allow';
$args['capabilities']['delete_posts']           = 'do_not_allow';
$args['capabilities']['delete_private_posts']   = 'do_not_allow';
$args['capabilities']['delete_published_posts'] = 'do_not_allow';
$args['capabilities']['delete_others_posts']    = 'do_not_allow';
$args['capabilities']['edit_published_posts']   = 'do_not_allow';
$args['capabilities']['create_posts']           = 'do_not_allow';

I've played with these one by one and it seems no matter what I specify here, nothing seems to take effect properly.

PHP errors everywhere on edit.php and post.php

Attachments (2)

debug.log (42.7 KB) - added by michael.ecklund 3 years ago.
39725.diff (489 bytes) - added by lukecavanagh 3 years ago.
Basic patch

Download all attachments as: .zip

Change History (11)

@michael.ecklund
3 years ago

#1 @michael.ecklund
3 years ago

I could be overlooking something much more complex, but couldn't it be solved with something like:

if ( ! isset( $args[0] ) ) {
    $args[0] = null;
}

#2 follow-up: @johnbillion
3 years ago

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

Thanks for the ticket, @michael.ecklund.

I narrowed down the problem to the existence of three meta capabilities in your capabilities array:

$args['capabilities']['edit_post']   = 'edit_post';
$args['capabilities']['read_post']   = 'do_not_allow';
$args['capabilities']['delete_post'] = 'do_not_allow';

These are singular form meta capabilities, which shouldn't be defined in your capabilities array. They map to the edit_posts, read_posts, and delete_posts primitive capabilities respectively. If you remove these from your capabilities array, the functionality you're attempting to create appears to work as expected.

Let me know if this works for you.

#3 in reply to: ↑ 2 @michael.ecklund
3 years ago

Replying to johnbillion:

That doesn't seem to have resolved the problem. Still seeing PHP Notices everywhere.

The Codex must be incorrect then. The Codex demonstrates using those capabilities.

https://codex.wordpress.org/Function_Reference/register_post_type#Arguments

Thanks for the ticket, @michael.ecklund.

I narrowed down the problem to the existence of three meta capabilities in your capabilities array:

$args['capabilities']['edit_post']   = 'edit_post';
$args['capabilities']['read_post']   = 'do_not_allow';
$args['capabilities']['delete_post'] = 'do_not_allow';

These are singular form meta capabilities, which shouldn't be defined in your capabilities array. They map to the edit_posts, read_posts, and delete_posts primitive capabilities respectively. If you remove these from your capabilities array, the functionality you're attempting to create appears to work as expected.

Let me know if this works for you.

#4 @michael.ecklund
3 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

#5 @lukecavanagh
3 years ago

What happens if you use these for the custom capabilities of the registered post type.

https://codex.wordpress.org/Function_Reference/get_post_type_capabilities#Parameters

$capabilities = array(
		'edit_post'             => 'edit_post',
		'edit_posts'            => 'edit_posts',
		'edit_others_posts'     => 'edit_others_posts',
                'edit_private_posts'    => 'edit_private_posts'
	);

#6 @SergeyBiryukov
3 years ago

  • Milestone set to Awaiting Review

#7 @michael.ecklund
3 years ago

I'm not a core developer, so I'm unaware of the impact of this change. However, the following change does eliminate the PHP Notices.

./wp-includes/capabilities.php Line: 56

Change From:

$post = get_post( $args[0] );

Change To:

if ( isset( $args[0] ) ) {
    $post = get_post( $args[0] );
} else {
    $post = null;
}

@lukecavanagh
3 years ago

Basic patch

#8 @johnbillion
3 years ago

  • Focuses ui administration removed
  • Keywords reporter-feedback added

@lukecavanagh Your patch simply treats the symptom instead of the cause of the problem. Raising a notice here is desired behaviour when a meta capability such as edit_post is checked without passing a contextual parameter (the post ID).

@michael.ecklund Would you be so kind as to post the complete code you're using please? There may be something else in the capabilities array that I missed.

#9 @johnbillion
15 months ago

  • Milestone Awaiting Review deleted
  • Resolution set to worksforme
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.