Cho phép người dùng chỉ chỉnh sửa một số trang nhất định


16

Tôi muốn cho phép một số người dùng nhất định chỉ chỉnh sửa một trang và đó là các trang con. Làm thế nào điều này sẽ có thể? Tôi đã thử vai trò Scoper cũ, nhưng nó dường như có rất nhiều vấn đề và lỗi.


2
Tôi đã xóa yêu cầu của bạn về một đề xuất plugin vì điều đó làm cho câu hỏi lạc đề. Có, điều này có thể thực hiện được với một plugin nhưng khi tôi thấy những nỗ lực để thực hiện những việc đòi hỏi loại hack chức năng cơ bản này, tôi không thể không nghĩ rằng bạn đang sử dụng sai phương pháp. Bạn có thể giải thích dự án chi tiết hơn?
s_ha_dum

Câu trả lời:


14

Điều đầu tiên cần làm để thực hiện nhiệm vụ đó là có thể nhận ra trang nào người dùng có thể chỉnh sửa.

Có nhiều cách khác nhau để làm điều đó. Nó có thể là một meta người dùng, một số giá trị cấu hình ... Vì lợi ích của câu trả lời này, tôi sẽ giả sử rằng một hàm tồn tại:

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...

}

Bây giờ chúng tôi có một cách để xác định xem người dùng có thể chỉnh sửa trang hay không, chúng tôi chỉ cần yêu cầu WordPress sử dụng chức năng này để kiểm tra khả năng của người dùng để chỉnh sửa trang.

Điều đó có thể được thực hiện thông qua 'map_meta_cap' bộ lọc.

Cái gì đó như:

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 );

Tại thời điểm này, chúng tôi chỉ cần một cách để kết nối người dùng với một hoặc nhiều trang.

Có thể có các giải pháp khác nhau tùy thuộc vào trường hợp sử dụng.

Một giải pháp linh hoạt có thể là thêm một trang "gốc" thả xuống (xem wp_dropdown_pages ) vào màn hình quản trị người dùng chỉnh sửa và lưu (các) trang đã chọn làm meta người dùng.

Chúng tôi có thể tận dụng 'edit_user_profile'để thêm trường thả xuống trang và 'edit_user_profile_update'lưu trữ giá trị được chọn làm meta người dùng.

Tôi chắc chắn rằng trong trang web này có đủ hướng dẫn về cách chi tiết.

Khi (các) trang được lưu trữ dưới dạng meta người dùng, wpse_user_can_edit()chức năng từ phía trên có thể được kết thúc bằng cách kiểm tra xem id trang có phải là một phần của giá trị meta người dùng hay không.

Xóa khả năng chỉnh sửa trang, WordPress sẽ thực hiện phần còn lại: sẽ xóa mọi liên kết chỉnh sửa khỏi phụ trợ và giao diện, sẽ ngăn truy cập trực tiếp ... v.v.


3
Điều này tốt hơn nhiều so với câu trả lời của tôi. Tại sao phải giới hạn các liên kết chỉnh sửa khi bạn chỉ có thể sửa đổi khả năng của người dùng và để WordPress xử lý phần còn lại?
ricotheque

bạn nên sử dụng "a" trước từ "user" chứ không phải "an" bởi vì một "u" dài phát ra âm "yu" bắt đầu bằng một phụ âm.
Philip

7

Phải mất một lượng nhỏ mã để thực hiện tính năng này, ngay cả khi bạn sử dụng lớp PHP để tránh các biến toàn cục. Tôi cũng không muốn ẩn các trang bị cấm đối với người dùng trong Bảng điều khiển. Điều gì nếu họ thêm nội dung đã có trên trang web?

$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;
    }
}

Những gì đoạn mã trên làm là ngăn những thứ sau hoạt động hoặc xuất hiện khi cần thiết:

  1. get_edit_post_link
  2. Edit Page liên kết trên Thanh quản trị WP xuất hiện cho Trang
  3. Edit, Quick EditTrashcác liên kết nhanh xuất hiện bên dưới Trang trong/wp-admin/edit.php?post_type=page

Điều này làm việc trên cài đặt WordPress 4.7 cục bộ của tôi. Giả sử rằng các trang trên trang web sẽ không thay đổi thường xuyên, có thể tốt hơn là mã hóa ID của trang và các trang phụ của nó và xóa phương thức WP_Querybên trong __construct. Điều này sẽ tiết kiệm rất nhiều cho các cuộc gọi cơ sở dữ liệu.


+1 cho câu trả lời đầy đủ hơn @ Ben nhưng cách xử lý các liên kết đúng là bằng cách thao túng các khả năng,
Mark Kaplun

Vâng, khi tôi thấy câu trả lời của gmazzap, cuối cùng tôi đã nghĩ "Bây giờ tại sao tôi không nghĩ về điều đó?"
ricotheque

5

Nếu bạn muốn tránh xa các plugin, bạn có thể biến thể mã bên dưới trong tệp tin.php. Hoặc một plugin tùy chỉnh.

Có 2 phần riêng biệt cho mã này, Bạn sẽ chỉ cần sử dụng 1 trong số đó, nhưng phần nào phụ thuộc vào độ phức tạp của các yêu cầu.

Phần 1 là chỉ định một người dùng và giới hạn họ vào một bài đăng cụ thể.

Phần 2 cho phép bạn tạo bản đồ người dùng và đăng ID và cho phép nhiều bài đăng

Mã dưới đây chỉ dành cho một trang, nhưng nếu bạn muốn thay đổi nó thành một bài đăng, hoặc một loại bài đăng tùy chỉnh, bạn sẽ cần phải thay đổi chuỗi $screen->id == 'page'thành một thứ khác.

Bạn có thể tìm thấy một tham chiếu đến ID màn hình xung quanh wp-admin tại đây

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' );

1
+1 vì nó có thể hoạt động để thực hiện chức năng cốt lõi, nhưng điều này vẫn để lại các liên kết để chỉnh sửa các trang đang được xuất ngay cả với những người dùng không thể chỉnh sửa chúng, điều này tạo ra một UI xấu
Mark Kaplun 19/03/2017

-4

Tôi đã sử dụng User Role Editormột vài lần và là khá tốt. Có lẽ nó cũng có thể giúp bạn. Đây là liên kết Trình chỉnh sửa vai trò người dùng


Có vẻ là một plugin vững chắc, nhưng tôi không thể tìm ra cách hạn chế người dùng chỉnh sửa các trang cụ thể.
NAF

Làm cho người dùng bạn muốn giới hạn theo cách này người dùng ở cấp độ tác giả Thêm khả năng "edit_pages" vào cấp độ người dùng tác giả (sử dụng Trình soạn thảo vai trò người dùng) Đặt tác giả của trang cho người dùng mà bạn muốn cấp đặc quyền chỉnh sửa nó. Người dùng ở cấp độ tác giả được cung cấp khả năng của edit_pages có thể xem danh sách các trang trong bảng điều khiển, nhưng không có tùy chọn chỉnh sửa ngoại trừ các trang mà họ là tác giả.
dùng2319361

4
Cảm ơn, điều đó làm việc đến một mức độ. Tại một số điểm tôi có thể phải hạn chế nhiều người dùng để sửa đổi một trang cụ thể, vì vậy cần có một cách để đặt nhiều tác giả vào một trang.
NAF

Để hạn chế người dùng vào các trang cụ thể, bạn sẽ cần mua phiên bản Pro. Tôi đang tìm kiếm điều tương tự và tìm thấy điều đó. wordpress.stackexchange.com/questions/191658/ từ
Ricardo Andres

1
trong khi plugin cụ thể đó là một điều chắc chắn ngay bây giờ, có lẽ việc viết mã để làm điều đó có thể dễ dàng hơn so với lội trong tất cả các tùy chọn mà plugin cung cấp. (nếu nó thậm chí cho phép bạn làm những gì OP yêu cầu)
Mark Kaplun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.