WordPress Roller och förmågor Ett verkligt exempel

Detta är en serie med fyra delar, som omfattar WordPress-användare, roller och funktioner. Serien kommer att täcka arkitekturen och utformningen av användarroller i WordPress; markera de viktigaste funktionerna för att interagera med användare och hantera roller och funktioner; och i den sista handledningen kommer vi att bygga ett verkligt exempel som visar användbarheten av detta API.


Introduktion

Denna handledning kommer att vara inriktad på att bygga en praktisk lösning med hjälp av WordPress-roller och kapacitetssystem. Om du har missat de två sista handledningarna rekommenderar jag starkt att du kolla in dem. Den första delen "WordPress Roller and Capabilities: The Basics" förklarar utformningen av detta system; medan den andra delen "WordPress Roller and Capabilities: Functions of Note" fokuserar på funktioner och klasser som WordPress erbjuder för att interagera med systemet.

Lösningen som föreslås i denna handledning är samma som jag använder för en av mina premium WordPress-plugins. Jag har valt det efter att ha försökt olika metoder. Det är enkelt, kort och inkapslat i en klass. Du kan enkelt anpassa den till din egen plugin. Koden är tillgänglig på GitHub; och är inte licensierad. Det kommer inte med några garantier, och du är fri att använda och licensiera det som du vill.


Steg 1 Scenariot

Vi bygger ett WordPress-plugin som har en speciell klientadministratörspanel. Den här administratörspanelen ska vara tillgänglig endast för en begränsad uppsättning användare. Dessa användare kan väljas av bloggadministratören. Han kan aktivera olika roller, användare eller alla av dem för att komma åt klientens administratörspanel eller funktioner.

Utöver det behöver vi ha ett begränsat mediebibliotek åtkomst för användare med tillgång till klientpanelen. WordPress har en speciell förmåga att komma åt och ladda upp filer till mediebiblioteket: "ladda upp filer". Det ger dock användaren (eller rollen) full tillgång till mediebiblioteket. Det här är inte bra, särskilt att foton (eller filer) inte kan hierarkiseras under olika kategorier där du kan begränsa åtkomsten för varje.

Vi behöver begränsa Media Library-åtkomsten endast till de filer som användaren har laddat upp. Han borde inte ha tillgång till andra användares uppladdningar. Denna begränsning bör endast tillämpas på användare som inte har "ladda upp filer"Andra användare och roller är inte oroade över denna begränsning eftersom de redan har fullständig tillgång till mediebiblioteket.

Vår blogg kommer att ha dessa fyra kategorier av användare:

De första två uppsättningarna av användare är de som inte har tillgång till plugin-klientpanelen. Jag har markerat det faktum att det finns användare som har tillgång till mediebiblioteket och en uppsättning som inte gör det. Det är viktigt att vår lösning inte påverkar de två första kategorierna och lämnar sina möjligheter intakta.

Med det i åtanke bör vår klass göra två saker:

  • Ange rätt behörigheter till den tredje och fjärde uppsättningen användare
  • Aktivera ett begränsat Media Library-åtkomst till den fjärde kategorin. Det bör se till att efter att inaktivera pluginprogrammet eller ändra användarnas rättigheter, får den här användargruppen tillbaka sina ursprungliga behörigheter.

Steg 2 Plugin-gränssnittet

Innan vi skapar vår klass, låt oss få en djupare inblick i plugin. Pluggen har en ganska enkel struktur. Den består av två olika menyer: En för administratören och den fungerar som en administrativ panel, endast tillgänglig för användare med förmåga att "manage_options"Den andra menyn är för kunder och ger tillgång till klientpanelen. Den här panelen kräver en"wptuts_client_page"förmåga.

Denna funktion finns inte i WordPress; Vi måste lägga till och tilldela den till angivna användare eller roller. Men före det, låt oss ta en titt på plugin.

 / * Plugin Name: WordPress Roller Plugin Plugin URI: https://github.com/omarabid/WordPress-Roles-Plugin Beskrivning: En WordPress Roller Plugin Författare: Abid Omar Författare URI: http://omarabid.com Version: 1.0 * / // Lägg till en användarmeny för administratören till WordPress Dashboard add_action ('admin_menu', 'wptuts_admin_menu'); funktion wptuts_admin_menu () add_menu_page ('Admin Access', 'Admin Access', 'manage_options', 'wptuts-admin', 'wptuts_admin_page');  funktion wptuts_admin_page () echo 'Admin Page';  // Lägg till en klient användarmeny till WordPress Dashboard add_action ('admin_menu', 'wptuts_client_menu'); funktion wptuts_client_menu () add_menu_page ('Client Access', 'Client Access', 'wptuts_client', 'wptuts-client', 'wptuts_client_page');  funktion wptuts_client_page () echo 'klientsida'; 

Vi har två "admin_menu"action krokar som lägger till Admin-menyn för både administratören och klienten. Vi kan förkorta den till bara en krok som lägger till båda, men jag föredrar att skilja de två. Varje"add_menu_page"funktionskrokar till en annan funktion som visar sidinnehållet.

Därefter måste vi initialisera vår Roll-klass. Klasskoden placeras i en annan fil; och initialiseringsprocessen sker under "i det"krok som säkerställer att WordPress är klar att ladda.

Konstruktörsfunktionen accepterar tre parametrar:

  • $ alla Booleska (valfritt) Om du vill ge klienten tillgång till alla användare på bloggen kan du ställa in den här till sann och ignorera de återstående parametrarna.
  • $ roller Array (valfritt) En grupp med roller 'ids som kommer att ha åtkomst till klientpanelen.
  • $ användare Array (valfritt) En grupp med användarnamn som kommer att ha åtkomst till klientpanelen.
 // Laddar och initialiserar roller-klassen add_action ('init', 'wptuts_start_plugin'); funktion wptuts_start_plugin () require_once ('roles_class.php'); $ all = false; $ roller = array ('abonnent'); $ users = array (3); nya wpttuts_roles ($ alla, $ roller, $ användare); 

Steg 3 Rollen Klass

Egenskaperna

Klassen har endast 3 egenskaper: $ alla, $ roller och $ användare. Dessa är samma variabler som du skickar till konstruktörsfunktionen. Värdet av variablerna ändras inte i vårt exempel; men i ett verkligt praktiskt fall kanske du vill slå samman med en annan källa. För detta har du set_entities fungera. Du kan ta emot det till dina egna behov.

 / ** * @var boolean * / privat $ all; / ** * @var array * / private $ roller; / ** * @var array * / private $ users; / ** * Ange behörighetsenheter * * @param boolean $ all * @param array $ roller * @param array $ users * / privatfunktion set_entities ($ alla, $ roller, $ användare) $ this-> all = $ Allt; $ this-> roller = $ roller; $ this-> users = $ users; 

Konstruktörsfunktionen

I ett första steg initierar konstruktorfunktionen $ alla, $ roller och $ användare variabler som använder set_entitites () fungera. Därefter kallas det en privat funktion för att ställa in funktionerna, och en annan för mediebibliotekets begränsning. Det här är exakt de steg vi definierade i vårt scenario.

 / ** * Skapar en ny instans av rollerna Klass * * @param boolean $ alla * @param array $ roller * @param array $ users * / function __construct ($ all = false, $ roller = array (), $ users = array ()) // Ange de tillåtna enheterna $ this-> set_entities ($ alla, $ roller, $ users); // Ange behörighet för användaråtkomst $ this-> set_permissions (); // Media Library Filter $ this-> media_filter (); 

Statiska funktioner

Statiska funktioner kräver inte klassinitiering. De liknar oberoende funktioner, men helt enkelt kopplade till den angivna klassen. Jag har bestämt mig för att hålla några funktioner statiska eftersom de kan användas oberoende; och du kan hitta dem användbara i ett annat sammanhang.

Dessa funktioner är filter_roles () och filter_users (); som är förknippade med två andra funktioner role_has_caps () och user_has_caps (). Funktionerna spelar en del av ett filter. De filtrerar roller (eller användare) baserat på kapacitet de har och inte har.

Båda funktionerna accepterar två argument:

  • $ inkluderar Array En rad funktioner som rollen har.
  • $ utesluta Array En rad funktioner som rollen inte har.
 / ** * Filtrera alla roller i bloggen baserat på funktioner * * @static * @param array $ inkluderar Array of capabilities att inkludera * @param array $ utesluta Array of capabilities för att utesluta * @return array * / statisk funktion filter_roles ($ inkludera, $ utesluta) $ filtered_roles = array (); globala $ wp_roles; $ roller = $ wp_roles-> get_names (); foreach ($ roller som $ role_id => $ role_name) $ role = get_role ($ role_id); om (själv: roll_has_caps ($ roll, $ include) &&! själv :: role_has_caps ($ roll, $ exclude)) $ filtered_roles [] = $ role_id;  returnera $ filtered_roles;  / ** * Filtrera alla användare av bloggen baserat på funktioner * * @static * @param array $ inkluderar Array of capabilities att inkludera * @param array $ utesluta Array of capabilities för att utesluta * @return array * / static function filter_users ( $ inkluderar, $ utesluta) $ filtered_users = array (); $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); om (själv :: user_has_caps ($ user, $ include) &&! self :: user_has_caps ($ user, $ exclude)) $ filtered_users [] = $ användar-> ID;  returnera $ filtered_users; 

Funktionerna går igenom alla roller och användare i databasen. För varje roll (eller användare) kontrollerar den om den har de nödvändiga egenskaperna och har inte möjlighet att utesluta. Denna kontroll görs med role_has_caps () och user_has_caps () funktioner.

Dessa två funktioner (role_has_caps () och user_has_caps ()) acceptera två argument:

  • $ roll (eller $ användare) Sträng Roll-ID eller användar-ID.
  • $ caps Array En mängd möjligheter att kontrollera mot.

Om rollen (eller användaren) har angivna funktioner i $ caps array returnerar funktionen sant. I annat fall returnerar funktionen false. Funktionen går i grunden genom varje förmåga och kontrollerar att rollen (eller användaren) har den angivna funktionen.

 / ** * Returnerar sant om en roll har kapacitet i den överförda arrayen * * @static * @param $ roll * @param $ caps * @return bool * / statisk funktion role_has_caps ($ roll, $ caps) foreach caps som $ cap) if (! $ role-> has_cap ($ cap)) return false;  returnera sant;  / ** * Returnerar sant om en användare har förmågan i den överlämnade arrayen * * @static * @param $ user * @param $ caps * @return bool * / statisk funktion user_has_caps ($ user, $ caps) foreach $ caps som $ cap) if (! $ user-> has_cap ($ cap)) return false;  returnera sant; 

Lägga till behörigheter

Detta är det första steget att införa lagen i vårt plugin. Jag har fördelat funktionaliteten över 3 funktioner: En för inställning av behörigheter till alla användare, en för inställning av behörigheter till rollerna och en annan för inställning av behörigheter till de angivna användarna. Huvudfunktionen bestämmer helt enkelt vilka funktioner som ska ringas.

 / ** * Ange menyn och Sidor åtkomstbehörigheter * / privat funktion set_permissions () $ this-> set_all_permissions (); om (! $ this-> all) $ this-> set_roles_permissions (); $ This-> set_users_permissions (); 

De set_all_permissions () funktion loopar genom alla användare i bloggen, och lägg till (eller ta bort) "wptuts_client"kapacitet beroende på värdet av $ alla variabel. Vi får den fullständiga listan över användare som använder get_users () fungera; och initiera en ny WP_User föremål för att få tillgång till add_cap () och remove_cap () funktioner.

 / ** * Ange behörigheterna för ALLA användare * / privat funktion set_all_permissions () $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); om ($ this-> all) $ user-> add_cap ('wptuts_client');  else $ user-> remove_cap ('wptuts_client'); 

De set_roles_permissions () funktion loopar genom alla roller i bloggen och tar bort "wptuts_client"förmåga. Därefter slingrar det sig genom roller i $ roller array och lägger till "wptuts_client"Det första steget var att se till att vi städar möjligheten från roller som tidigare har haft det.

 / ** * Ställ in behörigheterna för roller * / privat funktion set_roles_permissions () global $ wp_roles; $ roller = $ wp_roles-> get_names (); foreach ($ roller som $ role_id => $ role_name) $ role = get_role ($ role_id); $ Roll-> remove_cap (wptuts_client ');  om (! tomt ($ this-> roller)) foreach ($ this-> roller som $ role_id) $ role = get_role ($ role_id); $ Roll-> add_cap (wptuts_client '); 

De set_users_permissions () funktionen gör samma sak som den sista funktionen. Den enda skillnaden är att den riktar sig till användare istället för roller.

 / ** * Ange behörigheterna för specifika Användare * / privat funktion set_users_permissions () $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); $ User-> remove_cap (wptuts_client ');  om (! tomt ($ this-> users)) foreach ($ this-> användare som $ user_id) $ user = new WP_User ($ user_id); $ User-> add_cap (wptuts_client '); 

Media Library Filter

Nu har vi satt rätt behörigheter för rätt enheter. (Det är antingen en användare eller en roll) Vi måste också begränsa mediebibliotekets tillgång till den fjärde kategorin som vi skiljer i scenariot.

Denna kategori av roller (eller användare) har "wptuts_client"förmåga, men har inte"ladda upp filer", och det är där våra filterfunktioner spelar in. De hjälper oss att filtrera och returnera denna kategori av roller (eller användare).

För denna kategori lägger vi till två funktioner "ladda upp filer"och"remove_upload_files"."ladda upp filer"kommer att ge fullständig tillgång till mediebiblioteket, och den andra funktionen kommer att användas för att filtrera mediabibliotekets inlägg, och det kommer också att användas för att ta bort"ladda upp filer"förmåga en gång"wptuts_client"kapacitet tas också bort.

 / ** * Begränsa mediaåtkomst * / privatfunktion media_filter () // Använd mediafiltret för nuvarande Klienter $ roller = self :: filter_roles (array ('wptuts_client'), array ('upload_files')); $ users = self :: filter_users (array ('wptuts_client'), array ('upload_files')); $ this-> roles_add_cap ($ roller, 'upload_files'); $ this-> roles_add_cap ($ roller, 'remove_upload_files'); $ this-> users_add_cap ($ users, 'upload_files'); $ this-> users_add_cap ($ users, 'remove_upload_files'); // Begränsa Media Library access add_filter ('parse_query', array (& $ this, 'restrict_media_library')); // För rengöringsändamål $ clean_roles = self :: filter_roles (array ('remove_upload_files'), array ('wptuts_client')); $ clean_users = self :: filter_users (array ('remove_upload_files'), array ('wptuts_client')); $ this-> roles_remove_cap ($ clean_roles, 'upload_files'); $ this-> roles_remove_cap ($ clean_roles, 'remove_upload_files'); $ this-> users_remove_cap ($ clean_users, 'upload_files'); $ this-> users_remove_cap ($ clean_users, 'remove_upload_files'); 

Efter att ha ställt in möjligheterna till den här kategorin kopplar vi till "parse_query"Detta filter tillåter oss att ändra de inlägg som returneras av WP_Query. I vårt fall kommer vi att ställa in "författare"frågesvariabel. Detta resulterar i att endast återkommande inlägg skapas av den angivna författaren.

 / ** * Begränsa mediebibliotekets åtkomst * * @param $ wp_query * / public function limit_media_library ($ wp_query) om (strpos ($ _ SERVER ['REQUEST_URI'], '/wp-admin/upload.php')) (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID);  annars om (strpos ($ _ SERVER ['REQUEST_URI'], '/wp-admin/media-upload.php')) if (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID); 

Den fullständiga koden

 om (! class_exists ('wpttuts_roles')) class wpttuts_roles / ** * Bestämmer om alla användare ska ha de behöriga behörigheterna * * @var boolean * / private $ all; / ** * En array med de roller som har de behöriga behörigheterna * * @var array * / private $ roller; / ** * En array med användarnamnen som har de behöriga behörigheterna * * @var array * / private $ users; / ** * Skapar en ny instans av rollerna Klass * * @param boolean $ alla * @param array $ roller * @param array $ users * / function __construct ($ all = false, $ roller = array (), $ users = array ()) // Ange de tillåtna enheterna $ this-> set_entities ($ alla, $ roller, $ users); // Ange behörighet för användaråtkomst $ this-> set_permissions (); // Media Library Filter $ this-> media_filter ();  / ** * Ange behörighetsenheter * * @param boolean $ all * @param array $ roller * @param array $ users * / privatfunktion set_entities ($ all, $ roller, $ users) $ this-> all = $ allt; $ this-> roller = $ roller; $ this-> users = $ users;  / ** * Ange menyn och Sidor åtkomstbehörigheter * / privat funktion set_permissions () $ this-> set_all_permissions (); om (! $ this-> all) $ this-> set_roles_permissions (); $ This-> set_users_permissions ();  / ** * Ange behörigheterna för ALLA användare * / privat funktion set_all_permissions () $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); om ($ this-> all) $ user-> add_cap ('wptuts_client');  else $ user-> remove_cap ('wptuts_client');  / ** * Ange behörigheterna för roller * / privat funktion set_roles_permissions () global $ wp_roles; $ roller = $ wp_roles-> get_names (); foreach ($ roller som $ role_id => $ role_name) $ role = get_role ($ role_id); $ Roll-> remove_cap (wptuts_client ');  om (! tomt ($ this-> roller)) foreach ($ this-> roller som $ role_id) $ role = get_role ($ role_id); $ Roll-> add_cap (wptuts_client ');  / ** * Ställ in behörigheterna för specifika användare * / privata funktion set_users_permissions () $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); $ User-> remove_cap (wptuts_client ');  om (! tomt ($ this-> users)) foreach ($ this-> användare som $ user_id) $ user = new WP_User ($ user_id); $ User-> add_cap (wptuts_client ');  / ** * Begränsa mediaåtkomst * / privatfunktion media_filter () // Använda mediefiltret för currenct AdPress Clients $ roles = self :: filter_roles (array ('wptuts_client'), array ('upload_files')) ; $ users = self :: filter_users (array ('wptuts_client'), array ('upload_files')); $ this-> roles_add_cap ($ roller, 'upload_files'); $ this-> roles_add_cap ($ roller, 'remove_upload_files'); $ this-> users_add_cap ($ users, 'upload_files'); $ this-> users_add_cap ($ users, 'remove_upload_files'); // Begränsa Media Library access add_filter ('parse_query', array (& $ this, 'restrict_media_library')); // För rengöringsändamål $ clean_roles = self :: filter_roles (array ('remove_upload_files'), array ('wptuts_client')); $ clean_users = self :: filter_users (array ('remove_upload_files'), array ('wptuts_client')); $ this-> roles_remove_cap ($ clean_roles, 'upload_files'); $ this-> roles_remove_cap ($ clean_roles, 'remove_upload_files'); $ this-> users_remove_cap ($ clean_users, 'upload_files'); $ this-> users_remove_cap ($ clean_users, 'remove_upload_files');  / ** * Lägg till en förmåga till en Array of Roles * * @param $ roller * @param $ cap * / privat funktion roles_add_cap ($ roller, $ cap) foreach ($ roller som $ roll) $ role = get_role ($ roll); $ Roll-> add_cap ($ cap);  / ** * Lägg till en förmåga till en användargrupp * * @param $ användare * @param $ cap * / privat funktion users_add_cap ($ användare, $ cap) foreach ($ användare som $ användare) $ user = ny WP_User ($ användare); $ User-> add_cap ($ cap);  / ** * Ta bort en funktion från en Array of Roles * * @param $ roller * @param $ cap * / privat funktion roles_remove_cap ($ roller, $ cap) foreach ($ roller som $ roll) $ role = get_role ($ roll); $ Roll-> remove_cap ($ cap);  / ** * Ta bort en funktion från en användargrupp * * @param $ användare * @param $ cap * / privat funktion users_remove_cap ($ användare, $ cap) foreach ($ användare som $ användare) $ user = ny WP_User ($ användare); $ User-> remove_cap ($ cap);  / ** * Filtrera alla roller i bloggen baserat på funktioner * * @static * @param array $ inkluderar Array of capabilities att inkludera * @param array $ utesluta Array of capabilities för att utesluta * @return array * / statisk funktion filter_roles ($ inkluderar, $ utesluta) $ filtered_roles = array (); globala $ wp_roles; $ roller = $ wp_roles-> get_names (); foreach ($ roller som $ role_id => $ role_name) $ role = get_role ($ role_id); om (själv: roll_has_caps ($ roll, $ include) &&! själv :: role_has_caps ($ roll, $ exclude)) $ filtered_roles [] = $ role_id;  returnera $ filtered_roles;  / ** * Returnerar sant om en roll har förmågan i den passerade gruppen * * @ Static * @ Param $ roll * @param $ caps * @return bool * / statisk funktion role_has_caps ($ roll, $ caps) foreach $ caps som $ cap) if (! $ role-> has_cap ($ cap)) return false;  returnera sant;  / ** * Filtrera alla användare av bloggen baserat på funktioner * * @static * @param array $ inkluderar Array of capabilities att inkludera * @param array $ utesluta Array of capabilities för att utesluta * @return array * / static function filter_users ( $ inkluderar, $ utesluta) $ filtered_users = array (); $ users = get_users (); foreach ($ användare som $ användare) $ user = new WP_User ($ user-> ID); om (själv :: user_has_caps ($ user, $ include) &&! self :: user_has_caps ($ user, $ exclude)) $ filtered_users [] = $ användar-> ID;  returnera $ filtered_users;  / ** * Returnerar sant om en användare har förmågan i den överlämnade arrayen * * @static * @param $ user * @param $ caps * @return bool * / statisk funktion user_has_caps ($ user, $ caps) foreach $ caps som $ cap) if (! $ user-> has_cap ($ cap)) return false;  returnera sant;  / ** * Begränsa mediebibliotekets åtkomst * * @param $ wp_query * / allmän funktion limit_media_library ($ wp_query) om (strpos ($ _ SERVER ['REQUEST_URI'], '/wp-admin/upload.php'))  om (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID);  annars om (strpos ($ _ SERVER ['REQUEST_URI'], '/wp-admin/media-upload.php')) if (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID); 

Slutsats

I denna handledning försökte jag använda det material vi lärde oss från de föregående två inläggen för att skapa en anpassad lösning för roller och funktioner. Lösningen inkapslades i en klass som kan anpassas för dina egna behov eller plugins. Du kan hitta koden på Github.

Om du har några frågor, förslag eller förbättringar kan du skicka in det i kommentarerna.