Rôles et fonctionnalités de WordPress un exemple concret

Ce tutoriel en quatre parties couvre les utilisateurs WordPress, les rôles et les fonctionnalités. La série couvrira l'architecture et la conception des rôles d'utilisateur dans WordPress; souligner les fonctions les plus importantes pour interagir avec les utilisateurs et gérer les rôles et les fonctionnalités; et dans le dernier tutoriel, nous allons construire un exemple réel qui démontre l'utilité de cette API.


introduction

Ce tutoriel sera axé sur la création d’une solution pratique utilisant le système de rôles et de fonctionnalités de WordPress. Si vous avez manqué les deux derniers tutoriels, je vous suggère fortement de les consulter. La première partie "Rôles et fonctionnalités de WordPress: notions de base" explique la conception de ce système; La seconde partie, intitulée "Rôles et fonctionnalités de WordPress: Fonctions de la note", porte sur les fonctions et les classes offertes par WordPress pour interagir avec le système..

La solution proposée dans ce tutoriel est la même que celle que j'utilise pour l'un de mes plugins WordPress premium. Je l'ai choisi après avoir essayé différentes approches. C'est simple, court et encapsulé dans une classe. Vous pouvez facilement l'adapter à votre propre plugin. Le code est disponible sur GitHub; et n'est pas autorisé. En outre, il n’ya aucune garantie et vous êtes libre de l’utiliser et de le concéder sous licence à votre guise..


Étape 1 Le scénario

Nous construisons un plugin WordPress qui a un panneau d’administration client spécial. Ce panneau d'administration ne devrait être accessible qu'à un nombre limité d'utilisateurs. Ces utilisateurs peuvent être sélectionnés par l'administrateur du blog. Il peut activer différents rôles, utilisateurs ou tous d’eux pour accéder au panneau d’administration ou aux fonctionnalités du client..

En dehors de cela, nous devons avoir un accès limité à la médiathèque pour les utilisateurs ayant un accès au panneau client. WordPress a une capacité spéciale pour accéder et télécharger des fichiers dans la médiathèque: "télécharger des fichiers". Cependant, cela donne à l'utilisateur (ou au rôle) un accès complet à la médiathèque. Ce n'est pas une bonne chose, surtout que les photos (ou fichiers) ne peuvent pas être hiérarchisées sous différentes catégories où vous pouvez restreindre l'accès à chacune d'elles..

Nous devons limiter l'accès à la médiathèque aux fichiers que l'utilisateur a téléchargés. Il ne devrait pas avoir accès aux téléchargements d'autres utilisateurs. Cette restriction ne devrait s'appliquer qu'aux utilisateurs qui n'ont pas le "télécharger des fichiers"capacité. Les autres utilisateurs et rôles ne sont pas concernés par cette restriction car ils ont déjà un accès complet à la médiathèque.

Notre blog aura ces quatre catégories d'utilisateurs:

Les deux premiers groupes d'utilisateurs sont ceux qui n'auront pas accès au plugin Client Panel. J'ai souligné le fait qu'il existe des utilisateurs qui ont accès à la médiathèque et un ensemble qui n'en a pas. Il est essentiel que notre solution n'affecte pas les deux premières catégories et ne laisse pas leurs capacités intactes..

Dans cet esprit, notre classe devrait faire deux choses:

  • Définissez les autorisations appropriées sur les troisième et quatrième groupes d'utilisateurs
  • Activer l'accès limité à la quatrième catégorie de la médiathèque. Assurez-vous qu'après avoir désactivé le plug-in ou modifié les droits des utilisateurs, cette catégorie d'utilisateurs récupère ses autorisations d'origine..

Étape 2 L'interface du plugin

Avant de créer notre classe, approfondissons notre idée du plugin. Le plugin a une structure assez simple. Il est composé de deux menus différents: un pour l'administrateur et il sert de panneau d'administration, accessible uniquement aux utilisateurs ayant la capacité de "manage_options". Le deuxième menu est destiné aux clients et donne accès au panneau de client. Ce"wptuts_client_page" aptitude.

Cette fonctionnalité n'existe pas dans WordPress; nous devons l'ajouter et l'assigner aux utilisateurs ou aux rôles spécifiés. Mais avant cela, jetons un coup d'oeil dans le plugin.

 / * Nom du plugin: URI du plugin du plugin WordPress Roles: https://github.com/omarabid/WordPress-Roles-Plugin Description: Un plugin pour le rôle de WordPress Auteur: Abid Omar URI de l'auteur: http://omarabid.com Version: 1.0 * / // Ajout d'un menu utilisateur administrateur au tableau de bord WordPress add_action ('admin_menu', 'wptuts_admin_menu'); function wptuts_admin_menu () add_menu_page ('Accès administrateur', 'Accès administrateur', 'options_gérer', 'wptuts-admin', 'wptuts_admin_page');  function wptuts_admin_page () echo 'Page admin';  // Ajouter un menu utilisateur client au tableau de bord WordPress add_action ('admin_menu', 'wptuts_client_menu'); function wptuts_client_menu () add_menu_page ('Accès client', 'Accès client', 'wptuts_client', 'wptuts-client', 'wptuts_client_page');  function wptuts_client_page () echo 'Page client'; 

Nous avons deux "admin_menu"Action hooks qui ajoutent le menu Admin à la fois pour l'administrateur et le client. Nous pouvons le raccourcir en un seul crochet qui ajoute les deux; mais je préfère séparer les deux."add_menu_page"la fonction s'accroche à une autre fonction qui affichera le contenu de la page.

Ensuite, nous devons initialiser notre classe de rôles. Le code de classe est placé dans un autre fichier. et le processus d’initialisation se fait pendant la "init"crochet qui assure que le chargement de WordPress est terminé.

La fonction constructeur accepte trois paramètres:

  • $ tout Booléen (facultatif) Si vous souhaitez autoriser le client à accéder à tous les utilisateurs du blog, vous pouvez le définir sur true et ignorer les paramètres restants..
  • $ rôles Tableau (facultatif) Un tableau avec les identifiants de rôles qui auront accès au panneau client.
  • $ utilisateurs Tableau (facultatif) Un tableau avec les noms d'utilisateurs qui auront accès au panneau client.
 // Charge et initialise la classe de rôles add_action ('init', 'wptuts_start_plugin'); fonction wptuts_start_plugin () require_once ('roles_class.php'); $ all = false; $ roles = array ('abonné'); $ utilisateurs = tableau (3); new wpttuts_roles ($ all, $ rôles, $ utilisateurs); 

Étape 3: la classe de rôles

Les propriétés

La classe n'a que 3 propriétés: $ tout, $ rôles et $ utilisateurs. Ce sont les mêmes variables que vous passez à la fonction constructeur. La valeur des variables n'est pas modifiée dans notre exemple. mais dans un cas concret, vous pouvez fusionner avec une autre source. Pour cela, vous avez le set_entities une fonction. Vous pouvez l'adapter à vos propres besoins.

 / ** * @var boolean * / private $ all; / ** * @var array * / private $ roles; / ** * @var array * / private $ users; / ** * Définir les entités de permission * * @param boolean $ all * @param tableau $ rôles * @param tableau $ utilisateurs * / fonction privée set_entities ($ all, $ rôles, $ utilisateurs) $ this-> all = $ tout; $ this-> rôles = $ rôles; $ this-> utilisateurs = $ utilisateurs; 

La fonction constructeur

Dans un premier temps, la fonction constructeur initialise le $ tout, $ rôles et $ utilisateurs variables utilisant le set_entitites () une fonction. Ensuite, il appelle une fonction privée pour définir les capacités et une autre pour la restriction de la bibliothèque multimédia. Ce sont exactement les étapes que nous avons définies dans notre scénario.

 / ** * Crée une nouvelle instance de la classe de rôles * * @param booléen $ all * @param tableau $ rôles * @param tableau $ utilisateurs * / fonction __construct ($ tout = faux, $ rôles = array (), $ utilisateurs = array ()) // Définit les entités autorisées $ this-> set_entities ($ all, $ roles, $ utilisateurs); // Définir la permission d'accès de l'utilisateur $ this-> set_permissions (); // Filtre de la bibliothèque multimédia $ this-> media_filter (); 

Fonctions statiques

Les fonctions statiques ne nécessitent pas d'initialisation de classe. Elles sont similaires aux fonctions indépendantes, mais simplement liées à la classe spécifiée. J'ai décidé de garder certaines fonctions statiques car elles peuvent être utilisées indépendamment. et vous pourriez les trouver utiles dans un autre contexte.

Ces fonctions sont filter_roles () et filter_users (); qui sont associés à deux autres fonctions role_has_caps () et user_has_caps (). Les fonctions jouent le rôle d'un filtre. Ils filtrent les rôles (ou les utilisateurs) en fonction des capacités dont ils disposent et n’ont pas.

Les deux fonctions acceptent deux arguments:

  • $ include Tableau Un éventail de fonctionnalités que le rôle a.
  • $ exclure Tableau Un éventail de fonctionnalités que le rôle n'a pas.
 / ** * Filtrer tous les rôles du blog en fonction des fonctionnalités * * @static * @param array $ include Tableau de fonctionnalités à inclure * @param array $ exclude Tableau de fonctionnalités à exclure * @return array * / static function filter_roles ($ inclure, $ exclure) $ filtré_roles = array (); global $ wp_roles; $ rôles = $ wp_roles-> get_names (); foreach ($ rôles comme $ role_id => $ role_name) $ role = get_role ($ role_id); if (self :: role_has_caps ($ role, $ include) &&! self :: role_has_caps ($ role, $ exclude)) $ filter_roles [] = $ role_id;  return $ filtré_roles;  / ** * Filtrer tous les utilisateurs du blog en fonction des fonctionnalités * * @static * @param array $ include Tableau de fonctionnalités à inclure * @param array $ exclude Tableau de fonctionnalités à exclure * @return array * / static function filter_users ( $ include, $ exclude) $ filtré_users = array (); $ utilisateurs = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); if (self :: user_has_caps ($ user, $ include) &&! self :: user_has_caps ($ user, $ exclude)) $ filtré_utilisateurs [] = $ user-> ID;  return $ filtré_utilisateurs; 

Les fonctions parcourent tous les rôles et utilisateurs de la base de données. Pour chaque rôle (ou utilisateur), il vérifie s'il dispose des fonctionnalités requises et non des fonctionnalités à exclure. Cette vérification est faite avec le role_has_caps () et user_has_caps () les fonctions.

Ces deux fonctions (role_has_caps () et user_has_caps ()) accepte deux arguments:

  • $ rôle (ou $ utilisateur) Chaîne L'ID du rôle ou l'ID utilisateur.
  • $ casquettes Tableau Un éventail de fonctionnalités à vérifier.

Si le rôle (ou l'utilisateur) dispose des fonctionnalités spécifiées dans la $ casquettes tableau, la fonction retourne vrai. Dans le cas contraire, la fonction renvoie false. La fonction parcourt fondamentalement chaque capacité et vérifie que le rôle (ou l'utilisateur) a la capacité spécifiée..

 / ** * Renvoie true si un rôle a les capacités du tableau passé * * @ @static * @param $ role * @param $ caps * @return bool * / static function role_has_caps ($ role, $ caps) foreach ($ caps as $ cap) if (! $ role-> has_cap ($ cap)) return false;  return true;  / ** * Renvoie true si un utilisateur dispose des fonctionnalités du tableau transmis * * @ @static * @param $ user * @param $ caps * @return bool * / static function user_has_caps ($ user, $ caps) foreach ( $ caps as $ cap) if (! $ user-> has_cap ($ cap)) return false;  return true; 

Ajouter des autorisations

C'est la première étape pour imposer la loi de notre plugin. J'ai réparti les fonctionnalités sur 3 fonctions: une pour la définition des autorisations de tous les utilisateurs, une pour la définition des autorisations des rôles et une autre pour la définition des autorisations des utilisateurs spécifiés. La fonction principale décide simplement des fonctions à appeler.

 / ** * Définir les autorisations d'accès au menu et aux pages * / private function set_permissions () $ this-> set_all_permissions (); if (! $ this-> all) $ this-> set_roles_permissions (); $ this-> set_users_permissions (); 

le set_all_permissions () fonction parcourt tous les utilisateurs du blog et ajoute (ou supprime) le "wptuts_client"capacité en fonction de la valeur de la $ tout variable. Nous obtenons la liste complète des utilisateurs utilisant le get_users () une fonction; et initialiser un nouveau WP_User objet pour avoir accès à la add_cap () et remove_cap () les fonctions.

 / ** * Définir les autorisations pour TOUS les utilisateurs * / private function set_all_permissions () $ users = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); if ($ this-> all) $ user-> add_cap ('wptuts_client');  else $ user-> remove_cap ('wptuts_client'); 

le set_roles_permissions () fonction en boucle à travers tous les rôles du blog et supprime le "wptuts_client"capacité. Après cela, il boucle à travers les rôles dans le $ rôles tableau et ajoute le "wptuts_client"capacité. La première étape consistait à nous assurer que la capacité était supprimée des rôles qui auraient pu l'être auparavant.

 / ** * Définir les autorisations pour les rôles * / private function set_roles_permissions () global $ wp_roles; $ rôles = $ wp_roles-> get_names (); foreach ($ rôles comme $ role_id => $ role_name) $ role = get_role ($ role_id); $ role-> remove_cap ('wptuts_client');  if (! empty ($ this-> rôles)) foreach ($ this-> rôles en tant que $ role_id) $ role = get_role ($ role_id); $ role-> add_cap ('wptuts_client'); 

le set_users_permissions () function fait la même chose que la dernière fonction. La seule différence est qu'il cible les utilisateurs plutôt que les rôles..

 / ** * Définir les autorisations pour des utilisateurs spécifiques * / fonction privée set_users_permissions () $ users = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); $ user-> remove_cap ('wptuts_client');  if (! empty ($ this-> utilisateurs)) foreach ($ this-> utilisateurs en tant que $ user_id) $ user = new WP_User ($ user_id); $ user-> add_cap ('wptuts_client'); 

Filtre de médiathèque

Nous avons maintenant défini les bonnes autorisations pour les bonnes entités. (En tant qu'utilisateur ou rôle) Nous devons également limiter l'accès à la médiathèque pour la quatrième catégorie que nous avons distinguée dans le scénario..

Cette catégorie de rôles (ou utilisateurs) a le "wptuts_client"capacité, mais n'a pas le"télécharger des fichiers"capacité. C’est là que nos fonctions de filtrage entrent en jeu. Elles nous aident à filtrer et à renvoyer cette catégorie de rôles.

Pour cette catégorie, nous ajouterons deux capacités "télécharger des fichiers" et "remove_upload_files". Le "télécharger des fichiers"donnera un accès complet à la médiathèque; l’autre fonctionnalité sera utilisée pour filtrer les publications de la médiathèque et sera également utilisée pour supprimer le"télécharger des fichiers"capacité une fois"wptuts_client"la capacité est également supprimée.

 / ** * Restreindre l'accès au média * / private function media_filter () // Appliquer le filtre de média pour les clients actuels $ roles = self :: filter_roles (array ('wptuts_client'), array ('upload_files')); $ utilisateurs = self :: filter_users (array ('wptuts_client'), array ('upload_files')); $ this-> roles_add_cap ($ roles, 'upload_files'); $ this-> roles_add_cap ($ roles, 'remove_upload_files'); $ this-> users_add_cap ($ users, 'upload_files'); $ this-> users_add_cap ($ users, 'remove_upload_files'); // Restreindre l'accès à la médiathèque add_filter ('parse_query', array (& $ this, 'restrict_media_library')); // à des fins de nettoyage $ 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'); 

Après avoir défini les capacités dans cette catégorie, nous nous associons au "parse_query"filtre. Ce filtre nous permet de modifier les messages renvoyés par WP_Query. Dans notre cas, nous allons définir le "auteur"variable de requête. Il en résulte que seuls les messages créés par l'auteur spécifié sont renvoyés..

 / ** * Restreindre l'accès à la bibliothèque multimédia * * @param $ wp_query * / public function restrict_media_library ($ wp_query) if (strpos ($ _ SERVER ['REQUEST_URI'], '/ wp-admin/upload.php')) if (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID);  else if (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); 

Le code complet

 if (! class_exists ('wpttuts_roles')) class wpttuts_roles / ** * Détermine si tous les utilisateurs disposeront des autorisations requises * * @ @ boolean * / private $ all; / ** * Un tableau avec les rôles disposant des autorisations requises * * @var array * / private $ roles; / ** * Un tableau avec les noms d'utilisateur disposant des autorisations requises * * @var array * / private $ users; / ** * Crée une nouvelle instance de la classe de rôles * * @param booléen $ all * @param tableau $ rôles * @param tableau $ utilisateurs * / fonction __construct ($ tout = faux, $ rôles = array (), $ utilisateurs = array ()) // Définit les entités autorisées $ this-> set_entities ($ all, $ roles, $ utilisateurs); // Définir la permission d'accès de l'utilisateur $ this-> set_permissions (); // Filtre de la bibliothèque multimédia $ this-> media_filter ();  / ** * Définir les entités de permission * * @param booléen $ all * @param tableau $ rôles * @param tableau $ utilisateurs * / fonction privée set_entities ($ all, $ rôles, $ utilisateurs) $ this-> all = $ tout; $ this-> rôles = $ rôles; $ this-> utilisateurs = $ utilisateurs;  / ** * Définir les autorisations d'accès au menu et aux pages * / private function set_permissions () $ this-> set_all_permissions (); if (! $ this-> all) $ this-> set_roles_permissions (); $ this-> set_users_permissions ();  / ** * Définir les autorisations pour TOUS les utilisateurs * / private function set_all_permissions () $ users = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); if ($ this-> all) $ user-> add_cap ('wptuts_client');  else $ user-> remove_cap ('wptuts_client');  / ** * Définir les autorisations pour les rôles * / private function set_roles_permissions () global $ wp_roles; $ rôles = $ wp_roles-> get_names (); foreach ($ rôles comme $ role_id => $ role_name) $ role = get_role ($ role_id); $ role-> remove_cap ('wptuts_client');  if (! empty ($ this-> rôles)) foreach ($ this-> rôles en tant que $ role_id) $ role = get_role ($ role_id); $ role-> add_cap ('wptuts_client');  / ** * Définir les autorisations pour des utilisateurs spécifiques * / fonction privée set_users_permissions () $ users = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); $ user-> remove_cap ('wptuts_client');  if (! empty ($ this-> utilisateurs)) foreach ($ this-> utilisateurs en tant que $ user_id) $ user = new WP_User ($ user_id); $ user-> add_cap ('wptuts_client');  / ** * Restreindre l'accès au média * / private function media_filter () // Appliquer le filtre de média pour les clients AdPress actuels $ roles = self :: filter_roles (array ('wptuts_client'), array ('upload_files')) ; $ utilisateurs = self :: filter_users (array ('wptuts_client'), array ('upload_files')); $ this-> roles_add_cap ($ roles, 'upload_files'); $ this-> roles_add_cap ($ roles, 'remove_upload_files'); $ this-> users_add_cap ($ users, 'upload_files'); $ this-> users_add_cap ($ users, 'remove_upload_files'); // Restreindre l'accès à la médiathèque add_filter ('parse_query', array (& $ this, 'restrict_media_library')); // à des fins de nettoyage $ 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');  / ** * Ajoute une capacité à un tableau de rôles * * @param $ roles * @param $ cap * / fonction privée roles_add_cap ($ roles, $ cap) foreach ($ roles as $ role) $ role = get_role ($ rôle); $ role-> add_cap ($ cap);  / ** * Ajoute une fonctionnalité à un tableau d'utilisateurs * * @param $ utilisateurs * @param $ cap * / fonction privée users_add_cap ($ utilisateurs, $ cap) foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = new WP_User ($ user); $ user-> add_cap ($ cap);  / ** * Supprimer une fonctionnalité d'un tableau de rôles * * @param $ roles * @param $ cap * / private function roles_remove_cap ($ roles, $ cap) foreach ($ roles as $ role) $ role = get_role ($ role); $ role-> remove_cap ($ cap);  / ** * Supprimer une fonctionnalité d'un tableau d'utilisateurs * * @param $ utilisateurs * @param $ cap * / fonction privée users_remove_cap ($ utilisateurs, $ cap) foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = new WP_User ($ user); $ user-> remove_cap ($ cap);  / ** * Filtrez tous les rôles du blog en fonction des fonctionnalités * * @static * @param array $ include Tableau de fonctionnalités à inclure * @param array $ exclude Tableau de fonctionnalités à exclure * @return array * / static function filter_roles ($ include, $ exclude) $ filtré_roles = array (); global $ wp_roles; $ rôles = $ wp_roles-> get_names (); foreach ($ rôles comme $ role_id => $ role_name) $ role = get_role ($ role_id); if (self :: role_has_caps ($ role, $ include) &&! self :: role_has_caps ($ role, $ exclude)) $ filter_roles [] = $ role_id;  return $ filtré_roles;  / ** * Renvoie true si un rôle possède les fonctionnalités du tableau transmis * * @ @static * @param $ role * @param $ caps * @return bool * / fonction statique role_has_caps ($ role, $ caps) foreach ( $ caps as $ cap) if (! $ role-> has_cap ($ cap)) return false;  return true;  / ** * Filtrer tous les utilisateurs du blog en fonction des fonctionnalités * * @static * @param array $ include Tableau de fonctionnalités à inclure * @param array $ exclude Tableau de fonctionnalités à exclure * @return array * / static function filter_users ( $ include, $ exclude) $ filtré_users = array (); $ utilisateurs = get_users (); foreach ($ utilisateurs en tant que $ utilisateur) $ utilisateur = nouveau WP_User ($ utilisateur-> ID); if (self :: user_has_caps ($ user, $ include) &&! self :: user_has_caps ($ user, $ exclude)) $ filtré_utilisateurs [] = $ user-> ID;  return $ filtré_utilisateurs;  / ** * Renvoie true si un utilisateur dispose des fonctionnalités du tableau transmis * * @ @static * @param $ user * @param $ caps * @return bool * / static function user_has_caps ($ user, $ caps) foreach ( $ caps as $ cap) if (! $ user-> has_cap ($ cap)) return false;  return true;  / ** * Restreindre l'accès à la bibliothèque multimédia * * @param $ wp_query * / public function restrict_media_library ($ wp_query) if (strpos ($ _ SERVER ['REQUEST_URI'], '/ wp-admin/upload.php'))  if (current_user_can ('remove_upload_files')) global $ current_user; $ wp_query-> set ('author', $ current_user-> ID);  else if (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); 

Conclusion

Dans ce didacticiel, j'ai essayé d'utiliser le contenu des deux publications précédentes pour créer une solution personnalisée pour les rôles et les fonctionnalités. La solution a été encapsulée dans une classe qui peut être personnalisée pour vos propres besoins ou plugins. Vous pouvez trouver le code sur Github.

Si vous avez des questions, des suggestions ou des améliorations, n'hésitez pas à les poster dans les commentaires..