Cum creez o capacitate pentru un rol personalizat?
Doresc să creez o capacitate personalizată pentru accesarea interfeței plugin-ului meu.
- Ar trebui ca plugin-ul să gestioneze adăugarea acestei capacități pentru toate conturile de administrator la activare?
- Dacă da: WordPress gestionează automat adăugarea capacității pentru toți administratorii sub-blogurilor și super administratorii în instalările multisite, sau această funcție trebuie gestionată de către plugin?
Pentru un plugin la care lucrez în prezent, am dorit să acord/restrâng accesul la setările pluginului (adică la paginile corespunzătoare din meniul de administrare) pe bază de rol.
Prin urmare, a trebuit să adăug o nouă capabilitate
specifică pluginului la rolurile utilizatorilor
.
Din păcate, răspunsul lui kaiser pare să nu mai funcționeze, așa că am petrecut ceva timp încercând să descopăr cum să permit funcționalitatea menționată mai sus.
Planul de Acțiune
Înainte de a vă împărtăși codul, iată despre ce este vorba, în termeni simpli:
- La activarea pluginului, adaugă noua capabilitate
CAPABILITATEA_NOUA
la rolurile care au o anumită capabilitate predefinităCAPABILITATE_PREDEFINITA
(în cazul meu:edit_pages
). - La fiecare încărcare de pagină, execută 1. (adică adaugă capabilitatea din nou). Acest lucru este necesar doar dacă doriți să țineți cont de eventualele roluri noi create după activarea pluginului. Astfel, aceste roluri noi nu vor avea capabilitatea specifică pluginului, chiar dacă au capabilitatea predefinită necesară.
- Folosește noua capabilitate pentru orice dorești. După cum am explicat anterior, o folosesc pentru a acorda/restrânge accesul la paginile din meniul de administrare al pluginului, așa cum este prezentat în exemplul de cod de mai jos.
- La dezactivarea pluginului, elimină capabilitatea. Desigur, puteți face acest lucru și la dezinstalarea pluginului. În orice caz, asigurați-vă că o faceți eventual.
Codul
Și iată lista de mai sus transformată în cod:
» Configurarea
class WPSE35165Plugin {
public function __construct() {
// Înregistrează hook-uri
register_activation_hook(__FILE__, array(__CLASS__, 'activation'));
register_deactivation_hook(__FILE__, array(__CLASS__, 'deactivation'));
// Adaugă acțiuni
add_action('admin_menu', array(__CLASS__, 'admin_menu'));
}
public function activation() {
self::add_cap();
}
// Adaugă noua capabilitate la toate rolurile care au o anumită capabilitate predefinită
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('CAPABILITATE_PREDEFINITA')) {
$role->add_cap('CAPABILITATEA_NOUA');
}
}
}
» Utilizarea
// Adaugă paginile de meniu ale pluginului în meniul de administrare
public function admin_menu() {
// Elimină următoarea linie dacă nu te interesează rolurile noi
// care au fost create după activarea pluginului
self::add_cap();
// Configurează meniul de administrare al pluginului
add_menu_page('Meniu', 'Meniu', 'CAPABILITATEA_NOUA', …);
add_submenu_page('wpse35165', 'Submeniu', 'Submeniu', 'CAPABILITATEA_NOUA', ...);
}
» Curățarea
public function deactivation() {
self::remove_cap();
}
// Elimină capabilitatea personalizată specifică pluginului
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('CAPABILITATEA_NOUA')) {
$role->remove_cap('CAPABILITATEA_NOUA');
}
}
}
}
Notă: Vă rugăm să nu folosiți capabilități cu litere mari. Aceasta este doar pentru lizibilitate.

Întotdeauna folosește get_editable_roles()
pentru a obține rolurile pe care vrei să le editezi. Altfel, vei strica plugin-uri.

@toscho Ei bine, bine, presupun că aceasta este una dintre acele funcții pe care nici măcar Codex-ul nu le cunoaște... ;) Desigur, această funcție are dreptul să existe, totuși, nu văd cum folosirea array-ului global WP_Roles ar strica vreun plugin în cazul meu.

Ștergeți ceea ce adăugați
În primul rând, asigurați-vă că tot ceea ce adaugați la activare este și eliminat la dezinstalare. Am pregătit un scurt tutorial care include cod exemplu pentru dumneavoastră.
Testați cu un mic plugin:
Nu știu prea multe despre MU, dar din câte am înțeles, obiectul de roluri este global pentru toate blogurile. Încercați acest mic plugin și vedeți ce obțineți:
<?php
/*
Plugin Name: Verificare roluri MU
Plugin URI: https://github.com/franz-josef-kaiser/
Description: Verifică rolurile în timpul vizualizării unui 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
*/
/**
* Afișează datele blogului și numele rolurilor în acest blog
* De asemenea, arată dacă capabilitatea personalizată a fost adăugată cu succes sau afișează n/a pentru rol
*
* @return void
*/
function wpse35165_role_check()
{
$blog = get_current_site();
$custom_cap = 'numele_capabilitatii_dvs_personalizate';
$html = "<hr /><table>";
$html .= "<caption>Listă roluri în (Blog) {$blog->site_name} / ID#{$blog->id}</caption>"
$html .= "<thead><tr><th>Nume Rol</th><th>Capabilități</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' );
Adăugarea capabilităților
/**
* Adaugă capabilitatea la obiectele de rol
* Ar trebui să fie în funcția de activare și făcut înainte de a inspecta cu pluginul dumneavoastră
*
* @return void
*/
function wpse35165_add_cap()
{
$custom_cap = 'numele_capabilitatii_dvs_personalizate';
$min_cap = 'capabilitatea_minima_ceruta_interna'; // Verificați "Tabelul roluri și obiecte" în 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 );
}
}
Notă: Puteți adăuga capabilitatea la rol fără a acorda acces la ea - doar setați al doilea argument $grant = false;
. Acest lucru permite adăugarea individuală a utilizatorilor prin simpla adăugare a capabilității cu ultimul argument setat ca true.

Testat cu WordPress 6.0 și funcționează:
add_action( 'activated_plugin',function( $plugin,$network_activation ){
add_role( 'your_custom_role_slug', __( 'Titlul rolului tău personalizat','your-plugin-domain' ),
array(
'read' => true,
'view_admin_dashboard' => true,
'activate_plugins' => false,
'deactivate_plugins' => false,
'your_custom_capability' => true
)
);
}, 10, 2 );
În array, ai doar câteva exemple de capabilități. Și poți adăuga propria ta capabilitate personalizată fără nicio problemă. Capabilitatea personalizată va fi stocată împreună cu celelalte capabilități.
Cu această metodă, nu vei putea specifica ce poți face cu "your_custom_capability", dar de cele mai multe ori, ca în cazul acestei întrebări, nu ai nevoie de altceva decât să verifici dacă utilizatorul curent poate "your_custom_capability". Dacă dorești să afișezi paginile de setări ale plugin-ului tău doar utilizatorilor care au capabilitatea "your_custom_capability", poți face acest lucru fără probleme. Folosește capabilitățile încorporate atunci când creezi rolul pentru a decide ce alte lucruri ar trebui să poată vedea și face utilizatorul cu rolul "your_custom_role_slug".
Aceasta va returna true dacă utilizatorul are rolul "your_custom_role_slug":
current_user_can( 'your_custom_capability' );
Și aceasta va afișa pagina de setări doar dacă utilizatorul are capabilitatea "your_custom_capability":
add_menu_page( __( 'Titlul tău','eos-dp' ),__( 'Titlul tău','your-domain' ),'your_custom_capability','your_page_slug','your_function_callback','dashicons-your-icon',20 );
Apoi, la ștergerea plugin-ului, aș elimina rolul utilizatorului cu:
remove_role( 'your_custom_role_slug' );

Aceasta funcționează pentru mine:
add_action('admin_init', 'add_custom_cap');
function add_custom_cap()
{
$custom_cap = 'test_cap';
$min_cap = 'read';
$grant = true;
$to_role = 'your_user_role';
$role = 'user_role';
foreach ( $GLOBALS['wp_roles'] as $role_obj )
{
if (is_object($role_obj[$role])) {
if (!$role_obj[$role]->has_cap( $custom_cap ) && $role_obj[$role]->has_cap( $min_cap )) {
$role_obj[$role]->add_cap( $custom_cap, $grant );
}
}
}
}

Niciodată nu modificați globals-urile rolurilor! Niciodată. Nu faceți asta! Nu veți declanșa niciun hook și veți anula filtrele, făcând codul vostru o țintă în mișcare. Nimeni nu va ști niciodată când și unde ați înregistrat acel rol (nu ați făcut-o, doar l-ați băgat acolo undeva, cândva, cumva). Vă rog: Niciodată nu faceți asta. Mai ales nu cu roluri.
