Benutzer darf nur bestimmte Seiten bearbeiten

16

Ich möchte bestimmten Benutzern erlauben, nur eine Seite und ihre Unterseiten zu bearbeiten. Wie wäre das möglich? Ich habe den alten Role Scoper ausprobiert, aber er scheint viele Probleme und Fehler zu haben.

naf
quelle
2
Ich habe Ihre Anfrage nach einer Plugin-Empfehlung entfernt, da die Frage dadurch nicht mehr zum Thema gehört. Ja, dies sollte mit einem Plugin möglich sein, aber wenn ich Versuche sehe, Dinge zu tun, die diese Art des Hackens grundlegender Funktionen erfordern, kann ich nicht anders, als zu glauben, dass Sie den falschen Ansatz verfolgen. Können Sie das Projekt näher erläutern?
s_ha_dum

Antworten:

14

Das erste, was Sie tun müssen, um eine solche Aufgabe zu implementieren, ist zu erkennen, welche Seite ein Benutzer bearbeiten kann.

Es gibt verschiedene Möglichkeiten, dies zu tun. Es könnte ein Benutzer-Meta sein, ein Konfigurationswert ... Um diese Antwort beantworten zu können, gehe ich davon aus, dass eine andere Funktion existiert:

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

}

Da wir nun eine Möglichkeit haben, festzustellen, ob ein Benutzer eine Seite bearbeiten kann, müssen wir WordPress lediglich anweisen, diese Funktion zu verwenden, um die Benutzerkapazität zum Bearbeiten einer Seite zu überprüfen.

Dies kann über 'map_meta_cap'Filter erfolgen.

Etwas wie:

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

An diesem Punkt müssen wir nur einen Weg verbinden einen Benutzer zu einer oder mehreren Seiten.

Je nach Anwendungsfall kann es unterschiedliche Lösungen geben.

Eine flexible Lösung könnte darin bestehen, wp_dropdown_pagesdem Bearbeitungsbildschirm für Benutzeradministratoren ein Dropdown-Menü mit Stammseiten (siehe ) hinzuzufügen und ausgewählte Seiten als Benutzer-Meta zu speichern.

Wir können 'edit_user_profile'das Dropdown-Feld Seiten hinzufügen und 'edit_user_profile_update'den ausgewählten Wert als Benutzer-Meta speichern.

Ich bin sicher, dass es auf dieser Website genügend Anleitungen dazu gibt.

Wenn Seiten als Benutzer-Meta gespeichert werden, kann die wpse_user_can_edit()Funktion von oben beendet werden, indem überprüft wird, ob die Seiten-ID Teil des Benutzer-Meta-Werts ist.

Wenn Sie die Fähigkeit zum Bearbeiten der Seite entfernen, erledigt WordPress den Rest: Entfernt alle Bearbeitungslinks vom Backend und Frontend, verhindert den direkten Zugriff ... und so weiter.

gmazzap
quelle
3
Das ist viel besser als meine Antwort. Warum sollten Sie Bearbeitungslinks einschränken, wenn Sie nur die Funktionalität des Benutzers ändern und WordPress den Rest erledigen lassen können?
Ricotheque
Sie sollten "a" vor dem Wort "user" und nicht "an" verwenden, da ein langes "u" wie "yu" klingt und mit einem Konsonanten beginnt.
Philip
7

Die Implementierung dieser Funktion erfordert nur wenig Code, selbst wenn Sie eine PHP-Klasse verwenden, um globale Variablen zu vermeiden. Ich wollte auch nicht die verbotenen Seiten für den Benutzer im Dashboard verstecken. Was passiert, wenn Inhalte hinzugefügt werden, die bereits auf der Website vorhanden sind?

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

Der obige Code verhindert, dass Folgendes funktioniert oder angezeigt wird:

  1. get_edit_post_link
  2. Edit Page Link in der WP-Admin-Leiste, die für die Seiten angezeigt wird
  3. Edit, Quick EditUnd Trashschnelle Verbindungen , die unter den Seiten erscheinen in/wp-admin/edit.php?post_type=page

Dies funktionierte auf meiner lokalen WordPress 4.7-Installation. Unter der Annahme, dass sich die Seiten auf der Site nicht oft ändern, ist es möglicherweise besser, die IDs der Seite und ihrer Unterseiten fest zu codieren und das WP_QueryInnere der __constructMethode zu entfernen . Dies spart viel bei Datenbankaufrufen.

Ricothek
quelle
+1 für die vollständigere Antwort als @ Bens, aber der richtige Weg, um mit den Links umzugehen, ist die Manipulation der Fähigkeiten,
Mark Kaplun
Ja, als ich die Antwort von gmazzap sah, dachte ich: "Warum habe ich nicht daran gedacht?"
Ricotheque
5

Wenn Sie sich von Plugins fernhalten möchten, können Sie den folgenden Code in einer functions.php-Datei oder einem benutzerdefinierten Plugin ändern.

Es gibt 2 separate Teile für diesen Code. Sie müssten nur einen davon verwenden. Welcher davon jedoch verwendet wird, hängt von der Komplexität der Anforderungen ab.

In Teil 1 wird ein einzelner Benutzer angegeben und auf einen bestimmten Beitrag beschränkt.

In Teil 2 können Sie eine Karte mit Benutzern und Beitrags-IDs erstellen und mehrere Beiträge erstellen

Der folgende Code gilt nur für eine Seite, aber wenn Sie diesen in einen Beitrag oder einen benutzerdefinierten Beitragstyp ändern möchten, müssen Sie die Zeichenfolge in $screen->id == 'page'einen anderen ändern .

Einen Verweis auf die Bildschirm-IDs rund um wp-admin finden Sie hier

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' );
Ben Casey
quelle
1
+1 wie es funktionieren kann, um die Kernfunktionalität zu tun, aber dies lässt die Links zum Bearbeiten der ausgegebenen Seiten auch für Benutzer, die sie nicht bearbeiten können, was eine schlechte Benutzeroberfläche macht
Mark Kaplun
-4

Ich habe User Role Editorein paar Mal verwendet und ist ziemlich gut. Vielleicht könnte es dir auch helfen. Hier ist der Link User Role Editor

user2319361
quelle
Scheint ein solides Plugin zu sein, aber ich kann keinen Weg finden, einen Benutzer auf das Bearbeiten bestimmter Seiten zu beschränken.
Naf
Festlegen der Benutzer, die auf diese Weise eingeschränkt werden sollen Benutzer auf Autorenebene Hinzufügen der Funktion "edit_pages" zur Autorenbenutzerebene (mithilfe des Benutzerrollen-Editors) Legen Sie den Autor einer Seite auf den Benutzer fest, dem Sie die Berechtigung zum Bearbeiten erteilen möchten. Ein Benutzer auf Autorenebene mit der Berechtigung edit_pages kann die Liste der Seiten im Dashboard anzeigen, hat jedoch keine Bearbeitungsoption, außer für Seiten, deren Autor er ist.
user2319361
4
Danke, das funktioniert einigermaßen. Irgendwann müssen möglicherweise mehrere Benutzer eingeschränkt werden, um eine bestimmte Seite zu ändern, sodass mehrere Autoren auf eine Seite festgelegt werden können müssen.
Naf
Um Benutzer auf bestimmte Seiten zu beschränken, müssen Sie die Pro-Version erwerben. Ich suche das Gleiche und habe es herausgefunden. wordpress.stackexchange.com/questions/191658/…
Ricardo Andres
1
Während dieses spezielle Plugin derzeit eine solide Sache ist, ist es wahrscheinlich einfacher, Code dafür zu schreiben, als alle Optionen, die das Plugin bietet, zu nutzen. (Wenn es sogar erlaubt, das zu tun, was der OP verlangt)
Mark Kaplun