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.
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.
Risposte:
La prima cosa da fare per implementare tale compito è essere in grado di riconoscere quale pagina un utente può modificare.
Esistono diversi modi per farlo. Potrebbe essere una meta utente, un valore di configurazione ... Per il bene di questa risposta, assumerò che esista una funzione 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...
}
Ora che abbiamo un modo per determinare se un utente può modificare una pagina, dobbiamo solo dire a WordPress di utilizzare questa funzione per verificare la capacità dell'utente di modificare una pagina.
Questo può essere fatto tramite 'map_meta_cap'
filtro.
Qualcosa di simile a:
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 );
A questo punto, abbiamo solo bisogno di un modo per connettere un utente a una o più pagine.
Potrebbero esserci diverse soluzioni a seconda del caso d'uso.
Una soluzione flessibile potrebbe essere quella di aggiungere un menu a discesa di pagine "root" (vedi wp_dropdown_pages
) alla schermata di modifica dell'utente amministratore e salvare le pagine selezionate come meta utente.
Potremmo sfruttare 'edit_user_profile'
per aggiungere il campo a discesa delle pagine e 'edit_user_profile_update'
per memorizzare il valore selezionato come meta utente.
Sono sicuro che in questo sito web ci sono abbastanza indicazioni su come farlo in dettaglio.
Quando le pagine sono memorizzate come meta utente, la wpse_user_can_edit()
funzione dall'alto può essere completata controllando se l'id della pagina fa parte del meta valore dell'utente.
Rimuovendo la possibilità di modificare la pagina, WordPress farà il resto: rimuoverà qualsiasi collegamento di modifica da backend e frontend, impedirà l'accesso diretto ... e così via.
Ci vuole una piccola quantità di codice per implementare questa funzione, anche se si utilizza una classe PHP per evitare variabili globali. Inoltre, non volevo nascondere le pagine vietate per l'utente nella Dashboard. E se aggiungessero contenuti che erano già sul sito?
$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;
}
}
Ciò che fa il codice sopra è impedire che quanto segue funzioni o appaia come necessario:
get_edit_post_link
Edit Page
collegamento sulla barra di amministrazione di WP visualizzata per le pagineEdit
, Quick Edit
e Trash
collegamenti rapidi che compaiono 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 codificare gli ID della pagina e delle sue pagine secondarie e rimuovere l' WP_Query
interno del __construct
metodo. Ciò farà risparmiare molto sulle chiamate al database.
Se volessi stare lontano dai plugin, potresti cambiare il codice qui sotto in un file Functions.php o in un plugin personalizzato.
Ci sono 2 parti separate in questo codice, dovresti usarne solo 1, ma quale dipende dalla complessità dei requisiti.
La parte 1 specifica un singolo utente e li limita a un post specifico.
La parte 2 ti consente di creare una mappa di utenti e pubblicare ID e consente più post
Il codice seguente è solo per una pagina, ma se si desidera modificarlo in un post o in un tipo di post personalizzato, è necessario modificare la stringa in $screen->id == 'page'
qualcos'altro.
Puoi trovare un riferimento agli ID dello schermo su wp-admin qui
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' );
Ho usato User Role Editor
un paio di volte ed è abbastanza buono. Forse potrebbe aiutare anche te. Ecco il link Editor ruoli utente