简体   繁体   English

如何限制新用户角色只能访问常规帖子,而不是自定义帖子类型?

[英]How to limit a new user role to access only regular posts, not custom post types?

We're trying to add a new user role called 'post_editor' that can only access Wordpress' default posts, not 2 custom post types we have named 'content_blocks' and 'slides'.我们正在尝试添加一个名为“post_editor”的新用户角色,它只能访问 Wordpress 的默认帖子,而不是我们命名为“content_blocks”和“slides”的 2 种自定义帖子类型。

We've been able to achieve this through the plugin User Role Editor but we're trying to not add another plugin.我们已经能够通过插件用户角色编辑器实现这一点,但我们试图不添加其他插件。

Here is what we have tried.这是我们尝试过的。 In each case it creates the new user role but they can continue to see, edit, and publish the 2 custom post types of 'content_blocks' and 'slides'.在每种情况下,它都会创建新的用户角色,但他们可以继续查看、编辑和发布“content_blocks”和“幻灯片”这两种自定义帖子类型。

How do we prevent this user role from accessing those 2 custom post types?我们如何防止此用户角色访问这 2 种自定义帖子类型?

// Attempt 1

  add_action( 'admin_init', 'add_role_post_editor' );

  function add_role_post_editor(){
    global $wp_roles;
    if( get_role( 'post_editor' ) == NULL){
        $cap = array(
            'edit_posts' => true,
            'edit_others_posts' => true,
            'edit_published_posts' => true,
            'read' => true,  
            'create_content_blocks' => false,
            'delete_content_blocks' => false,
            'edit_content_blocks' => false,
            'edit_slides' => false,
            'create_slides' => false,
            'delete_slides' => false,
          );
        add_role( 'post_editor', 'Post Editor', $cap );
     }
// Attempt 2

  add_action( 'admin_init', 'add_role_post_editor' );

  function add_role_post_editor(){
    global $wp_roles;
    if( get_role( 'post_editor' ) == NULL){

        $cap = array(
            'edit_posts' => true,
            'edit_others_posts' => true,
            'edit_published_posts' => true,
            'read' => true
          );
        add_role( 'post_editor', 'Post Editor', $cap );

        $role = get_role( 'post_editor' );

        $role->remove_cap( 'create_content_blocks');
        $role->remove_cap( 'delete_content_blocks' );
        $role->remove_cap( 'edit_content_blocks' );
        $role->remove_cap( 'edit_others_content_blocks' );
        $role->remove_cap( 'edit_published_content_blocks' );
        $role->remove_cap( 'publish_content_blocks');
        $role->remove_cap( 'read_slides' );
        $role->remove_cap( 'edit_slides' );
        $role->remove_cap( 'edit_others_slides' );
    }
   }

Is the issue that when we register the custom post types we have to also register these capabilities too, otherwise they are not available for us to add or remove from user_roles?问题是当我们注册自定义帖子类型时,我们也必须注册这些功能,否则我们无法从 user_roles 添加或删除它们?

This might point you in the right direction.这可能会为您指明正确的方向。

First of all, you should fix how you update the user's roles and capabilities.首先,您应该确定如何更新用户的角色和能力。 These are stored in the database very much unlike a custom post type which is simply registered at runtime.这些存储在数据库中非常不同于在运行时简单注册的自定义帖子类型。 If you are managing user roles or caps with custom code I recommend not using a plugin to do the same as this has not worked out well for me in the past.如果您使用自定义代码管理用户角色或上限,我建议不要使用插件来做同样的事情,因为这在过去对我来说效果不佳。

There are two general approaches.有两种通用方法。

  1. Give the user no capabilities at all except for 'read' when you register the user role, and then use map_meta_cap to give them only the things they need.当您注册用户角色时,除了“读取”之外,根本不给用户任何功能,然后使用 map_meta_cap 只为他们提供他们需要的东西。

  2. Give the user more capabilities than they need when you register the role and then use map_meta_cap to try to take things away.当您注册角色时,为用户提供比他们需要的更多的功能,然后使用 map_meta_cap 尝试删除这些内容。

In my experience, #1 works best , but the code below is much closer to #2.根据我的经验, #1 效果最好,但下面的代码更接近 #2。

Furthermore, I think that the 'edit_posts' capabilities actually give the user more than what it sounds like.此外,我认为“edit_posts”功能实际上为用户提供了比听起来更多的功能。 You'll want to read some docs on caps for more info.您需要阅读一些有关大写的文档以获取更多信息。

// update this to re-init caps which are stored in DB
$custom_user_role_version = "1.1";

if ( $custom_user_role_version !== get_option( "custom_user_role_version" ) ) {
    update_option( "custom_user_role_version", $custom_user_role_version );

    $r = 'post_editor';

    remove_role( $r );
    add_role( $r, [
        'edit_posts' => true,
        'edit_others_posts' => true,
        'edit_published_posts' => true,
        'read' => true,
        // whether or not these do anything is dependant upon how the custom post type is registered
        // and what we put inside of 'map_meta_cap'. Even though we say false here, it's possible
        // that it does not do anything.
        'create_content_blocks' => false,
        'delete_content_blocks' => false,
        'edit_content_blocks' => false,
        'edit_slides' => false,
        'create_slides' => false,
        'delete_slides' => false,
    ]);
}

Now we hook onto 'map_meta_cap'.现在我们挂上'map_meta_cap'。 This filter is actually just the last line of a function with the same name.这个过滤器实际上只是同名函数的最后一行。 You should read the function to see the options for each of the input parameters.您应该阅读该函数以查看每个输入参数的选项。 You will have to do some research and some testing to complete the problem.您将不得不做一些研究和一些测试来完成这个问题。 Reading the code in the function will also give you some insight in how the parameters of register_post_type work in regards to meta capabilities.阅读函数中的代码还将让您深入了解 register_post_type 的参数如何与元功能相关。

function is_post_editor( $user ){
    return $user instanceof WP_User && in_array( 'post_editor', $user->roles );
};

/**
 * @see map_meta_cap
 */
add_filter( 'map_meta_cap', function( $caps, $cap = '', $user_id = null, $args = []  ){

    // can return this to allow an action after authenticating the logged in user
//    $caps_to_allow = [
//        'exist'
//    ];

    switch( $cap ) {
        case 'edit_post':

            if ( in_array( get_post_type( $args[0]), [ 'content_blocks', 'slides' ] ) ){

                if ( is_post_editor( get_user_by( 'ID', $user_id ) ) ) {

                    // I think pushing 'do_not_allow' to $caps will also work.
                    return [
                        'do_not_allow'
                    ];
                }
            }

            break;
        case 'read_post':

            // you might need something here too.
            break;
    }

    // the $caps that the user must have to perform the thing that requires $cap
    return $caps;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM