Aujourd'hui, nous allons parler de la façon dont j'ai écrit le plugin GLPI pour travailler avec de nouvelles commandes créées sur la base de commandes déjà fermées, ou plutôt la réouverture de commandes fermées, si des demandes supplémentaires de l'utilisateur sont reçues pour celles-ci.
ContexteLes paramètres d'entrée sont les suivants.
Depuis près d'un mois maintenant, je fouille dans le code source du système d'assistance GLPI. Et en étudiant cette solution open source, j'ai attiré l'attention sur la quantité négligeable d'informations pour les développeurs. La grande majorité du matériel est liée à la configuration GLPI au sein de l'interface. Un peu moins, mais vous pouvez toujours trouver des informations sur la configuration du serveur. Et un seul article (et celui en anglais) parle du développement de plugins pour ce système miracle.
Des manuels officiels - quelques ressources sur readthedocs, plus un manuel généré à partir de phpdoc.
De la communauté - un chat dans le télégramme et un forum étranger.
Il existe un système d'assistance GLPI. Les candidatures des utilisateurs sont envoyées vers une boîte aux lettres dédiée connectée au système. La réponse du service d'assistance arrive également par courrier. En général, toutes les notifications sur l'avancement de la demande du premier appel à la décision et à la clôture sont envoyées par courrier.
Cependant, si l'utilisateur considère que son problème n'a pas été correctement résolu et décide de répondre à la lettre de clôture de la demande, alors au lieu de la rouvrir, une nouvelle demande est créée et l'ancien ticket y est simplement attaché. En fait, ce problème devait être résolu.
Alors allons-y.
La première étape consiste à installer le générateur de plugin- cela simplifie grandement la vie en créant le squelette de notre futur plugin. Cela peut être fait en utilisant l'algorithme suivant:
Et voilà, le cadre est prêt.
En allant dans le répertoire du plugin que vous avez créé, vous verrez un tas de fichiers, dont seuls setup.php et hook.php sont vraiment nécessaires. Si vous prévoyez d'utiliser des bibliothèques supplémentaires, vous pouvez quitter composer.json. Je n'en avais pas besoin, alors je n'ai laissé que 2 fichiers nécessaires.
Il y a deux fonctions requises dans le fichier setup.php - plugin_init_yourpluginname et plugin_version_yourpluginname . Le premier initialise le plugin, le second retourne des informations à son sujet - nom, auteur, version, etc.
Avec le second, tout est plus ou moins clair. Par conséquent, nous nous concentrerons brièvement sur la première fonction. Cela fonctionne avec la variable globale $ PLUGIN_HOOKS... Tout le monde sait sûrement ce que sont les crochets, mais si quelqu'un n'est pas au courant, c'est ce qu'on appelle. hooks système que le plugin tire. Vous pouvez en savoir plus sur les crochets dans le manuel officiel .
Chaque plugin doit enregistrer le hook csrf_compliant , sinon vous ne pourrez tout simplement pas l'activer, il y aura une erreur comme celle-ci:
Je ne sais pas quel est ce paramètre, jusqu'à ce que j'aie compris le système jusqu'à la fin. S'il y a des experts GLPI parmi les lecteurs, écrivez dans les commentaires.
En plus du crochet obligatoire, vous pouvez en enregistrer de nombreux autres, par exemple, définir un lien vers la page des paramètres:
$PLUGIN_HOOKS['config_page']['yourpluginname'] = 'config.php';
Les classes de plugins sont également enregistrées dans cette fonction:
Plugin::registerClass(PluginYourpluginnameConfig::class);
, , , GLPI , . : Plugin + + . , , .Revenons à nos crochets. J'ai besoin de suivre la création d'un nouveau ticket d' annulation, je vais donc enregistrer le gestionnaire de hook pre_item_add . Vous pouvez passer des paramètres au gestionnaire, cela se fait à l'aide d'un tableau associatif, où la clé est l'objet de l'entité souhaitée (dans mon cas, Ticket), et la valeur est le nom de la fonction du gestionnaire.
: PluginYourpluginnameConfig, config.class.php. inc ( , , , , — — , - ).
.
En conséquence, dans mon cas, les deux fonctions requises du fichier setup.php ressemblent à ceci:
/**
* Init hooks of the plugin.
* REQUIRED
*
* @return void
*/
function plugin_init_advtickets() {
global $PLUGIN_HOOKS;
Plugin::registerClass(PluginAdvticketsEvent::class);
$PLUGIN_HOOKS['csrf_compliant']['advtickets'] = true;
$PLUGIN_HOOKS['pre_item_add']['advtickets'] = [
Ticket::class => 'plugin_advtickets_pre_item_add'
];
}
/**
* Get the name and the version of the plugin
* REQUIRED
*
* @return array
*/
function plugin_version_advtickets() {
return [
'name' => 'Adv Tickets',
'version' => PLUGIN_ADVTICKETS_VERSION,
'author' => 'Roman Gonyukov',
'license' => '',
'homepage' => 'https://github.com/stayfuneral/advtickets',
'requirements' => [
'glpi' => [
'min' => '9.2',
]
]
];
}
La documentation dit qu'il est possible d'enregistrer des méthodes statiques de classes en tant que gestionnaire, auquel cas elles devraient ressembler à ceci (au fait, il n'est pas du tout nécessaire de passer des paramètres au gestionnaire):
/* */
//call a function
$PLUGIN_HOOKS['hook_name']['plugin_name'] = 'function_name';
//call a static method from an object
$PLUGIN_HOOKS['other_hook']['plugin_name'] = ['ObjectName', 'methodName'];
Les fonctions du gestionnaire elles-mêmes sont stockées dans le fichier hook.php. Les fonctions d'installation et de désinstallation du plugin y sont également stockées. Les noms de fonction ont les mêmes exigences - plugin_yourpluginname_function_name.
Au fait, j'ai essayé d'enregistrer une méthode statique pour gérer le hook et passer l'objet Ticket aux paramètres, mais pour une raison quelconque, rien n'a fonctionné pour moi. Mais avec la fonction habituelle, tout a fonctionné. Par conséquent, afin de ne pas jeter hook.php avec du code inutile, j'ai enregistré une classe qui contient une méthode de gestionnaire de hook, et dans la fonction requise, j'ai simplement appelé cette méthode:
// hook.php
/**
* @param Ticket $ticket
*
* @return bool
*/
function plugin_advtickets_pre_item_add(Ticket $ticket)
{
return PluginAdvticketsEvent::pre_item_add_ticket($ticket);
}
Si vous devez installer des tables dans une base de données, la documentation officielle contient un paragraphe distinct sur ce sujet. Je n'avais pas besoin des tables, alors je saute ce moment.
Eh bien, nous avons en quelque sorte compris l'installation / la suppression du plugin, l'enregistrement et les gestionnaires de hook d'appel, il est maintenant temps de comprendre comment nous allons traiter la nouvelle demande.
Pour ce faire, comme mentionné ci-dessus, j'ai enregistré la classe PluginAdvticketsEvent (fichier inc / event.php), qui contient une seule méthode pre_item_add_ticket .
class PluginAdvticketsEvent extends CommonDBTM
{
static function pre_item_add_ticket(Ticket $ticket)
{
global $DB;
// .. , input
$fields = $ticket->input;
// , ( )
if($fields['_link']['tickets_id_2']) {
$relatedTicketId = $fields['_link']['tickets_id_2'];
$relatedTicketParamsForUpdate = [
'itemtype' => \Ticket::class, // ,
'items_id' => $relatedTicketId, // id
'users_id' => $fields['_users_id_requester'], // id
'users_id_editor' => 0,
'content' => $fields['content'],
'date' => date('c'),
'date_mod' => date('c'),
'date_creation' => date('c'),
'is_private' => 0,
'requesttypes_id' => $fields['requesttypes_id'], // (helpdesk, email ..)
'timeline_position' => 4,
'sourceitems_id' => 0,
'sourceof_items_id' => 0
];
// ( , ), . , glpi_itilfollowups
$DB->insert('glpi_itilfollowups', $relatedTicketParamsForUpdate);
// , "". glpi_tickets
$DB->update('glpi_tickets', [
'status' => 1
], [
'id' => $relatedTicketId
]);
// .. , input false. .
$ticket->input = false;
return $ticket->input;
}
}
}
C'est tout. Merci de votre attention. Code source, comme toujours sur github .
Liens utiles:
Site Web
officiel de GLPI Forums officiels Exemple de
discussion de télégramme Documentation de
plug- in
pour les
développeurs APIDoc
Documentation sur la création de plug-ins Article sur la création de plug- in
GLPI