Cómo permitir que el editor edite solo la página/configuración de privacidad
En mi instalación de WordPress (4.9.8.)
el rol de editor no tiene permisos para editar la página de privacidad.
Funcionaría añadiendo esto en mi functions.php
:
$role_object = get_role( 'editor' );
$role_object->add_cap( 'manage_privacy_options', true );
$role_object->add_cap( 'manage_options' ); // esto debe estar activo para que la capacidad anterior funcione
Pero ahora el editor tiene muchos más permisos que solo editar la página de privacidad.
¿Existe otra forma de otorgar acceso al rol de editor
con algunas líneas de código PHP?
Como solución temporal estoy usando este plugin: https://wordpress.org/plugins/manage-privacy-options/
Otra solución alternativa es simplemente no seleccionar ninguna página de privacidad en los ajustes.

La edición de la página de política de privacidad está restringida a manage_privacy_options
como se menciona en un comentario en el archivo núcleo de WordPress wp-includes/capabilities.php
:
/*
* Establecer la página de política de privacidad requiere `manage_privacy_options`,
* por lo que editarla también debería requerirlo.
*/
if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
$caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
}
Para permitir que los usuarios con los roles que pueden editar páginas (en instancias individuales y también multisitio) puedan editar y eliminar la página de política de privacidad, se debe sobrescribir el array editor
y administrador
$caps
:
add_filter('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args)
{
if (!is_user_logged_in()) return $caps;
if ('manage_privacy_options' === $cap) {
$manage_name = is_multisite() ? 'manage_network' : 'manage_options';
$caps = array_diff($caps, [ $manage_name ]);
}
return $caps;
}
Actualización: Permitir que usuarios con el rol editor
o administrador
puedan editar y eliminar la página de política de privacidad (lo cual no es posible por defecto en instancias multisitio):
add_filter('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args)
{
if (!is_user_logged_in()) return $caps;
$user_meta = get_userdata($user_id);
if (array_intersect(['editor', 'administrator'], $user_meta->roles)) {
if ('manage_privacy_options' === $cap) {
$manage_name = is_multisite() ? 'manage_network' : 'manage_options';
$caps = array_diff($caps, [ $manage_name ]);
}
}
return $caps;
}

Oh, parece muy inteligente... 1. ¿$caps = array_diff($caps, [ $manage_name ]);
restringe todas las demás capacidades de manage_options
? ¿Y solo permite editar las opciones de privacidad? 2. El administrator
realmente no necesitaría esto, ya que esta capacidad ya está incluida, ¿o no?

@AndréKelling 1. El hook map_meta_cap
funciona por cada entrada/post. Ningún otro post tiene la restricción manage_privacy_options
, así que debería estar bien eliminarlo. Más información aquí.
2. En entornos multisitio de WordPress solo los superadministradores pueden editar la página de política de privacidad. Como mencionaste, esto no es relevante para instalaciones de un solo sitio.

@AndréKelling ¿Tienes alguna otra pregunta sobre mi respuesta? Si no, por favor acepta la respuesta para marcar esta pregunta como resuelta :)

Lo siento, no tuve tiempo de revisar esto. ¡Lo haré inmediatamente!

Esto funciona bastante bien, pero ¿no sería mejor verificar también el rol del usuario... esto debería afectar este permiso para todos los usuarios, ¿no?

@GDY Buen punto. Asumí que solo los editores y administradores pueden editar páginas. He añadido la verificación del rol de usuario a mi respuesta.

En realidad, la pregunta se refiere al rol de editor (que no puede editar la página de privacidad en instalaciones regulares), por lo que debería cubrir tanto a editores como a administradores.

Muchas gracias por la solución. Para aquellos que deseen permitir que los Gerentes de Tienda de WooCommerce puedan editar la política de privacidad, agreguen "shop_manager" al array_intersect en el segundo ejemplo.

Sé que add_action
es un alias de add_filter
, pero dado que el filtro map_meta_cap
está definido usando apply_filters
, creo que deberías reemplazar add_action()
con add_filter()
para mayor claridad.

Este código provoca un error fatal (Fatal error: Uncaught TypeError: array_intersect(): Argument #2 must be of type array, null given ...snip... /wp-admin/user-new.php(195): edit_user()
) al crear una nueva cuenta de usuario. Parece que el usuario puede ser nulo. He añadido una línea adicional de verificaciones después de la llamada a get_userdata()
que lo envuelve así: if ($user_meta && isset($user_meta->roles) && is_array($user_meta->roles)) { }

Gracias @Sven por el buen método alternativo, funciona bien pero tuve un problema cuando el usuario aún no ha iniciado sesión, la acción map_meta_cap se ejecuta de todas formas, lo que resultó en un error "502 bad gateway". Añadí una verificación is_user_logged_in()
antes así:
if (is_user_logged_in()){
add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
}
Tal vez sea mi configuración del servidor (nginx) lo que causa este error, pero si alguien tiene el mismo problema, aquí está una solución.

La respuesta proporcionada funcionó. Sin embargo, esta línea:
if (array_intersect(['editor', 'administrator'], $user_meta->roles)) {
Estaba generando este error:
array_intersect(): Expected parameter 2 to be an array, null given in
Así que ajusté un poco el código para asegurarme de que ambos valores fueran arrays válidos (código completo):
add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args) {
if ( !is_user_logged_in() ) return $caps;
$target_roles = array('editor', 'administrator');
$user_meta = get_userdata($user_id);
$user_roles = ( array ) $user_meta->roles;
if ( array_intersect($target_roles, $user_roles) ) {
if ('manage_privacy_options' === $cap) {
$manage_name = is_multisite() ? 'manage_network' : 'manage_options';
$caps = array_diff($caps, [ $manage_name ]);
}
}
return $caps;
}

No veo lo que has cambiado. Si $user_meta->roles es null, todavía estás pasando null a array_intersect aquí.

Como nos aseguramos de que el usuario haya iniciado sesión primero, ¿$user_meta->roles nunca podría ser null? Pensé que el problema se debía a usar $user_meta->roles directamente en array_intersect, así que lo guardé en una variable primero. Ya no recibo mensajes de error, así que parece que eso solucionó el problema.

⚠ ¡Atención! Hasta que este error se solucione, esta respuesta, aunque conceptualmente válida, no funcionará! ⚠
En mi opinión, esto ahora se logra mejor mediante wp-cli
.
Por ejemplo, para extender los permisos del rol de editor:
wp cap add editor manage_privacy_options
O, solo para un usuario específico:
wp user add-cap USER_ID manage_privacy_options

Vaya, aparentemente no funciona :-( Si alguien puede comentar, confirmar... Huele a bug.

Encontré el culpable, un bug bastante antiguo :-/
