¿Cómo crear una capacidad personalizada de rol?

30 nov 2011, 19:15:51
Vistas: 56.9K
Votos: 29

Deseo crear una capacidad personalizada para acceder a la interfaz de mi plugin.

  • ¿Debería el plugin gestionar la adición de esta capacidad a todas las cuentas de administrador durante la activación?
  • Si es así: ¿WordPress gestiona la adición de la capacidad a todos los administradores de sub-blogs y super administradores en instalaciones multisite, o esa función debe ser manejada por el plugin?
1
Comentarios

Un blog detallado: http://goo.gl/xNuafH

Suresh Kamrushi Suresh Kamrushi
14 ene 2016 11:18:27
Todas las respuestas a la pregunta 4
3
20

Para un plugin en el que estoy trabajando actualmente, quería otorgar/restringir el acceso a la configuración del plugin (es decir, a las páginas del menú de administración correspondientes) por rol.
Por lo tanto, tuve que agregar una nueva capability específica del plugin a los user roles.

Desafortunadamente, la respuesta de kaiser parece no funcionar más, así que pasé un tiempo tratando de descubrir cómo permitir la funcionalidad mencionada anteriormente.


El Plan

Antes de compartir mi código con ustedes, aquí está de qué se trata, en texto claro:

  1. Al activar el plugin, agregar la nueva capacidad THE_NEW_CAP a los roles que tienen una determinada capacidad incorporada BUILT_IN_CAP (en mi caso: edit_pages).
  2. En cada carga de página, hacer 1. (es decir, agregar la capacidad nuevamente). Esto solo es necesario si deseas tener en cuenta posibles nuevos roles que se hayan creado después de la activación del plugin. Por lo tanto, estos nuevos roles no tienen la capacidad específica del plugin, incluso si tienen la capacidad incorporada requerida.
  3. Usar la nueva capacidad para lo que desees. Como se explicó antes, yo la uso para otorgar/restringir el acceso a las páginas del menú de administración del plugin, así es como se hace en el siguiente ejemplo de código.
  4. Al desactivar el plugin, eliminar la capacidad. Por supuesto, también podrías hacer esto cuando el plugin se desinstale. De cualquier manera, hazlo eventualmente.

El Código

Y aquí está la lista anterior convertida en código:

» Configurándolo

class WPSE35165Plugin {

    public function __construct() {
        // Registrar hooks
        register_activation_hook(__FILE__, array(__CLASS__, 'activation'));
        register_deactivation_hook(__FILE__, array(__CLASS__, 'deactivation'));

        // Agregar acciones
        add_action('admin_menu', array(__CLASS__, 'admin_menu'));
    }

    public function activation() {
        self::add_cap();
    }

    // Agregar la nueva capacidad a todos los roles que tienen una cierta capacidad incorporada
    private static function add_cap() {
        $roles = get_editable_roles();
        foreach ($GLOBALS['wp_roles']->role_objects as $key => $role) {
            if (isset($roles[$key]) && $role->has_cap('BUILT_IN_CAP')) {
                $role->add_cap('THE_NEW_CAP');
            }
        }
    }

» Usándolo

    // Agregar páginas del menú del plugin al menú de administración
    public function admin_menu() {
        // Elimina la siguiente línea si no te importan los nuevos roles
        // que se hayan creado después de la activación del plugin
        self::add_cap();

        // Configurar el menú de administración del plugin
        add_menu_page('Menú', 'Menú', 'THE_NEW_CAP', …);
        add_submenu_page('wpse35165', 'Submenú', 'Submenú', 'THE_NEW_CAP', ...);
    }

» Limpiándolo

    public function deactivation() {
        self::remove_cap();
    }

    // Eliminar la capacidad personalizada específica del plugin
    private static function remove_cap() {
        $roles = get_editable_roles();
        foreach ($GLOBALS['wp_roles']->role_objects as $key => $role) {
            if (isset($roles[$key]) && $role->has_cap('THE_NEW_CAP')) {
                $role->remove_cap('THE_NEW_CAP');
            }
        }
    }

}

Nota: Por favor, no uses capacidades en mayúsculas. Esto es solo para legibilidad.

14 mar 2013 04:24:38
Comentarios

Siempre usa get_editable_roles() para obtener los roles que quieres editar. De lo contrario, vas a romper plugins.

fuxia fuxia
28 abr 2013 20:38:38

@toscho Bueno, vale, supongo que es una de esas funciones que ni el Codex conoce... ;) Claro que esta función tiene razón de existir, sin embargo, no creo que usar el array global WP_Roles rompa ningún plugin en mi caso.

tfrommen tfrommen
28 abr 2013 20:44:42

Algunos plugins crean roles de usuario especializados y dependen de un conjunto exacto de capacidades. En algunos casos, una capacidad excluye el uso de otra en la lógica del programa. No puedes saber cuándo ese es el caso.

fuxia fuxia
28 abr 2013 20:54:13
0
12

Elimina lo que agregas

Primero, asegúrate de que todo lo que agregues durante la activación también sea eliminado durante la desinstalación. Tengo un breve tutorial que incluye código de ejemplo para ti.

Prueba con un pequeño plugin:

No sé mucho sobre MU, pero por lo que entiendo, el objeto de roles es global en todos los blogs. Prueba este pequeño plugin y observa lo que obtienes:

<?php
/*
Plugin Name:    Verificador de roles MU
Plugin URI:     https://github.com/franz-josef-kaiser/
Description:    Verifica los roles al visualizar un blog
Author:         Franz Josef Kaiser
Author URI:     https://plus.google.com/u/0/107110219316412982437
Version:        0.1
Text Domain:    murc
License:        GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/

/**
 * Muestra los datos del blog y los nombres de roles en este blog
 * También muestra si la capacidad personalizada fue agregada exitosamente, o muestra n/a para el rol
 * 
 * @return void
 */
function wpse35165_role_check()
{
    $blog = get_current_site();
    $custom_cap = 'nombre_de_tu_capacidad_personalizada';

    $html = "<hr /><table>";
    $html .= "<caption>Lista de roles en (Blog) {$blog->site_name} / ID#{$blog->id}</caption>"
    $html .= "<thead><tr><th>Nombre del Rol</th><th>Capacidades</th></tr></thead><tbody>";
    foreach ( $GLOBALS['wp_roles'] as $name => $role_obj )
    {
        $cap = in_array( $custom_cap, $role_obj->caps ) ? $custom_cap : 'n/a';
        $cap = $cap OR in_array( $custom_cap, $role_obj->allcaps ) ? $custom_cap : 'n/a';
        $html .= "<tr><td>{$name}</td><td>{$cap}</td></tr>";
    }
    $html .= '</tbody></table>';

    print $html;
}
add_action( 'shutdown', 'wpse35165_role_check' );

Agregando Capacidades

/**
 * Agrega la capacidad a los objetos de roles
 * Debe estar en tu función de activación y hacerse antes de inspeccionar con tu plugin
 * 
 * @return void
 */
function wpse35165_add_cap()
{
    $custom_cap = 'nombre_de_tu_capacidad_personalizada';
    $min_cap    = 'la_capacidad_minima_requerida_integrada'; // ¡Revisa la "Tabla de roles y objetos" en el codex!
    $grant      = true; 

    foreach ( $GLOBALS['wp_roles'] as $role_obj )
    {
        if ( 
            ! $role_obj->has_cap( $custom_cap ) 
            AND $role_obj->has_cap( $min_cap )
        )
            $role_obj->add_cap( $custom_cap, $grant );
    }
}

Nota: Puedes agregar la capacidad al rol sin otorgar acceso a ella - simplemente establece el segundo argumento $grant = false;. Esto permite incluir usuarios individuales en una lista blanca simplemente agregando la capacidad con el último argumento como true.

30 nov 2011 23:26:14
0

Probado con WordPress 6.0, y funciona:

add_action( 'activated_plugin',function( $plugin,$network_activation ){
    add_role( 'your_custom_role_slug', __( 'Tu título de rol personalizado','your-plugin-domain' ),
        array(
            'read' => true,
            'view_admin_dashboard' => true,
            'activate_plugins' => false,
            'deactivate_plugins' => false,
            'your_custom_capability' => true
        )
    );
}, 10, 2 );

En el arreglo, tienes solo algunos ejemplos de capacidades. Y puedes agregar tu capacidad personalizada sin ningún problema. La capacidad personalizada se almacenará junto con las otras capacidades.

Con este método, no podrás decir qué puedes hacer con "your_custom_capability", pero la mayoría de las veces como en el caso de esta pregunta, no necesitas nada más que verificar si el usuario actual puede "your_custom_capability". Si quieres mostrar las páginas de configuración de tu plugin solo a los usuarios que tienen la capacidad "your_custom_capability", puedes hacerlo sin problemas. Usa las capacidades integradas cuando crees el rol para decidir qué otras cosas el usuario con el rol "your_custom_role_slug" debería poder ver y hacer.

Esto devolverá true si el usuario tiene el rol "your_custom_role_slug":

current_user_can( 'your_custom_capability' );

Y esto mostrará la página de configuración solo si el usuario tiene la capacidad "your_custom_capability":

add_menu_page( __( 'Tu título','eos-dp' ),__( 'Tu título','your-domain' ),'your_custom_capability,'your_page_slug','your_function_callback','dashicons-your-icon',20 );

Luego, al eliminar el plugin, eliminaría el rol de usuario con:

remove_role( 'your_custom_role_slug' );
10 jun 2022 18:38:30
1

Esto funciona para mí:

add_action('admin_init', 'add_custom_cap');
function add_custom_cap()
{
  // Definir la capacidad personalizada que queremos añadir
  $custom_cap = 'test_cap';
  // Capacidad mínima requerida para asignar la nueva capacidad
  $min_cap    = 'read';
  // Si se concede o no la capacidad
  $grant      = true;
  // Rol de usuario al que queremos añadir la capacidad
  $to_role = 'your_user_role';
  $role = 'user_role';

  // Iterar a través de todos los roles disponibles
  foreach ( $GLOBALS['wp_roles'] as $role_obj )
  {
    // Verificar si el objeto de rol existe
    if (is_object($role_obj[$role])) {
      // Comprobar si el rol no tiene la capacidad personalizada pero sí tiene la capacidad mínima requerida
      if (!$role_obj[$role]->has_cap( $custom_cap ) && $role_obj[$role]->has_cap( $min_cap )) {
        // Añadir la capacidad personalizada al rol
        $role_obj[$role]->add_cap( $custom_cap, $grant );
      }
    }
  }
}
31 ago 2018 14:48:45
Comentarios

¡Nunca modifiques los globals de los roles! Jamás. ¡No lo hagas! No activarás ningún hook y negarás los filtros, convirtiendo tu código en un objetivo móvil. Nadie sabrá nunca cuándo o dónde registraste ese rol (no lo hiciste, simplemente lo metiste ahí en algún lugar, en algún momento, de alguna manera). Por favor: Nunca hagas eso. Especialmente no con roles.

kaiser kaiser
13 oct 2019 19:46:19