仅允许用户编辑某些页面

时间:2015-06-16 作者:naf

我想允许某些用户只编辑一个页面及其子页面。这怎么可能?我尝试了旧的角色范围器,但它似乎有很多问题和bug。

4 个回复
最合适的回答,由SO网友:gmazzap 整理而成

要实现这样的任务,首先要做的是能够识别用户可以编辑的页面。

有不同的方法可以做到这一点。它可能是一个用户元,一些配置值。。。为了得到这个答案,我将假设存在一个函数lile this:

function wpse_user_can_edit( $user_id, $page_id ) {

   $page = get_post( $page_id );

   // let\'s find the topmost page in the hierarchy
   while( $page && (int) $page->parent ) {
     $page = get_post( $page->parent );
   }

   if ( ! $page ) {
     return false;
   }

   // now $page is the top page in the hierarchy
   // how to know if an user can edit it, it\'s up to you...

}
现在我们有了一种确定用户是否可以编辑页面的方法,我们只需要告诉WordPress使用此功能来检查用户编辑页面的能力。

可以通过\'map_meta_cap\' 滤器

类似于:

add_filter( \'map_meta_cap\', function ( $caps, $cap, $user_id, $args ) {

    $to_filter = [ \'edit_post\', \'delete_post\', \'edit_page\', \'delete_page\' ];

    // If the capability being filtered isn\'t of our interest, just return current value
    if ( ! in_array( $cap, $to_filter, true ) ) {
        return $caps;
    }

    // First item in $args array should be page ID
    if ( ! $args || empty( $args[0] ) || ! wpse_user_can_edit( $user_id, $args[0] ) ) {
        // User is not allowed, let\'s tell that to WP
        return [ \'do_not_allow\' ];
    }
    // Otherwise just return current value
    return $caps;

}, 10, 4 );
此时,我们只需要一种将用户连接到一个或多个页面的方法。

根据用例的不同,可能会有不同的解决方案。

一个灵活的解决方案可以是添加下拉的“根”页面(请参见wp_dropdown_pages) 转到编辑用户管理屏幕,并将所选页面另存为用户元。

我们可以利用\'edit_user_profile\' 要添加页面下拉字段,请执行以下操作\'edit_user_profile_update\' 将所选值存储为用户元。

我相信,在这个网站上有足够的指导如何做到这一点的细节。

当页面存储为用户元时wpse_user_can_edit() 通过检查页面id是否是用户元值的一部分,可以完成上面的函数。

删除编辑页面的功能,WordPress将完成其余操作:将从后端和前端删除任何编辑链接,将阻止直接访问。。。等等

SO网友:ricotheque

即使使用PHP类来避免全局变量,也需要少量代码来实现此功能。我也不想在仪表板中为用户隐藏禁止的页面。如果他们添加了网站上已有的内容,会怎么样?

$user_edit_limit = new NS_User_Edit_Limit(
    15,       // User ID we want to limit
    [2, 17]   // Array of parent page IDs user is allowed to edit
                 (also accepts sub-page IDs)
);

class NS_User_Edit_Limit {

    /**
     * Store the ID of the user we want to control, and the
     * posts we will let the user edit.
     */
    private $user_id = 0;
    private $allowed = array();

    public function __construct( $user_id, $allowed ) {

        // Save the ID of the user we want to limit.
        $this->user_id = $user_id;

        // Expand the list of allowed pages to include sub pages
        $all_pages = new WP_Query( array(
            \'post_type\' => \'page\',
            \'posts_per_page\' => -1,
        ) );            
        foreach ( $allowed as $page ) {
            $this->allowed[] = $page;
            $sub_pages = get_page_children( $page, $all_pages );
            foreach ( $sub_pages as $sub_page ) {
                $this->allowed[] = $sub_page->ID;
            }
        }

        // For the prohibited user...
        // Remove the edit link from the front-end as needed
        add_filter( \'get_edit_post_link\', array( $this, \'remove_edit_link\' ), 10, 3 );
        add_action( \'admin_bar_menu\', array( $this, \'remove_wp_admin_edit_link\' ), 10, 1 );
        // Remove the edit link from wp-admin as needed
        add_action( \'page_row_actions\', array( $this, \'remove_page_list_edit_link\' ), 10, 2 );
    }

    /**
     * Helper functions that check if the current user is the one
     * we want to limit, and check if a specific post is in our
     * list of posts that we allow the user to edit.
     */
    private function is_user_limited() {
        $current_user = wp_get_current_user();
        return ( $current_user->ID == $this->user_id );
    }
    private function is_page_allowed( $post_id ) {
        return in_array( $post_id, $this->allowed );
    }

    /**
     * Removes the edit link from the front-end as needed.
     */
    public function remove_edit_link( $link, $post_id, $test ) {
        /**
         * If...
         * - The limited user is logged in
         * - The page the edit link is being created for is not in the allowed list
         * ...return an empty $link. This also causes edit_post_link() to show nothing.
         *
         * Otherwise, return link as normal.
         */
        if ( $this->is_user_limited() && !$this->is_page_allowed( $post_id ) ) {
            return \'\';
        }
        return $link;
    }

    /**
     * Removes the edit link from WP Admin Bar
     */
    public function remove_wp_admin_edit_link( $wp_admin_bar ) {
        /**
         *  If:
         *  - We\'re on a single page
         *  - The limited user is logged in
         *  - The page is not in the allowed list
         *  ...Remove the edit link from the WP Admin Bar
         */
        if ( 
            is_page() &&
            $this->is_user_limited() &&
            !$this->is_page_allowed( get_post()->ID )
        ) {
            $wp_admin_bar->remove_node( \'edit\' );
        }
    }

    /**
     * Removes the edit link from WP Admin\'s edit.php
     */
    public function remove_page_list_edit_link( $actions, $post ) {
        /**
         * If:
         * -The limited user is logged in
         * -The page is not in the allowed list
         * ...Remove the "Edit", "Quick Edit", and "Trash" quick links.
         */
        if ( 
            $this->is_user_limited() &&
            !$this->is_page_allowed( $post->ID )
        ) {
            unset( $actions[\'edit\'] );
            unset( $actions[\'inline hide-if-no-js\']);
            unset( $actions[\'trash\'] );
        }
        return $actions;
    }
}
上述代码所做的是防止以下内容在需要时工作或出现:

  1. get_edit_post_link
  2. Edit Page 页面显示的WP管理栏上的链接Edit, Quick Edit, 和Trash 中页面下方显示的快速链接/wp-admin/edit.php?post_type=page
这在我的本地WordPress 4.7安装中起到了作用。假设站点上的页面不会经常更改,最好对页面及其子页面的ID进行硬编码,并删除WP_Query 内部__construct 方法这将节省大量数据库调用。

SO网友:Ben Casey

如果您想远离插件,可以在函数中修改下面的代码。php文件或自定义插件。

此代码有两个独立的部分,您只需要使用其中的一个,但哪一个取决于需求的复杂性。

第1部分是指定单个用户并将其限制为特定的职位。

第2部分允许您创建用户和帖子ID的映射,并允许多篇帖子

下面的代码仅用于页面,但如果要将其更改为帖子或自定义帖子类型,则需要在中更改字符串$screen->id == \'page\' 去做别的事。

您可以在wp admin附近找到屏幕ID的参考here

function my_pre_get_posts( $query ){

    $screen = get_current_screen();
    $current_user = wp_get_current_user();

    /**
     * Specify a single user and restrict to a single page
     */
    $restricted_user_id = 10; //User ID of the restricted user
    $allowed_post_id = 1234; //Post ID of the allowed post

    $current_post_id = isset( $_GET[\'post\'] ) ? (int)$_GET[\'post\'] : false ;

    //Only affecting a specific user
    if( $current_user->ID !== $restricted_user_id ){
        return;
    }

    //Only Affecting EDIT page.
    if( ! $current_post_id ){
        return;
    }

    if( $screen->id == \'page\' && $current_post_id !== $allowed_post_id ){
        wp_redirect( admin_url( ) );
        exit;
    }

    /**
     * Specify a map of user_id => $allowed_posts
     */
    $restrictions_map = [
        10 => [ 123 ], //Allow user ID to edit Page ID 123
        11 => [ 152, 186 ] //Allow user ID to edit Page ID 123 and 186
    ];

    if( array_key_exists( $current_user->ID, $restrictions_map ) ){

        $allowed_posts = $restrictions_map[$current_user->ID];

        if( $screen->id == \'page\' && ! in_array( $current_user->ID, $allowed_posts ) ){
            wp_redirect( admin_url( ) );
            exit;
        }

    }

}
add_action( \'pre_get_posts\', \'my_pre_get_posts\' );

SO网友:user2319361

我用过User Role Editor 好几次了,还不错。也许这对你也有帮助。这里是链接User Role Editor

结束

相关推荐

具有序列化的自定义元值的GET_USERS

我正在尝试使用get_users 选择只有特定元值的用户。在这种情况下,元键是extraInfo 但这些值位于序列化数组中。我可以这样把用户拉出来吗?这就是我一直在尝试的,但运气不佳:$meta_key = \'extraInfo[zip]\'; $meta_value = $zip; $query = get_users(\'meta_key=\'.$meta_key.\'&meta_value=\'.$meta_value);