Permite utilizatorului să editeze doar anumite pagini

16 iun. 2015, 17:15:25
Vizualizări: 26.3K
Voturi: 17

Aș dori să permit unui anumit utilizator să editeze doar o pagină și subpaginile acesteia. Cum ar fi posibil acest lucru? Am încercat vechiul Role Scoper, dar pare să aibă multe probleme și bug-uri.

1
Comentarii

Am eliminat solicitarea ta pentru o recomandare de plugin, deoarece aceasta a făcut întrebarea să fie în afara subiectului. Da, acest lucru ar trebui să fie posibil cu un plugin, dar când văd încercări de a face lucruri care necesită acest fel de modificare a funcționalității de bază, nu pot să nu mă gândesc că ai o abordare greșită. Poți să explici proiectul mai în detaliu?

s_ha_dum s_ha_dum
16 iun. 2015 17:44:12
Toate răspunsurile la întrebare 4
2
17

Primul lucru de făcut pentru a implementa o astfel de sarcină este să poți recunoaște ce pagină poate edita un utilizator.

Există diferite metode pentru a face acest lucru. Ar putea fi un metadate al utilizatorului, o valoare de configurare... În scopul acestui răspuns, voi presupune că există o funcție de genul acesta:

function wpse_user_can_edit( $user_id, $page_id ) {

   $page = get_post( $page_id );

   // să găsim pagina cea mai de sus în ierarhie
   while( $page && (int) $page->parent ) {
     $page = get_post( $page->parent );
   }

   if ( ! $page ) {
     return false;
   }

   // acum $page este pagina de top în ierarhie
   // cum să știm dacă un utilizator o poate edita, depinde de tine...

}

Acum că avem o metodă de a determina dacă un utilizator poate edita o pagină, trebuie doar să spunem WordPress să folosească această funcție pentru a verifica capacitatea utilizatorului de a edita o pagină.

Aceasta se poate realiza prin intermediul filtrului 'map_meta_cap'.

Ceva de genul:

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

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

    // Dacă capacitatea filtrată nu ne interesează, returnăm valoarea curentă
    if ( ! in_array( $cap, $to_filter, true ) ) {
        return $caps;
    }

    // Primul element din array-ul $args ar trebui să fie ID-ul paginii
    if ( ! $args || empty( $args[0] ) || ! wpse_user_can_edit( $user_id, $args[0] ) ) {
        // Utilizatorul nu are permisiunea, să comunicăm asta către WP
        return [ 'do_not_allow' ];
    }
    // Altfel returnăm valoarea curentă
    return $caps;

}, 10, 4 );

În acest moment, avem nevoie doar de o metodă de a conecta un utilizator la una sau mai multe pagini.

Pot exista diferite soluții în funcție de cazul de utilizare.

O soluție flexibilă ar putea fi adăugarea unui meniu derulant cu pagini "rădăcină" (vezi wp_dropdown_pages) în ecranul de administrare pentru editarea utilizatorului, și salvarea paginii/paginilor selectate ca metadate ale utilizatorului.

Am putea folosi 'edit_user_profile' pentru a adăuga câmpul meniu derulant și 'edit_user_profile_update' pentru a stoca valoarea selectată ca metadate ale utilizatorului.

Sunt sigur că pe acest site există suficiente informații despre cum să facem acest lucru în detaliu.

Când paginile sunt stocate ca metadate ale utilizatorului, funcția wpse_user_can_edit() de mai sus poate fi finalizată prin verificarea dacă ID-ul paginii face parte din valoarea metadatelor utilizatorului.

Eliminând capacitatea de a edita pagina, WordPress va face restul: va elimina orice link de editare din backend și frontend, va preveni accesul direct... și așa mai departe.

14 mar. 2017 12:07:19
Comentarii

Acest lucru este mult mai bun decât răspunsul meu. De ce să limitezi linkurile de editare când poți pur și simplu să modifici capabilitățile utilizatorului și să lași WordPress să se ocupe de restul?

ricotheque ricotheque
19 mar. 2017 19:04:19

ar trebui să folosești "a" înaintea cuvântului "user" și nu "an" deoarece sunetul lung al lui "u" se aude ca "yu" care începe cu o consoană.

Philip Philip
10 dec. 2019 21:16:39
2

Este nevoie de o cantitate mică de cod pentru a implementa această funcționalitate, chiar dacă folosești o clasă PHP pentru a evita variabilele globale. De asemenea, nu am vrut să ascund paginile interzise pentru utilizator în Panoul de control. Ce se întâmplă dacă au adăugat conținut care era deja pe site?

$user_edit_limit = new NS_User_Edit_Limit(
    15,       // ID-ul utilizatorului pe care vrem să-l limităm
    [2, 17]   // Matricea ID-urilor paginilor părinte pe care utilizatorul are voie să le editeze
                 (acceptă și ID-uri de sub-pagini)
);

class NS_User_Edit_Limit {

    /**
     * Stochează ID-ul utilizatorului pe care vrem să-l controlăm și
     * postările pe care le vom permite utilizatorului să le editeze.
     */
    private $user_id = 0;
    private $allowed = array();

    public function __construct( $user_id, $allowed ) {

        // Salvează ID-ul utilizatorului pe care vrem să-l limităm.
        $this->user_id = $user_id;

        // Extinde lista de pagini permise pentru a include sub-paginile
        $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;
            }
        }

        // Pentru utilizatorul interzis...
        // Elimină link-ul de editare din front-end după caz
        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 );
        // Elimină link-ul de editare din wp-admin după caz
        add_action( 'page_row_actions', array( $this, 'remove_page_list_edit_link' ), 10, 2 );
    }

    /**
     * Funcții ajutătoare care verifică dacă utilizatorul curent este cel
     * pe care vrem să-l limităm și verifică dacă o anumită postare este în lista
     * noastră de postări pe care le permitem utilizatorului să le editeze.
     */
    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 );
    }

    /**
     * Elimină link-ul de editare din front-end după caz.
     */
    public function remove_edit_link( $link, $post_id, $test ) {
        /**
         * Dacă...
         * - Utilizatorul limitat este autentificat
         * - Pagina pentru care se creează link-ul de editare nu este în lista permisă
         * ...returnează un $link gol. Acest lucru face și ca edit_post_link() să nu afișeze nimic.
         *
         * Altfel, returnează link-ul normal.
         */
        if ( $this->is_user_limited() && !$this->is_page_allowed( $post_id ) ) {
            return '';
        }
        return $link;
    }

    /**
     * Elimină link-ul de editare din Bara de administrare WP
     */
    public function remove_wp_admin_edit_link( $wp_admin_bar ) {
        /**
         *  Dacă:
         *  - Suntem pe o singură pagină
         *  - Utilizatorul limitat este autentificat
         *  - Pagina nu este în lista permisă
         *  ...Elimină link-ul de editare din Bara de administrare WP
         */
        if ( 
            is_page() &&
            $this->is_user_limited() &&
            !$this->is_page_allowed( get_post()->ID )
        ) {
            $wp_admin_bar->remove_node( 'edit' );
        }
    }

    /**
     * Elimină link-ul de editare din edit.php al WP Admin
     */
    public function remove_page_list_edit_link( $actions, $post ) {
        /**
         * Dacă:
         * - Utilizatorul limitat este autentificat
         * - Pagina nu este în lista permisă
         * ...Elimină link-urile rapide "Editare", "Editare rapidă" și "Coș de gunoi".
         */
        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;
    }
}

Ceea ce face codul de mai sus este să prevină următoarele lucruri să funcționeze sau să apară după caz:

  1. get_edit_post_link
  2. Linkul Editare Pagină din Bara de administrare WP care apare pentru Pagini
  3. Linkurile rapide Editare, Editare rapidă și Coș de gunoi care apar sub Pagini în /wp-admin/edit.php?post_type=page

Acest cod a funcționat pe instalarea mea locală de WordPress 4.7. Presupunând că paginile de pe site nu se vor schimba des, ar putea fi mai bine să hardcodezi ID-urile paginii și sub-paginilor sale și să elimini WP_Query din metoda __construct. Acest lucru va economisi multe apeluri la baza de date.

14 mar. 2017 11:26:20
Comentarii

+1 pentru răspunsul mai complet decât cel al lui @Ben, dar modul corect de a gestiona linkurile este prin manipularea capabilităților,

Mark Kaplun Mark Kaplun
19 mar. 2017 07:35:42

Da, când am văzut răspunsul lui gmazzap am ajuns să mă gândesc "De ce naiba nu m-am gândit la asta?"

ricotheque ricotheque
19 mar. 2017 19:05:07
1

Dacă dorești să eviți plugin-urile, poți folosi o variantă a codului de mai jos în fișierul functions.php sau într-un plugin personalizat.

Există 2 părți separate în acest cod, ai nevoie doar de una dintre ele, dar alegerea depinde de complexitatea cerințelor.

Partea 1 specifică un singur utilizator și îl restricționează la un anumit articol.

Partea 2 îți permite să creezi o mapă de utilizatori și ID-uri de articole și permite mai multe articole.

Codul de mai jos este doar pentru o pagină, dar dacă vrei să schimbi asta într-un articol sau un tip personalizat de postare, trebuie să modifici string-ul din $screen->id == 'page' cu altceva.

Poți găsi o referință pentru ID-urile de ecran în wp-admin aici

function my_pre_get_posts( $query ){

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

    /**
     * Specifică un singur utilizator și restricționează la o singură pagină
     */
    $restricted_user_id = 10; //ID-ul utilizatorului restricționat
    $allowed_post_id = 1234; //ID-ul articolului permis

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

    //Afectează doar un utilizator specific
    if( $current_user->ID !== $restricted_user_id ){
        return;
    }

    //Afectează doar pagina de EDITARE.
    if( ! $current_post_id ){
        return;
    }

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

    /**
     * Specifică o mapă de user_id => $allowed_posts
     */
    $restrictions_map = [
        10 => [ 123 ], //Permite userului cu ID să editeze Pagina cu ID 123
        11 => [ 152, 186 ] //Permite userului cu ID să editeze Paginile cu ID 123 și 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' );
14 mar. 2017 11:26:51
Comentarii

+1, deoarece poate funcționa pentru a realiza funcționalitatea de bază, dar acest lucru încă lasă linkurile pentru editarea paginilor afișate chiar și pentru utilizatorii care nu le pot edita, ceea ce creează o interfață neplăcută

Mark Kaplun Mark Kaplun
19 mar. 2017 07:29:56
5
-4

Am folosit User Role Editor de câteva ori și este destul de bun. Poate te-ar putea ajuta și pe tine. Iată linkul User Role Editor

16 iun. 2015 17:31:25
Comentarii

Pare a fi un plugin solid, dar nu găsesc o modalitate de a restricționa un utilizator să editeze anumite pagini.

naf naf
16 iun. 2015 17:35:42

Faceți utilizatorii pe care doriți să-i limitați în acest fel utilizatori de nivel autor Adăugați capabilitatea "edit_pages" la nivelul de utilizator autor (folosind User Role Editor) Setați autorul unei pagini la utilizatorul căruia doriți să-i acordați privilegiul de a o edita. Un utilizator de nivel autor căruia i se acordă capabilitatea de edit_pages poate vedea lista de pagini în panoul de control, dar nu are opțiunea de a edita decât paginile al căror autor este.

user2319361 user2319361
16 iun. 2015 17:46:00

Mulțumesc, funcționează într-o oarecare măsură. La un moment dat ar putea fi necesar să am mai mulți utilizatori restricționați să modifice o anumită pagină, deci ar trebui să existe o modalitate de a seta mai mulți autori pentru o pagină.

naf naf
16 iun. 2015 17:59:38

Pentru a restricționa utilizatorii la anumite pagini, va trebui să achiziționați versiunea Pro. Căutam același lucru și am aflat asta. http://wordpress.stackexchange.com/questions/191658/allowing-user-to-edit-only-certain-pages/191661#191661?s=f87626a8cf184588bca7c4e397c972a4

Ricardo Andres Ricardo Andres
3 mar. 2017 16:32:08

deși acel plugin specific este o soluție bună acum, este probabil mai ușor să scrii cod pentru a face asta decât să te lupți cu toate opțiunile pe care le oferă pluginul. (dacă măcar îți permite să faci ceea ce cere OP)

Mark Kaplun Mark Kaplun
14 mar. 2017 06:25:41