Consentire all'utente di modificare solo determinate pagine

16 giu 2015, 17:15:25
Visualizzazioni: 26.3K
Voti: 17

Vorrei consentire a determinati utenti di modificare solo una pagina e le sue sottopagine. Come sarebbe possibile? Ho provato il vecchio Role Scoper, ma sembra avere molti problemi e bug.

1
Commenti

Ho rimosso la tua richiesta di un plugin consigliato poiché rendeva la domanda off-topic. Sì, questo dovrebbe essere possibile con un plugin, ma quando vedo tentativi di fare cose che richiedono questo tipo di hacking della funzionalità di base, non posso fare a meno di pensare che tu stia adottando l'approccio sbagliato. Puoi spiegare il progetto in modo più dettagliato?

s_ha_dum s_ha_dum
16 giu 2015 17:44:12
Tutte le risposte alla domanda 4
2
17

La prima cosa da fare per implementare questo compito è essere in grado di riconoscere quale pagina un utente può modificare.

Ci sono diversi modi per farlo. Potrebbe essere un meta utente, qualche valore di configurazione... Per semplificare questa risposta, assumerò che esista una funzione come questa:

function wpse_user_can_edit( $user_id, $page_id ) {

   $page = get_post( $page_id );

   // troviamo la pagina più in alto nella gerarchia
   while( $page && (int) $page->parent ) {
     $page = get_post( $page->parent );
   }

   if ( ! $page ) {
     return false;
   }

   // ora $page è la pagina principale nella gerarchia
   // come determinare se un utente può modificarla, dipende da te...

}

Ora che abbiamo un modo per determinare se un utente può modificare una pagina, dobbiamo solo dire a WordPress di usare questa funzione per verificare la capacità dell'utente di modificare una pagina.

Questo può essere fatto tramite il filtro 'map_meta_cap'.

Qualcosa come:

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

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

    // Se la capacità filtrata non ci interessa, restituiamo il valore corrente
    if ( ! in_array( $cap, $to_filter, true ) ) {
        return $caps;
    }

    // Il primo elemento nell'array $args dovrebbe essere l'ID della pagina
    if ( ! $args || empty( $args[0] ) || ! wpse_user_can_edit( $user_id, $args[0] ) ) {
        // L'utente non è autorizzato, comunichiamolo a WP
        return [ 'do_not_allow' ];
    }
    // Altrimenti restituiamo il valore corrente
    return $caps;

}, 10, 4 );

A questo punto, ci serve solo un modo per collegare un utente a una o più pagine.

Potrebbero esserci diverse soluzioni a seconda del caso d'uso.

Una soluzione flessibile potrebbe essere aggiungere un dropdown di pagine "radice" (vedi wp_dropdown_pages) alla schermata di modifica utente nel backend, e salvare la pagina selezionata come meta utente.

Possiamo sfruttare 'edit_user_profile' per aggiungere il campo dropdown delle pagine e 'edit_user_profile_update' per salvare il valore selezionato come meta utente.

Sono sicuro che in questo sito ci sono abbastanza guide su come farlo nel dettaglio.

Quando le pagine sono salvate come meta utente, la funzione wpse_user_can_edit() di cui sopra può essere completata verificando se l'ID della pagina fa parte del valore meta dell'utente.

Rimuovendo la capacità di modificare la pagina, WordPress farà il resto: rimuoverà ogni link di modifica dal backend e frontend, impedirà l'accesso diretto... e così via.

14 mar 2017 12:07:19
Commenti

Questa soluzione è molto migliore della mia. Perché limitare i link di modifica quando puoi semplicemente modificare le capacità dell'utente e lasciare che WordPress gestisca il resto?

ricotheque ricotheque
19 mar 2017 19:04:19

dovresti usare "a" prima della parola "user" e non "an" perché una "u" lunga suona come "yu" che inizia con una consonante.

Philip Philip
10 dic 2019 21:16:39
2

Implementare questa funzionalità richiede una piccola quantità di codice, anche se si utilizza una classe PHP per evitare variabili globali. Inoltre, non volevo nascondere le pagine proibite per l'utente nella Dashboard. E se avessero aggiunto contenuti già presenti sul sito?

$user_edit_limit = new NS_User_Edit_Limit(
    15,       // ID dell'utente che vogliamo limitare
    [2, 17]   // Array di ID delle pagine genitore che l'utente può modificare
                 (accetta anche gli ID delle pagine figlio)
);

class NS_User_Edit_Limit {

    /**
     * Memorizza l'ID dell'utente che vogliamo controllare e i
     * post che permetteremo all'utente di modificare.
     */
    private $user_id = 0;
    private $allowed = array();

    public function __construct( $user_id, $allowed ) {

        // Salva l'ID dell'utente che vogliamo limitare.
        $this->user_id = $user_id;

        // Espande la lista delle pagine consentite per includere le pagine figlio
        $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;
            }
        }

        // Per l'utente limitato...
        // Rimuove il link di modifica dal front-end se necessario
        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 );
        // Rimuove il link di modifica da wp-admin se necessario
        add_action( 'page_row_actions', array( $this, 'remove_page_list_edit_link' ), 10, 2 );
    }

    /**
     * Funzioni helper che verificano se l'utente corrente è quello
     * che vogliamo limitare e controllano se un post specifico è nella
     * lista dei post che permettiamo all'utente di modificare.
     */
    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 );
    }

    /**
     * Rimuove il link di modifica dal front-end se necessario.
     */
    public function remove_edit_link( $link, $post_id, $test ) {
        /**
         * Se...
         * - L'utente limitato è loggato
         * - La pagina per cui viene creato il link di modifica non è nella lista consentita
         * ...ritorna una stringa vuota $link. Questo fa anche sì che edit_post_link() non mostri nulla.
         *
         * Altrimenti, ritorna il link normalmente.
         */
        if ( $this->is_user_limited() && !$this->is_page_allowed( $post_id ) ) {
            return '';
        }
        return $link;
    }

    /**
     * Rimuove il link di modifica dalla barra di amministrazione di WP
     */
    public function remove_wp_admin_edit_link( $wp_admin_bar ) {
        /**
         *  Se:
         *  - Siamo su una singola pagina
         *  - L'utente limitato è loggato
         *  - La pagina non è nella lista consentita
         *  ...Rimuove il link di modifica dalla barra di amministrazione di WP
         */
        if ( 
            is_page() &&
            $this->is_user_limited() &&
            !$this->is_page_allowed( get_post()->ID )
        ) {
            $wp_admin_bar->remove_node( 'edit' );
        }
    }

    /**
     * Rimuove il link di modifica da edit.php di WP Admin
     */
    public function remove_page_list_edit_link( $actions, $post ) {
        /**
         * Se:
         * - L'utente limitato è loggato
         * - La pagina non è nella lista consentita
         * ...Rimuove i link rapidi "Modifica", "Modifica rapida" e "Cestino".
         */
        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;
    }
}

Il codice sopra impedisce che le seguenti funzionalità funzionino o appaiano quando necessario:

  1. get_edit_post_link
  2. Il link Modifica Pagina sulla barra di amministrazione di WP che appare per le pagine
  3. I link rapidi Modifica, Modifica rapida e Cestino che appaiono sotto le pagine in /wp-admin/edit.php?post_type=page

Questo ha funzionato sulla mia installazione locale di WordPress 4.7. Supponendo che le pagine del sito non cambino spesso, potrebbe essere meglio hardcodare gli ID della pagina e delle sue pagine figlio, rimuovendo la WP_Query all'interno del metodo __construct. Questo risparmierà molte chiamate al database.

14 mar 2017 11:26:20
Commenti

+1 per la risposta più completa di quella di @Ben, ma il modo corretto per gestire i link è manipolando le capacità,

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

Sì, quando ho visto la risposta di gmazzap ho finito per pensare "Perché non ci ho pensato prima?"

ricotheque ricotheque
19 mar 2017 19:05:07
1

Se desideri evitare l'uso di plugin, puoi utilizzare una variante del codice seguente nel file functions.php o in un plugin personalizzato.

Ci sono 2 parti separate in questo codice, avresti bisogno di utilizzarne solo 1, ma quale dipende dalla complessità dei requisiti.

La Parte 1 specifica un singolo utente e lo limita a un post specifico.

La Parte 2 ti permette di creare una mappa di utenti e ID dei post e consente più post.

Il codice seguente è per una pagina soltanto, ma se desideri cambiarlo per un post o un custom post type, dovrai modificare la stringa in $screen->id == 'page' con qualcos'altro.

Puoi trovare un riferimento agli ID degli screen in wp-admin qui

function my_pre_get_posts( $query ){

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

    /**
     * Specifica un singolo utente e limita a una singola pagina
     */
    $restricted_user_id = 10; //ID dell'utente limitato
    $allowed_post_id = 1234; //ID del post consentito

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

    //Interessa solo un utente specifico
    if( $current_user->ID !== $restricted_user_id ){
        return;
    }

    //Interessa solo la pagina di MODIFICA.
    if( ! $current_post_id ){
        return;
    }

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

    /**
     * Specifica una mappa di user_id => $allowed_posts
     */
    $restrictions_map = [
        10 => [ 123 ], //Consenti all'utente con ID di modificare la Pagina con ID 123
        11 => [ 152, 186 ] //Consenti all'utente con ID di modificare le Pagine con ID 123 e 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
Commenti

+1 perché può funzionare per la funzionalità principale, ma questo lascia ancora i link per modificare le pagine visibili anche agli utenti che non possono modificarle, il che rappresenta una cattiva esperienza utente

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

Ho utilizzato User Role Editor un paio di volte ed è davvero ottimo. Forse potrebbe esserti utile anche a te. Ecco il link User Role Editor

16 giu 2015 17:31:25
Commenti

Sembra un plugin solido, ma non riesco a trovare un modo per limitare un utente a modificare pagine specifiche.

naf naf
16 giu 2015 17:35:42

Rendi gli utenti che vuoi limitare utenti di livello autore Aggiungi la capacità "edit_pages" al livello utente autore (utilizzando User Role Editor) Imposta l'autore di una pagina all'utente a cui vuoi concedere il privilegio di modificarla. Un utente di livello autore a cui viene data la capacità edit_pages può vedere l'elenco delle pagine nella dashboard, ma non ha l'opzione per modificare tranne le pagine di cui è autore.

user2319361 user2319361
16 giu 2015 17:46:00

Grazie, funziona fino a un certo punto. A un certo punto potrei avere la necessità di avere più utenti limitati a modificare una pagina specifica, quindi ci sarebbe bisogno di un modo per impostare più autori per una pagina.

naf naf
16 giu 2015 17:59:38

Per limitare gli utenti a pagine specifiche dovrai acquistare la versione Pro. Sto cercando la stessa cosa e l'ho scoperto. 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

anche se quel plugin specifico è una cosa solida al momento, probabilmente è più semplice scrivere del codice per farlo che navigare tra tutte le opzioni che offre il plugin. (se addirittura ti permette di fare ciò che chiede l'OP)

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