1

I have created a custom role called Custom Author. Users in this role can edit their own pages and add new pages. I would like to restrict new page creation and allow Custom Authors to create pages only as child pages of their own pages. In other words, I would like them to still be able to create new pages, but only as child pages of the pages they have editor access to.

Here is what I think I need to do: remove capability publish_pages (I can do it with a plugin) and add a new capability by doing something like this:

function add_theme_custom_author_caps() {
    $role = get_role( 'custom-author' );
    $role->add_cap( 'publish_own_pages' ); 
}
add_action( 'admin_init', 'add_theme_custom_author_caps');

The problem here is that add_cap( 'publish_own_pages' ) simply will not work and I struggle to understand how to create a new capability based on my requirements.

8
  • How will the list of parent pages be created if they could only create children pages? Jun 26, 2019 at 15:53
  • I wouldn't say adding the new capability "will not work." Your code should successfully add that capability to the Custom Author role. However, WordPress doesn't automatically understand that when you say "publish_own_pages" you mean "let them create new pages that are children of their own pages, but not other new pages." You'll need to hook into one of the hooks that fires when a post is updated or created, and add logic there that checks whether the current user is the author of the parent of the page they're trying to publish.
    – WebElaine
    Jun 26, 2019 at 18:51
  • An alternative approach you might find easier is, give everyone their own CPT. They'll then have an archive that can act like the parent page, and you can use map_meta_cap to create custom capabilities for each CPT, so each author can then get only those permissions and only work on their own CPT.
    – WebElaine
    Jun 26, 2019 at 18:52
  • @NathanPowell the very first parent page will be created by the administrator. Then page 'Author' will be changed to relevant user.
    – Anna
    Jun 26, 2019 at 21:21
  • Thanks @WebElaine, I'm going to have to go with 'custom post type' approach if I can't figure out how to do what you suggested in your first comment.
    – Anna
    Jun 26, 2019 at 21:28

1 Answer 1

0

Custom Post Types will be much easier to set up, and you won't have to code your own solution to check in the Editor whether the current user has permission to create a new page or edit something.

You can set up the CPT archives at whatever URL you like.

So, in your example, you can set up a regular Page at /animals/ and a regular child Page at /animals/carnivores/. Your custom roles will not have any access to edit those.

You will then create a CPT of "cat". You should look into all of the options for registering CPTs, as you may not need all of the options, but some may be handy, like "menu_icon" which sets the icon that appears in the wp-admin left sidebar, and some will be necessary, like "rewrite" which is what you need to set them up at the URLs you desire, and "capabilities" which are what you'll use to restrict who can access what. You'll also want to decide what to put in "supports" - this example includes a title, editor, and a thumbnail (featured image).

<?php
/* Plugin Name: WPSE custom post types
*/
// on init, create a custom post type called Cat
add_action('init', 'wpse_create_post_types');
function wpse_create_post_types() {
    // Capabilities: this is how you'll enable some users to edit, delete, etc.
    $capabilities = array(
        'edit_post'                 => 'edit_cat',
        'read_post'                 => 'read_cat',
        'delete_post'               => 'delete_cat',
        'create_posts'              => 'create_cats',
        'delete_posts'              => 'delete_cats',
        'delete_others_posts'       => 'delete_others_cats',
        'delete_private_posts'      => 'delete_private_cats',
        'delete_published_posts'    => 'delete_published_cats',
        'edit_posts'                => 'edit_cats',
        'edit_others_posts'         => 'edit_others_cats',
        'edit_private_posts'        => 'edit_private_cats',
        'edit_published_posts'      => 'edit_published_cats',
        'publish_posts'             => 'publish_news',
        'read_private_posts'        => 'read_private_news'
    );
    // Other CPT arguments
    $args = array(
        // Important: make sure to include the next 2 args for capabilities
        'map_meta_cap' => true,
        'capabilities' => $capabilities,
        // Important: make sure to set the rewrite to your desired archive URL
        'rewrite'           => array('slug' => 'animals/carnivores/cats'),
        // You can adjust the other args as needed
        'public' => true,
        'has_archive' => true,
        'hierarchical' => false,
        'supports' => array('title', 'editor', 'thumbnail')
    );
    // Actually create the post type
    register_post_type('cat', $args);
}

Because you have created new capabilities, no users have access to it yet - including Administrators. So to grant access, add this to the same plugin file:

// 'cat_author' is a slug, 'Custom Author Cats' is how you will see this role in wp-admin
add_role('cat_author', 'Custom Author Cats', array(
    // You may or may not want to give them all these capabilities.
    // For example you could let them publish but not delete.
    'delete_cats' => true,
    'create_cats' => true,
    'delete_cats' => true,
    'delete_others_cats' => true,
    'delete_private_cats' => true,
    'delete_published_cats' => true,
    'edit_cats' => true,
    'edit_others_cats' => true,
    'edit_private_cats' => true,
    'edit_published_cats' => true,
    'publish_cats' => true,
    'read_private_cats' => true,
    // If you want them to be able to upload files and read on the front end,
    // make sure to include the following 2 capabilities:
    'read' => true,
    'upload_files' => true
));

Finally, you may also want to have Admins (like yourself perhaps) be able to add/edit/delete these custom News posts. If so, add this to the plugin:

add_action('admin_init', 'wpse_add_admin_caps');
function wpse_add_admin_caps() {
    $role = get_role('administrator');
    $role->add_cap('delete_cats');
    $role->add_cap('create_cats');
    $role->add_cap('delete_cats');
    $role->add_cap('delete_others_cats');
    $role->add_cap('delete_private_cats');
    $role->add_cap('delete_published_cats');
    $role->add_cap('edit_cats');
    $role->add_cap('edit_others_cats');
    $role->add_cap('edit_private_cats');
    $role->add_cap('edit_published_cats');
    $role->add_cap('publish_cats');
    $role->add_cap('read_private_cats');
}

You'll need to repeat this for each custom post type, and make sure that after the plugin is activated, you visit the Settings > Permalinks page. You don't have to change any settings there, but visiting it will flush rewrite rules and set up the new URLs you've defined in the plugin. Then, the final step will be adding each user and assigning it the correct role.

4
  • Thank you for posting your answer! This plugin gave me a 500 error, and I'm not sure why (perhaps due to the changes in .htaccess). I'll keep trying to make it work and let you know how it goes.
    – Anna
    Jun 28, 2019 at 14:38
  • What changes did you make to .htaccess? CPTs don't require any.
    – WebElaine
    Jun 28, 2019 at 14:52
  • The plugin itself made a small change (I guess by flushing the rewrite rules) - added an extra </IfModule> where it's not needed.
    – Anna
    Jun 28, 2019 at 14:56
  • I fixed the .htaccess error and the plugin seems to be working now. Weirdly enough I did not include the last bit of code to enable admin access, but I can still edit this CPT as an adminitrator.
    – Anna
    Jun 28, 2019 at 15:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.