Permitir al usuario editar solo ciertas páginas
Lo primero que hay que hacer para implementar esta tarea es poder reconocer qué página puede editar un usuario.
Hay diferentes formas de hacerlo. Podría ser un meta de usuario, algún valor de configuración... Para esta respuesta, asumiré que existe una función como esta:
function wpse_user_can_edit( $user_id, $page_id ) {
$page = get_post( $page_id );
// encontremos la página superior en la jerarquía
while( $page && (int) $page->parent ) {
$page = get_post( $page->parent );
}
if ( ! $page ) {
return false;
}
// ahora $page es la página superior en la jerarquía
// cómo saber si un usuario puede editarla, depende de ti...
}
Ahora que tenemos una forma de determinar si un usuario puede editar una página, solo necesitamos decirle a WordPress que use esta función para verificar la capacidad del usuario de editar una página.
Eso se puede hacer mediante el filtro 'map_meta_cap'
.
Algo como:
add_filter( 'map_meta_cap', function ( $caps, $cap, $user_id, $args ) {
$to_filter = [ 'edit_post', 'delete_post', 'edit_page', 'delete_page' ];
// Si la capacidad filtrada no es de nuestro interés, simplemente devolver el valor actual
if ( ! in_array( $cap, $to_filter, true ) ) {
return $caps;
}
// El primer elemento en el array $args debería ser el ID de la página
if ( ! $args || empty( $args[0] ) || ! wpse_user_can_edit( $user_id, $args[0] ) ) {
// El usuario no tiene permiso, informemos a WP
return [ 'do_not_allow' ];
}
// De lo contrario, simplemente devolver el valor actual
return $caps;
}, 10, 4 );
En este punto, solo necesitamos una forma de conectar un usuario a una o más páginas.
Puede haber diferentes soluciones según el caso de uso.
Una solución flexible podría ser añadir un desplegable de páginas "raíz" (ver wp_dropdown_pages
) a la pantalla de edición de usuario en el administrador, y guardar la(s) página(s) seleccionada(s) como meta del usuario.
Podríamos aprovechar 'edit_user_profile'
para añadir el campo desplegable de páginas y 'edit_user_profile_update'
para almacenar el valor seleccionado como meta del usuario.
Estoy seguro de que en este sitio hay suficiente orientación sobre cómo hacerlo en detalle.
Cuando las páginas se almacenan como meta del usuario, la función wpse_user_can_edit()
de arriba puede completarse verificando si el ID de la página es parte del valor del meta del usuario.
Al eliminar la capacidad de editar la página, WordPress hará el resto: eliminará cualquier enlace de edición del backend y frontend, evitará el acceso directo... y así sucesivamente.

Esto es mucho mejor que mi respuesta. ¿Por qué limitar los enlaces de edición cuando puedes simplemente modificar la capacidad del usuario y dejar que WordPress maneje el resto?

Implementar esta funcionalidad requiere una pequeña cantidad de código, incluso si usas una clase PHP para evitar variables globales. Tampoco quise ocultar las páginas prohibidas para el usuario en el Dashboard. ¿Qué pasaría si agregaran contenido que ya existe en el sitio?
$user_edit_limit = new NS_User_Edit_Limit(
15, // ID del usuario que queremos limitar
[2, 17] // Array de IDs de páginas padre que el usuario puede editar
(también acepta IDs de subpáginas)
);
class NS_User_Edit_Limit {
/**
* Almacena el ID del usuario que queremos controlar y los
* posts que permitiremos que el usuario edite.
*/
private $user_id = 0;
private $allowed = array();
public function __construct( $user_id, $allowed ) {
// Guardamos el ID del usuario que queremos limitar.
$this->user_id = $user_id;
// Expandimos la lista de páginas permitidas para incluir subpáginas
$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;
}
}
// Para el usuario prohibido...
// Eliminamos el enlace de edición del front-end según sea necesario
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 );
// Eliminamos el enlace de edición de wp-admin según sea necesario
add_action( 'page_row_actions', array( $this, 'remove_page_list_edit_link' ), 10, 2 );
}
/**
* Funciones auxiliares que verifican si el usuario actual es el que
* queremos limitar y si un post específico está en nuestra
* lista de posts que permitimos que el usuario edite.
*/
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 );
}
/**
* Elimina el enlace de edición del front-end según sea necesario.
*/
public function remove_edit_link( $link, $post_id, $test ) {
/**
* Si...
* - El usuario limitado está logueado
* - La página para la que se está creando el enlace de edición no está en la lista permitida
* ...retornamos un $link vacío. Esto también hace que edit_post_link() no muestre nada.
*
* De lo contrario, retornamos el enlace normalmente.
*/
if ( $this->is_user_limited() && !$this->is_page_allowed( $post_id ) ) {
return '';
}
return $link;
}
/**
* Elimina el enlace de edición de la barra de administración de WP
*/
public function remove_wp_admin_edit_link( $wp_admin_bar ) {
/**
* Si:
* - Estamos en una página individual
* - El usuario limitado está logueado
* - La página no está en la lista permitida
* ...Eliminamos el enlace de edición de la barra de administración de WP
*/
if (
is_page() &&
$this->is_user_limited() &&
!$this->is_page_allowed( get_post()->ID )
) {
$wp_admin_bar->remove_node( 'edit' );
}
}
/**
* Elimina el enlace de edición de edit.php en el admin de WP
*/
public function remove_page_list_edit_link( $actions, $post ) {
/**
* Si:
* - El usuario limitado está logueado
* - La página no está en la lista permitida
* ...Eliminamos los enlaces rápidos "Editar", "Edición rápida" y "Papelera".
*/
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;
}
}
Lo que hace el código anterior es evitar que lo siguiente funcione o aparezca según sea necesario:
get_edit_post_link
- Enlace
Editar página
en la barra de administración de WP que aparece para las Páginas - Enlaces rápidos
Editar
,Edición rápida
yPapelera
que aparecen debajo de las Páginas en/wp-admin/edit.php?post_type=page
Esto funcionó en mi instalación local de WordPress 4.7. Asumiendo que las páginas del sitio no cambiarán con frecuencia, podría ser mejor codificar manualmente los IDs de la página y sus subpáginas, y eliminar el WP_Query
dentro del método __construct
. Esto ahorrará muchas consultas a la base de datos.

Si deseas evitar el uso de plugins, podrías utilizar una variación del código siguiente en un archivo functions.php o en un plugin personalizado.
Este código tiene 2 partes separadas. Solo necesitarías usar 1 de ellas, dependiendo de la complejidad de los requisitos.
La Parte 1 especifica un único usuario y lo restringe a una publicación específica.
La Parte 2 te permite crear un mapa de usuarios e IDs de publicaciones, permitiendo múltiples publicaciones.
El código siguiente es solo para páginas, pero si deseas cambiarlo para posts o un tipo de publicación personalizada, necesitarías cambiar la cadena en $screen->id == 'page'
por otra cosa.
Puedes encontrar una referencia a los IDs de pantalla en wp-admin aquí
function my_pre_get_posts( $query ){
$screen = get_current_screen();
$current_user = wp_get_current_user();
/**
* Especifica un único usuario y lo restringe a una única página
*/
$restricted_user_id = 10; //ID del usuario restringido
$allowed_post_id = 1234; //ID de la publicación permitida
$current_post_id = isset( $_GET['post'] ) ? (int)$_GET['post'] : false ;
//Solo afecta a un usuario específico
if( $current_user->ID !== $restricted_user_id ){
return;
}
//Solo afecta la página de EDICIÓN
if( ! $current_post_id ){
return;
}
if( $screen->id == 'page' && $current_post_id !== $allowed_post_id ){
wp_redirect( admin_url( ) );
exit;
}
/**
* Especifica un mapa de user_id => $allowed_posts
*/
$restrictions_map = [
10 => [ 123 ], //Permite al usuario ID editar la Página ID 123
11 => [ 152, 186 ] //Permite al usuario ID editar las Páginas ID 123 y 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' );

Utilicé User Role Editor
un par de veces y es bastante bueno.
Quizás también te pueda ayudar.
Aquí está el enlace User Role Editor

Parece ser un plugin sólido, pero no encuentro una manera de restringir a un usuario para editar páginas específicas.

Haz que los usuarios que quieras limitar sean usuarios de nivel autor Añade la capacidad "edit_pages" al nivel de usuario autor (usando User Role Editor) Establece el autor de una página como el usuario al que quieres dar privilegios de edición. Un usuario de nivel autor al que se le da la capacidad de edit_pages puede ver la lista de páginas en el panel, pero no tiene la opción de editar excepto las páginas de las que es autor.

Gracias, eso funciona hasta cierto punto. En algún momento podría necesitar tener múltiples usuarios restringidos para modificar una página específica, así que necesitaría una manera de establecer múltiples autores para una página.

Para restringir a los usuarios a páginas específicas necesitarás comprar la versión Pro. Estaba buscando lo mismo y descubrí eso. http://wordpress.stackexchange.com/questions/191658/allowing-user-to-edit-only-certain-pages/191661#191661?s=f87626a8cf184588bca7c4e397c972a4
