zoukankan      html  css  js  c++  java
  • [原]iTop自定义修改相关时间字段的实现要点记录

    [gzg@operation itop]$ cd /var/www/html/itop [gzg@operation itop]$ mkdir yh [gzg@operation itop]$ cd yh [gzg@operation itop]$ touch upticketdates.php

    开发简要说明:

    字典文件位置: itop/env-production/dictionaries/zh-cn.dict.php 'Class:UserRequest/Attribute:resolutiondate' => '解决时间', 'Class:UserRequest/Attribute:resolutiondate+' => '',

    iTop的底层数据支撑框架为CMDB

    一个数据模型类的继承层次为(如:UserRequest):

    UserRequest < Ticket < _Ticket < cmdbAbstractObject < CMDBObject < DBObject

    这些类的文件位置是:

    • UserRequest => O:itopenv-productionitop-request-mgmt-itilmodel.itop-request-mgmt-itil.php
    • Ticket => O:itopenv-productionitop-ticketsmodel.itop-tickets.php
    • _Ticket => O:itopenv-toolkititop-ticketsmain.itop-tickets.php
    • cmdbAbstractObject => O:itopapplicationcmdbabstract.class.inc.php
    • CMDBObject => O:itopcorecmdbobject.class.inc.php
    • DBObject => O:itopcoredbobject.class.php

    DBObject安装注释中的说明: "Class dbObject: the root of persistent classes" 它是“可持久化”的“数据模型类”的“根类”,而DBObject中操作数据库依靠的的更底层的CMDBSource(itop/core/cmdbsource.class.inc.php) CMDBSource中的数据操作则依靠“mysqli”

    self::$m_oMysqli = new mysqli(self::$m_sDBHost, self::$m_sDBUser, self::$m_sDBPwd);
    

    例如其 DBUpdate() 方法中的两行代码: $sSQL = $oFilter->MakeUpdateQuery($aChanges); CMDBSource::Query($sSQL);

    引入三个文件后,可以使用 MetaModel, 装载更新数据记录

    require_once('../approot.inc.php');
    require_once(APPROOT.'/application/application.inc.php');
    require_once(APPROOT.'/application/startup.inc.php');
    

    类MetaModel定义位于: itop/core/metamodel.class.php

    静态方法MetaModel::GetObject可以装载指定数据类 GetObject($sClass, $iKey, $bMustBeFound = true, $bAllowAllData = false, $aModifierProperties = null) 参数说明: $sClass:数据类名,例如表“itopticket”的类名为“Ticket”,可以使用基类装载子类,也可以用子类直接load $iKey:数据行的id $bMustBeFound:该id的数据行是否必须存在, 默认值为false,未找到返回null,如果设置为true,未找到抛出异常;MySQLException $bAllowAllData:是否load全部字段?? $aModifierProperties:可修改字段数组?? 使用举例: $data = MetaModel::GetObject('Ticket',1296); getclass($data); // UserRequest, 这是一条request $data->get('resolutiondate'); // 获取解决时间 $data->Set('resolutiondate','2019-12-19 12:33:34'); // 设置解决时间 $data->DBUpdate(); // 更新数据库

    最后更新时间的修改

    Ticket的三个子类 UserRequest,Problem,Incident 都覆盖了基类的OnUpdate方法,其中主要是做了更新追踪记录,设置最后更新时间 因此想要覆盖更新这个字段,只能绕开 数据模型类,幸运的是这个字段是在 基类表 Ticket中,因此可以使用CMDBSource直接修改数据库中的字段值, 从而实现最后更新时间的修改。

    CMDBSource::query("update itop_ticket set last_update='$last_update' where id = $ticket_id"); 

    整个过程实现源码:


    <?php 
    require_once('../approot.inc.php');
    require_once(APPROOT.'/application/application.inc.php');
    require_once(APPROOT.'/application/startup.inc.php');
    
    // "http://192.168.0.105/itop/pages/UI.php?c[menu]=UserRequest:OpenRequests"
    $tbls = array('UserRequest'=>'itop_ticket_request','Incident'=>'itop_ticket_incident','Problem'=>'itop_ticket_problem');
    $baseFlds = array('start_date','end_date','close_date');
    $extFlds = array('assignment_date','resolution_date');
    $ticket_id=$start_date=$end_date=$assignment_date=$close_date=$resolution_date=$last_update="";
    $error_msg = $msg= '';
    $btn='';
    /** this function , just for example */
    function __update(){
        $t=MetaModel::GetObject('Ticket',1296);
        $rd=$t->Get('resolution_date');
        $t->Set('resolution_date','2019-12-19 12:33:34');
        $t->DBUpdate();
        // direct access
        $ds = CMDBSource::query("update itop_ticket set start_date='2012-12-12 12:12:12' where id =1295"); 
        // print $ds;  // this will display:  1;
    }
    function pm($name){
        return $_POST[$name];
    }
    function has_pm($name){
        return array_key_exists($name,$_POST);
    }
    /** startup script */
    if ($_SERVER["REQUEST_METHOD"] == "POST"){    
        try{
            $ticket_id=pm('ticket_id');
            //echo("<pre>ticket_id=[$ticket_id]</pre>");
            if(strlen($ticket_id)==0){            
                $error_msg='请输入id!';
            }else{
                $data = MetaModel::GetObject('Ticket',$ticket_id, false);
                $dataClass = get_class($data); // ex: UserRequest
                //echo("data loaded=$data");    
                if(!$data){
                    echo("<script>var oDateLoaded = false;</script>");
                    $error_msg='数据未找到,该ID并不存在!';
                    goto END;
                }
                
                if(has_pm('btn_load')){
                    $btn = 'btn_load';            
                    if($data){
                        $start_date = $data->get('start_date');
                        $end_date=$data->get('end_date');
                        $assignment_date=$data->get('assignment_date');
                        $close_date=$data->get('close_date');
                        $resolution_date=$data->get('resolution_date');
                        $last_update=$data->get('last_update');
                        echo("<script>var oDateLoaded = true;</script>");
                        $msg="已成功查询到数据!";
                    }else{
                        $error_msg = "Ticket id=[" + $ticket_id +"] 未找到!";
                    }
                }else{ /** btn_save */            
                    $btn = 'btn_save';
                    $start_date = pm('start_date');
                    $end_date=pm('end_date');
                    $assignment_date=pm('assignment_date');
                    $close_date=pm('close_date');
                    $resolution_date=pm('resolution_date');
                    $last_update=pm('last_update');
                    if($start_date)$data->set('start_date',$start_date);
                    if($end_date)$data->set('end_date',$end_date);
                    if($assignment_date)$data->set('assignment_date',$assignment_date);
                    if($close_date)$data->set('close_date',$close_date);
                    if($resolution_date)$data->set('resolution_date',$resolution_date);
                    if($last_update)$data->set('last_update',$last_update);
                    //不起作用!!$data->onUpdate=function(){};
                    $data->DBUpdate();
                    //
                    if($last_update){                    
                        CMDBSource::query("update itop_ticket set last_update='$last_update' where id = $ticket_id"); 
                    }
                    //
                    echo("<script>var oDateLoaded = true;</script>");
                    $msg = "ok, 保存成功了! 您可以继续修改当前记录。";
                }
            }
        }catch(Exception $ex){
             $error_msg = $ex->getMessage();
        }
    }else{ /** GET */
        echo("<script>var oDateLoaded = false;</script>");    
    } /** end of HTTP method */
    
    END:
      echo ''
    
    ?>
    
    <div class="form" id="pane_up_ticket_dates">
        <style scoped="scoped">
            .grid-x, .button-group{
                display: flex; margin:8px;
            }
            .button-group.align-center{
                justify-content: center;
            }
            .msg-info{
                color: lightblue;
                font-size: 1.2em;
            }
        </style>
        <form method="post" action="../yh/up_ticket_dates.php" name="form_up_ticket_dates" id='form_up_ticket_dates' ">
            <h2>[请首先输入id并查询]</h2>        
            
            <div class="grid-x">        
            <label>事件ID[形如:1298]:<input type="number" name="ticket_id" value="<?php echo $ticket_id; ?>"></label>
            <button name="btn_load">查询</button>
            </div>
            <hr/><p class="msg-info">
            <?php if($msg){ ?>            
                <?php echo $msg ?>        
            <?php } ?>
            </p><hr/>
            <br/><br/>
            <div class="grid-x">
            <label>起始日期:<input type="datetime" name="start_date" value="<?php echo $start_date; ?>"></label>
            </div>
            <div class="grid-x">
            <label>结束日期:<input type="datetime" name="end_date" value="<?php echo $end_date; ?>"></label>
            </div>
            <div class="grid-x">
            <label>指派日期:<input type="datetime" name="assignment_date" value="<?php echo $assignment_date; ?>"></label>
            </div class="grid-x">
            <div class="grid-x">
            <label>关闭日期:<input type="datetime" name="close_date" value="<?php echo $close_date; ?>"></label>
            </div>
            <div class="grid-x">
            <label>解决日期:<input type="datetime" name="resolution_date" value="<?php echo $resolution_date; ?>"></label>
            </div>
            <div class="grid-x">
            <label>最后更新:<input type="datetime" name="last_update" value="<?php echo $last_update; ?>"></label>
            </div>
            <div  class="grid-x button-group align-center">
            <button name="btn_reset">清除</button><div style="5em;"></div> <button name="btn_save" >更新</button>
            </div>
        </form>
        <br/>
        
        <div id="error_pad" style="color:red;">
        <?php if($error_msg){ ?>
            <?php echo($error_msg); ?>
        <?php } ?>
        </div>
        
        <script>
            $(function(){
                var pane= $('#pane_up_ticket_dates'), frm= pane.find('form'),url=frm.attr('action'), ppad = $('.ui-layout-content');
                var errBox= pane.find('#error_pad'), msgBox = pane.find('.msg-info');
                if(!oDateLoaded){
                    pane.find('button[name="btn_save"]').attr("disabled",true);
                }
                frm.find('button').on('click',function(){
                    var btn=$(this), btnName=btn.attr('name');
                    if(btnName=='btn_reset'){
                        oDateLoaded = false;
                        frm.find('input').val(''); errBox.html('');
                        return false;
                    }
                    if(btnName === 'btn_save' && !oDateLoaded){
                        var msg="请首先查询,然后修改保存!";
                        errBox.html(msg);
                        alert(msg);
                        return false;
                    }
                    msgBox.html('请稍等......');
                    var ps = frm.serialize() + "&" + btnName + "=";
                    $.ajax({url: url,data: ps,type: 'post', dataType:'html'}).done(function(rep,textStatus,jqXHR){
                        ppad.html(rep);
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        ppad.html(jqXHR.responseText);
                    });
              //.always(hbusy);
                    return false;
                });
            });
        </script>
    </div>

    二、插入到管理菜单组,实现功能界面动态装载到iTop界面的右侧工作区域。

    1,实现MyWebPageMenuNode

    想要添加自己定义的菜单,就要用到iTop的应用菜单类ApplicationMenu,这个类的实现位于itop/application/menunode.class.inc.php

    首先找到WebPageMenuNode这个类,由于需要实现ajax动态装载,我们不能直接使用这个类,复制一份本类的源码,改名为MyWebPageMenuNode,对其GetHyperlink方法稍作修改

    class MyWebPageMenuNode extends MenuNode
    {
        protected $sHyperlink;
        
        /**
         * Create a menu item that points to any web page (not only UI.php)
         * @param string $sMenuId Unique identifier of the menu (used to identify the menu for bookmarking, and for getting the labels from the dictionary)
         * @param string $sHyperlink URL to the page to load. Use relative URL if you want to keep the application portable !
         * @param integer $iParentIndex ID of the parent menu
         * @param float $fRank Number used to order the list, any number will do, but for a given level (i.e same parent) all menus are sorted based on this value
         * @param string $sEnableClass Name of class of object
         * @param integer $iActionCode Either UR_ACTION_READ, UR_ACTION_MODIFY, UR_ACTION_DELETE, UR_ACTION_BULKREAD, UR_ACTION_BULKMODIFY or UR_ACTION_BULKDELETE
         * @param integer $iAllowedResults Expected "rights" for the action: either UR_ALLOWED_YES, UR_ALLOWED_NO, UR_ALLOWED_DEPENDS or a mix of them...
         * @return MenuNode
         */
        public function __construct($sMenuId, $sHyperlink, $iParentIndex, $fRank = 0, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
        {
            parent::__construct($sMenuId, $iParentIndex, $fRank, $sEnableClass, $iActionCode, $iAllowedResults, $sEnableStimulus);
            $this->sHyperlink = $sHyperlink;
            $this->aReflectionProperties['url'] = $sHyperlink;
        }
    
        public function GetHyperlink($aExtraParams)
        {
            $aExtraParams['c[menu]'] = $this->GetMenuId();
               //return $this->AddParams( $this->sHyperlink, $aExtraParams);
            $link=$this->AddParams( $this->sHyperlink, $aExtraParams);
           return "javascript:openMyPages('$link')";
        }
        
        public function RenderContent(WebPage $oPage, $aExtraParams = array())
        {
            assert(false); // Shall never be called, the external web page will handle the display by itself
        }
    }

    2,修改ApplicationMenu类,添加自定义方法

    /**
         * ----------------------------------------------------------------------------------------------------------------------------
         * ----        定制菜单
         * ----------------------------------------------------------------------------------------------------------------------------
         */
        static public function AddMyMenu($oPage){
            //public function __construct($sMenuId, $sHyperlink, $iParentIndex, $fRank = 0, $sEnableClass = null, $iActionCode = null, $iAllowedResults = UR_ALLOWED_YES, $sEnableStimulus = null)
            //AdminTools
            $link="../yh/up_ticket_dates.php";
            //$link= "../pages/UI.php?c[menu]=UpTicketDates:Modify";
            $mi = new MyWebPageMenuNode('UpTicketDates',$link,0);
            self::InsertMenu($mi,1,20);
            $oPage->add_ready_script('window.openMyPages=function(link){$(".ui-layout-content").load(link);};');
        }

    在这个方法中,实现了两个功能,创建一个新的菜单项, 然后在页面中注册了点击菜单时需要用到的js函数(注意:js函数名称和上面自定义类中的名称呼应)。

    3,修改DisplayMenu方法,调用上面的自定义方法:

    static public function DisplayMenu($oPage, $aExtraParams)
        {
            self::LoadAdditionalMenus();        
            // Sort the root menu based on the rank
            usort(self::$aRootMenus, array('ApplicationMenu', 'CompareOnRank'));
            // 添加自定义菜单
            self::AddMyMenu($oPage);
            //
            $iAccordion = 0;
            $iActiveMenu = self::GetMenuIndexById(self::GetActiveNodeId());
            foreach(self::$aRootMenus as $aMenu)
            {
                $oMenuNode = self::GetMenuNode($aMenu['index']);
                if (!$oMenuNode->IsEnabled()) continue; // Don't display a non-enabled menu
                $oPage->AddToMenu('<h3>'.$oMenuNode->GetTitle().'</h3>');
                $oPage->AddToMenu('<div>');
                $aChildren = self::GetChildren($aMenu['index']);
                if (count($aChildren) > 0)
                {
                    $oPage->AddToMenu('<ul>');
                    $bActive = self::DisplaySubMenu($oPage, $aChildren, $aExtraParams, $iActiveMenu);
                    $oPage->AddToMenu('</ul>');
                    if ($bActive)
                    {
                        //$oPage->add_ready_script("$('#accordion').accordion('activate', $iAccordion);");
                        // $oPage->add_ready_script("$('#accordion').accordion('option', {collapsible: true});"); // Make it auto-collapsible once it has been opened properly
                        $oPage->add_ready_script("$('#accordion').accordion('option', {collapsible: true, active: $iAccordion});"); // Make it auto-collapsible once it has been opened properly
                    }
                }
                $oPage->AddToMenu('</div>');
                $iAccordion++;
            }
        }
  • 相关阅读:
    HDU 1863 畅通project (最小生成树是否存在)
    经常使用MD5算法代码
    HDU 5045(Contest-费用流)[template:费用流]
    【c语言】统计一个数二进制中的1的个数
    git
    如何在阿里云服务器里配置iis 搭建web服务
    war包放入tomcat
    互联网推送服务原理:长连接+心跳机制(MQTT协议)
    保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护 3
    保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护 2
  • 原文地址:https://www.cnblogs.com/dajianshi/p/13410113.html
Copyright © 2011-2022 走看看