อนุญาตให้ผู้ใช้แก้ไขเฉพาะบางหน้า


16

ฉันต้องการอนุญาตให้ผู้ใช้บางคนแก้ไขหน้าเดียวได้และเป็นหน้าย่อย สิ่งนี้จะเป็นไปได้อย่างไร ฉันลองใช้ Role Scoper แบบเก่า แต่ดูเหมือนว่าจะมีปัญหาและข้อบกพร่องมากมาย


2
ฉันลบคำขอของคุณสำหรับคำแนะนำปลั๊กอินตามที่ทำให้เกิดคำถามนอกหัวข้อ ใช่สิ่งนี้ควรเป็นไปได้ด้วยปลั๊กอิน แต่เมื่อฉันเห็นความพยายามที่จะทำสิ่งต่าง ๆ ที่ต้องการการแฮ็กฟังก์ชันการทำงานพื้นฐานแบบนี้ฉันไม่สามารถช่วยได้ แต่คิดว่าคุณกำลังทำผิดวิธี คุณสามารถอธิบายรายละเอียดโครงการเพิ่มเติมได้หรือไม่
s_ha_dum

คำตอบ:


14

สิ่งแรกที่ต้องทำเพื่อปรับใช้ภารกิจดังกล่าวคือเพื่อให้สามารถจดจำหน้าที่ผู้ใช้สามารถแก้ไขได้

มีหลายวิธีที่จะทำ อาจเป็นเมตาของผู้ใช้ค่าการกำหนดค่าบางอย่าง ... เพื่อประโยชน์ของคำตอบนี้ฉันจะสมมติว่ามีฟังก์ชัน lile อยู่:

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 จะทำหน้าที่เหลือ: จะลบลิงก์แก้ไขใด ๆ จากแบ็กเอนด์และส่วนหน้าจะป้องกันการเข้าถึงโดยตรง ... และอื่น ๆ


3
นี้ดีกว่าคำตอบของฉัน ทำไม จำกัด การแก้ไขลิงก์เมื่อคุณสามารถแก้ไขความสามารถของผู้ใช้และให้ WordPress จัดการส่วนที่เหลือได้?
ricotheque

คุณควรใช้ "a" หน้าคำว่า "ผู้ใช้" ไม่ใช่ "an" เพราะเสียง "u" ที่ยาวเช่น "yu" ซึ่งเริ่มต้นด้วยพยัญชนะ
Philip

7

ใช้รหัสเพียงเล็กน้อยเพื่อใช้คุณลักษณะนี้แม้ว่าคุณจะใช้คลาส 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 Admin Bar ที่ปรากฏขึ้นสำหรับหน้า
  3. Edit,, Quick EditและTrashลิงค์ด่วนที่ปรากฏด้านล่างของเพจใน/wp-admin/edit.php?post_type=page

สิ่งนี้ใช้ได้กับการติดตั้ง WordPress 4.7 ในเครื่องของฉัน สมมติว่าหน้าในเว็บไซต์จะไม่เปลี่ยนแปลงบ่อยครั้งมันอาจเป็นการดีกว่าที่จะ hardcode รหัสของหน้าและหน้าย่อยและลบWP_Queryภายใน__constructวิธี สิ่งนี้จะประหยัดมากในการโทรฐานข้อมูล


+1 สำหรับคำตอบที่สมบูรณ์มากกว่า @ Ben แต่วิธีที่ถูกต้องในการจัดการลิงก์คือการจัดการความสามารถ
Mark Kaplun

ใช่เมื่อฉันเห็นคำตอบของ gmazzap ฉันคิดว่า "ทำไมฉันไม่คิดอย่างนั้นล่ะ?"
ricotheque

5

หากคุณต้องการหลีกเลี่ยงปลั๊กอินคุณสามารถเปลี่ยนแปลงรหัสด้านล่างในไฟล์ functions.php หรือปลั๊กอินที่กำหนดเอง

มี 2 ​​ส่วนแยกจากกันในรหัสนี้คุณจะต้องใช้ 1 ชิ้นส่วนเท่านั้น แต่ชิ้นส่วนใดขึ้นอยู่กับความซับซ้อนของข้อกำหนด

ส่วนที่ 1 ระบุผู้ใช้รายเดียวและ จำกัด การโพสต์ไว้เฉพาะ

ส่วนที่ 2 ช่วยให้คุณสร้างแผนที่ของผู้ใช้และรหัสโพสต์และอนุญาตให้โพสต์หลายรายการ

รหัสด้านล่างมีไว้สำหรับหน้าเท่านั้น แต่หากคุณต้องการเปลี่ยนเป็นโพสต์หรือประเภทโพสต์ที่กำหนดเองคุณจะต้องเปลี่ยนสตริง$screen->id == 'page'เป็นอย่างอื่น

คุณสามารถค้นหาการอ้างอิงถึง ID หน้าจอของ wp-admin ที่นี่

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 เนื่องจากสามารถใช้งานฟังก์ชันการทำงานหลักได้ แต่ยังคงทิ้งลิงก์ไว้เพื่อแก้ไขหน้าที่กำลังแสดงผลแม้กับผู้ใช้ที่ไม่สามารถแก้ไขได้ซึ่งทำให้ UI ไม่ดี
Mark Kaplun

-4

ฉันใช้User Role Editorสองสามครั้งและค่อนข้างดี บางทีมันอาจช่วยคุณได้เช่นกัน นี่คือลิงค์User Role Editor


ดูเหมือนจะเป็นปลั๊กอินทึบ แต่ฉันไม่สามารถหาวิธี จำกัด ผู้ใช้ในการแก้ไขหน้าเฉพาะ
naf

กำหนดให้ผู้ใช้ที่คุณต้องการ จำกัด วิธีนี้ผู้ใช้ระดับผู้เขียนเพิ่มความสามารถ "edit_pages" ให้กับระดับผู้ใช้ผู้เขียน (โดยใช้ตัวแก้ไขบทบาทผู้ใช้) ตั้งค่าผู้เขียนหน้าให้ผู้ใช้ที่คุณต้องการให้สิทธิ์ในการแก้ไข ผู้ใช้ระดับผู้แต่งที่ได้รับความสามารถของ edit_pages สามารถดูรายการหน้าในแดชบอร์ด แต่ไม่มีตัวเลือกในการแก้ไขยกเว้นสำหรับหน้าเว็บที่พวกเขาเป็นผู้เขียน
2319361

4
ขอบคุณที่ใช้งานได้ในระดับหนึ่ง ในบางจุดฉันอาจต้อง จำกัด ผู้ใช้หลายคนในการแก้ไขหน้าเฉพาะดังนั้นจึงจำเป็นต้องมีวิธีในการตั้งค่าผู้เขียนหลายคนในหน้า
naf

ในการ จำกัด ผู้ใช้เฉพาะบางหน้าคุณจะต้องซื้อ Pro versoin ฉันกำลังมองหาสิ่งเดียวกันและพบว่า wordpress.stackexchange.com/questions/191658/…
Ricardo Andres

1
ในขณะที่ปลั๊กอินที่เฉพาะเจาะจงเป็นสิ่งที่มั่นคงในขณะนี้มันอาจจะง่ายต่อการเขียนรหัสที่จะทำกว่าลุยในตัวเลือกทั้งหมดที่ปลั๊กอินให้ (ถ้ามันยังช่วยให้คุณทำสิ่งที่ OP ถาม)
Mark Kaplun
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.