编写GLPI插件以重新打开订单

你好。



今天,我们将讨论我如何编写GLPI插件以处理基于已关闭订单创建的新订单,或者在收到来自用户的其他请求的情况下重新打开已关闭订单的方法。

背景知识



近一个月来,我一直在研究GLPI服务台系统的源代码。在研究此开源解决方案时,我提请注意开发人员可忽略的信息量。绝大多数材料与界面中的GLPI配置有关。少一些,但是您仍然可以找到有关设置服务器的信息。只有一篇文章(和英文)讲述了这个奇迹系统的插件开发。



从官方手册中-在readthedocs上的一些资源,以及从phpdoc生成的手册。



来自社区-电报中的聊天和外国论坛。

输入参数如下。



有一个GLPI服务台系统。来自用户的应用程序发送到连接到系统的专用邮箱。支持回复也通过邮件到达。通常,从第一次调用到决策和关闭的所有有关应用程序进度的通知都会发送到邮件中。



但是,如果用户认为自己的问题尚未得到妥善解决,并决定对有关关闭应用程序的信件做出回应,那么将创建新票证而不是重新打开票证,并将旧票证与该票证捆绑在一起。实际上,这个问题必须解决。



所以走吧



第一步是安装插件生成器-通过创建我们未来插件的框架,极大地简化了生活。可以使用以下算法完成此操作:



  • (/path/to/glpi/plugins)
  • :



    $ ./plugin.sh YourPluginName 1.0


    YourPluginName — , 1.0 — .



就是这样,框架已经准备好了。



进入创建的插件目录,您将看到一堆文件,其中仅需要setup.php和hook.php。如果计划使用其他库,则可以保留composer.json。我不需要这些文件,因此只留下了2个必需的文件。setup.php



文件中有两个必需的功能-plugin_init_yourpluginnameplugin_version_yourpluginname。第一个初始化插件,第二个返回有关它的信息-名称,作者,版本等。



对于第二个,一切都差不多。因此,我们将简要介绍第一个功能。它与全局变量$ PLUGIN_HOOKS一起使用... 当然,每个人都知道钩子是什么,但是如果有人不知道,那就是所谓的。插件拉出的系统挂钩。您可以在官方手册中阅读有关钩子的更多信息



每个插件都必须注册csrf_compatible钩子,否则您将无法激活它,将出现如下错误:





我不知道这个参数是什么,直到我弄清楚系统到底。如果读者中有GLPI专家,请在评论中写。




除了强制性钩子之外,您还可以注册其他许多钩子,例如,设置指向设置页面的链接:



$PLUGIN_HOOKS['config_page']['yourpluginname'] = 'config.php';


插件类也在此函数中注册:

Plugin::registerClass(PluginYourpluginnameConfig::class);
, , , GLPI , . : Plugin + + . , , .



: PluginYourpluginnameConfig, config.class.php. inc ( , , , , — — , - ).



.

让我们回到钩子上。我需要跟踪新取消的创建,因此我将注册一个挂钩处理程序pre_item_add您可以将参数传递给处理程序,这是使用关联数组完成的,其中键是所需实体的对象(在我的例子中是Ticket),值是处理程序函数的名称。



结果,就我而言,setup.php文件的两个必需功能如下所示:



/**
 * 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',
         ]
      ]
   ];
}


该文档说,可以将类的静态方法注册为处理程序,在这种情况下,它们应该看起来像这样(顺便说一下,根本没有必要将任何参数传递给处理程序):



/*     */

//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'];


处理函数本身存储在hook.php文件中。安装和卸载插件的功能也存储在此处。函数名称的相同要求是plugin_yourpluginname_function_name。



顺便说一句,我试图注册一个静态方法来处理该钩子,并将Ticket对象传递给参数,但是由于某种原因,对我来说没有任何作用。但是使用通常的功能,一切都可以完成。因此,为了不让钩子.php堆满不必要的代码,我注册了一个包含钩子处理程序方法的类,在所需的函数中,该方法简称为:



// hook.php

/**
 * @param Ticket $ticket
 *
 * @return bool
 */
function plugin_advtickets_pre_item_add(Ticket $ticket)
{
    return PluginAdvticketsEvent::pre_item_add_ticket($ticket);
}


如果需要在数据库中安装表,则官方文档中有一个与此主题有关的单独段落。我不需要桌子,所以我跳过了这一刻。



好了,我们已经弄清楚了如何安装/卸载插件,注册和调用钩子处理程序,现在是时候弄清楚我们将如何处理新请求了。



为此,如上所述,我注册了PluginAdvticketsEvent(文件inc / event.php),其中包含一个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;
        }
    }
}


就这样。感谢您的关注。源代码一如既往地在github上



相关链接:



GLPI官方网站

官方论坛

电报聊天

示例插件

的文档

APIDoc开发商

对插件的创建文档

的GLPI插件创建文章



All Articles