Menu

Create a background task so you can send email notifications automatically

barakbar
2021-04-30
2021-07-12
  • barakbar

    barakbar - 2021-04-30

    Hello, everyone

    I have been trying to make a background task for email notifications continuously so that the user who has ticket and has resolved it can immediately close the ticket, but when the background task is running nothing happens. Here's the code that I created, please correct it if something goes wrong.

    <?php
    
    class TriggerAutoNotif extends TriggerOnObject
    {
        public static function init()
        {
            $aParams = array
            (
                "category" => "core/cmdb,application,grant_by_profile",
                "key_type" => "autoincrement",
                "name_attcode" => "description",
                "state_attcode" => "",
                "reconc_keys" => array('description'),
                "db_table" => "priv_trigger_onautonotif",
                "db_key_field" => "id",
                "db_finalclass_field" => "",
                "display_template" => "",
            );
            MetaModel::Init_Params($aParams);
            MetaModel::Init_InheritAttributes();
                MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('state'))));
    
                //Display List
                MetaModel::Init_SetZListItems('details', array('description','target_class', 'filter','state','action_list'));
                MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description'));
                // Pencarian
                MetaModel::Init_SetZListItems('standard_search', array('target_class','description'));
        }
    }
    
    class AutoNotifikasi implements iBackgroundProcess
    {
        public function GetPeriodicity()
        {
            return 2; //dalam detik
        }
        public function Process($iTimeLimit)
        {
            echo "Memulai Proses............."."\n";
            CMDBObject::SetTrackInfo('Otomatis - Mengirim Notifikasi');
    
            $aReport = array();
            $queryTriggerr = "SELECT TriggerAutoNotif";
            $oSearch = DBObjectSearch::FromOQL($queryTriggerr);
            $oSet = new CMDBObjectSet($oSearch, array(), array());
    
            while($oTrigger = $oSet->Fetch())
            {
                $sClass = $oTrigger->Get('target_class');
                $oState = $oTrigger->Get('state');
                $action_list = $oTrigger->Get('action_list');
    
                if (MetaModel::IsValidClass($sClass)){
                        $queryAutoNotif = "SELECT '$sClass' WHERE status '$oState' = current_status()";
    
                        $oSearchToNotify = DBObjectSearch::FromOQL($queryAutoNotif);
                        $oSetToNotify = new CMDBObjectSet($oSearchToNotify, array(), array());
    
                        while($oItem = $oSetToNotify->Fetch())
                        {
                            $sFilter = trim ($oTrigger->Get('filter'));
                            if (strlen($sFilter) > 0)
                            {
                                $oSearch = DBObjectSearch::FromOQL($sFilter);
                                $oSearch -> AddCondition('id', $oItem->GetKey(), '=');
                                $oSet = new DBObjectSearch($oSearch);
                                $bRet = ($oSet->Count() > 0);
                            }else{
                                $bRet = true;
                            }
                            if($bRet){
                                echo $oItem->Get('name')."respect filter"."\n";
    
                                $oLinkedActions = $oTrigger->Get('action_list');
                                while ($oLink = $oLinkedActions->Fetch())
                                {
                                    $iActionId = $oLink->Get('action_id');
                                    $oAction = MetaModel::GetObject('Action',$iActionId);
    
                                    $oSearchEvent = DBObjectSearch::FromOQL('SELECT EventNotificationEmail');
                                    $oSearchEvent->AddCondition('action_id', $iActionId, '=');
                                    $oSearchEvent->AddCondition('object_id', $oItem->GetKey(), '=');
                                    $oSetEvent = new DBObjectSet($oSearchEvent);
    
                                    if ($oAction->IsActive() && $oSetEvent->Count() == 0)
                                    {
                                        $oAction->DoExecute($oTrigger,$oItem->ToArgs('this'));
                                        $aReport[] = "Send Notifikasi for ".$oItem->Get('name');
    
                                    }else{
                                        //echo "Notification ".$oAction->Get('name')." already send for ".$oItem->Get('name');
                                    }
                                }
                        }else{
                            //echo $oItem->Get('name')." don't respect fitler"."\n";
                        }
                    }
                }else{
                    echo $class." is not a valide class for trigger TriggerOnDurationChange"."\n";
            }
        }
        if (count($aReport)==0){
            return "No Notification to Process";
            echo "No Notification to Process"."\n";
        }
        else{
            return "Some Notification were notify on duration \n ".implode("\n", $aStringReport);
            echo "Some Notification were notify on duration \n ".implode("\n", $aStringReport);
            }
        }
    }
    ?>          
    

    thanks, akbar

     
  • Jeffrey Bostoen

    Jeffrey Bostoen - 2021-04-30

    Just wondering: is there a limitation in the use of the default notifications combined with a trigger "on state change"?

     
  • barakbar

    barakbar - 2021-05-03

    Hii, Jeffrey

    Yes, I am using a state of change but I don't really understand, can you please tell me where is the syntax error in my code? and whether in a certain state "resolve" I can create a background task so I can send emails continuously?

    Thanks :)

     
  • barakbar

    barakbar - 2021-05-03

    I have also created a notification trigger and the action but nothing happened.

     

    Last edit: barakbar 2021-05-03
  • barakbar

    barakbar - 2021-06-08

    Hello, can anyone help me?

     
  • Pierre Goiffon

    Pierre Goiffon - 2021-06-08

    Hello,
    In AutoNotifikasi you can replace echo function by IssueLog methods. Check the cron.php output (use verbose mode if needed) and iTop log.

     
  • barakbar

    barakbar - 2021-06-09

    Hello,
    For more details like this,
    So I plan to create an extension, where the extension that I will create will work and run in the Background. I want to make an extension where when the user creates a ticket and the ticket has resolved and the user does not close the ticket, an email notification will appear continuously until the user closes the ticket,

    I've tried the following:
    1. I created the following syntax, to create a process background

    <?php
    class AutoNotif implements iBackgroundProcess
    {
        public function GetPeriodicity()
        {   
            return 3; // Once a day
        }
        public function Process($iTimeLimit)
        {
            $aReport = array();
                $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnState"));
                while ($oNotify = $oSet->Fetch())
                {
                    $oNotify->Get('state');
                    $aReport[] = 'Notifikasi sudah terkirim #'.$oNotify->GetKey();
                }
                    if (count($aReport) == 0)
                    {
                        return "tidak ada ticket yang resolved";
                    }
                    else
                    {
                        return implode('; ', $aReport);
                    }
        }
    }
    
    1. I created the following syntax to create a custom trigger:
    class TriggerOnState extends TriggerOnStateChange
    {
        public static function Init()
        {
            $aParams = array
            (
                "category" => "grant_by_profile,core/cmdb,application",
                "key_type" => "autoincrement",
                "name_attcode" => "description",
                "state_attcode" => "",
                "reconc_keys" => array('description'),
                "db_table" => "priv_trigger_onstate",
                "db_key_field" => "id",
                "db_finalclass_field" => "",
                "display_template" => "",
            );
            MetaModel::Init_Params($aParams);
            MetaModel::Init_InheritAttributes();
    
            //Display List
            MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
            MetaModel::Init_SetZListItems('list', array('target_class', 'state')); // Attributes to be displayed for a list
    
            //Search criteria
            MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
        }
    }
    

    but the error "Error: Unknown attribute state from class TriggerOnState appears." looks like this problem because I haven't defined the state atribute,

    My question is:
    1. How do I connect the background process with a trigger/action so that notifications can be sent automatically and continuously?
    2. How do Notifications work on iTop?

     
  • barakbar

    barakbar - 2021-06-09

    additional question:
    1. can the trigger be run manually? if so, how can i run the trigger manually, without creating a ticket first?

     

    Last edit: barakbar 2021-06-09
  • Pierre Goiffon

    Pierre Goiffon - 2021-06-10

    Hello,

    You want to send a mail each day, so triggers won't do the job as they are launched during the CRUD stack

    You'll have to do a background process then.

    You can launch your iBackgroundProcess impl manually by running the cron.php manually. Enable verbose mode, add some logs in your code...

     
  • barakbar

    barakbar - 2021-06-11

    Hii, Pierre

    I have tried to understand what you are saying, what I understand is the following:
    1. I use Crud DBObject::AfterInsert To Trigger Notifications,
    2. I get an error like this:
    PHP Fatal error: Uncaught Error: Call to protected method DBObject::AfterInsert() from context

    1. I know, maybe it's an error because I didn't add the "protected function AfterInsert()" syntax, I want to ask, where do I put the syntax? Because I've tried several lines, the error still occurs?

    this is my code :

    <?php
    
    class AutoNotif implements iBackgroundProcess
    {
        public function GetPeriodicity()
        {
            return 3; //per detik
        }
    
        public function Process($iTimeLimit)
        {
            $aReport = array();
                $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter"));
                while ((time() < $iTimeLimit) && $oNotify = $oSet->Fetch())
                {
                        $oNotify->AfterInsert();
    
                        $sClass = get_class($oNotify);
                        $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
                        $oSetTrigger = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList')"));
                        while ($oTrigger = $oSetTrigger->Fetch())
                        {
                            $oTrigger->DoActivate($oNotify->ToArgs('this'));
                        }
                        return $oNotify->m_iKey;    
                }
        }
    }   
    
    ?>
    

    Thanks

     
  • Pierre Goiffon

    Pierre Goiffon - 2021-06-15

    Hello,

    You are doing a mix of Trigger and BackgroundProcess, I don't understand why you chose this path and I don't think this is a good idea.

    Just create a BackgroundProcess that will :

    • get all objects you want to notify using an OQL query
    • for each object, send an email (with pure PHP code, no trigger involved)

    If you want your custom notification email to be configurable in the admin console, then you should create a new iTop object, a menu entry to show them, and use those objects in your BackgroundProcess code.

     

    Last edit: Pierre Goiffon 2021-06-18
  • barakbar

    barakbar - 2021-06-17

    Hii, Pierre

    Thank you for helping me :)
    1. what is your suggestion for OQL Query so that notifications can be triggered by background tasks or Do you have documentation for me, so I can study it?
    2. https://www.itophub.io/wiki/page?id=2_7_0%3Acustomization%3Aapi%3Aobjects-manipulation%3Adbobject#dbobject what function can be used to call/trigger notification?

    Thanks,
    Kind Regards

     

    Last edit: barakbar 2021-06-17
  • Pierre Goiffon

    Pierre Goiffon - 2021-06-18

    Hello,
    I'm confused about your answer
    As said before, just forget about notifications, triggers and actions

    The background task needs to find all tickets for which a mail needs to be send.
    So if I understand correctly your original message, tickets that are in the resolved state ?
    SELECT Ticket WHERE status = 'resolved'

    Then loop on all objects returned by this query, and for each of them send an email.

     
  • barakbar

    barakbar - 2021-06-21

    Hii Pierre,

    I have tried what you suggested and nothing happens, here is my code:

    <?php
    
    //Membuat Background Task
    
    class AutoNotify implements iBackgroundProcess
    {
    
        public function GetPeriodicity()
        {
            return 30; //setiap detik
        }
    
        public function Process($iTimeLimit)
        {
    
            CMDBObject::SetTrackInfo("Automatic - Notifikasi ketika Ticket Berstatus Resolved tetapi tidak di Close");
    
        $aReport = array();
                $sSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRequest WHERE status = ('resolved')"));
                while ($oToNotify = $sSet->Fetch())
                {
                    $oToNotify->DBUpdate();//I'm confused here? how do I call the notification?
                }
        }
        return implode('; ', $aReport);
    }
    ?>
    

    honestly i'm confused and don't have basic php, i learn from the code i see in source itop then i follow code by code.

    Thanks Pierre, if you can help me, i really appreciate you :)

    Best Regards
    Akbar

     
    • barakbar

      barakbar - 2021-06-24

      Hii,
      does anyone want to give me advice or input about this auto notif?

      Thanks

       
  • barakbar

    barakbar - 2021-06-25

    do you have any suggestions for me, cause i'm stuck and confused,
    Hii Pierre,please advise me on this matter..

     
  • barakbar

    barakbar - 2021-07-05

    hi,,
    I have made this code, but an error like this appears, What do you think?

    this is my code:

    <?php
    
    //Membuat Background Task
    
    class AutoNotify implements iBackgroundProcess
    {
    
        public function GetPeriodicity()
        {
            return 30; //setiap detik
        }
    
        public function Process($iTimeLimit)
        {
    
            CMDBObject::SetTrackInfo("Automatic - Notifikasi ketika Ticket Berstatus Resolved tetapi tidak di Close");
    
        $aReport = array();
                $sSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRequest AS u WHERE u.status = 'resolved'"));
                while ((time() < $iTimeLimit) && $oNotify = $sSet->Fetch())
                {
                    $oNotify->Get('ref');
                    $oClass = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('UserRequest') AND state = 'resolved'"));
                    while ( $oTrigger = $Class->Fetch())
                    {
                        $oTrigger->DoActivate('this');
                    }
    
                }
        }
    }
    

    the error is like this:

    PHP Notice:  Undefined variable: Class in /var/www/html/itop/env-production/auto-notifikasi-duitku/main.auto-notifikasi-duitku.php on line 24
    PHP Fatal error:  Uncaught Error: Call to a member function Fetch() on null in /var/www/html/itop/env-production/auto-notifikasi/main.auto-notifikasi.php:24
    Stack trace:
    #0 /var/www/html/itop/webservices/cron.php(103): AutoNotify->Process()
    #1 /var/www/html/itop/webservices/cron.php(287): RunTask()
    #2 /var/www/html/itop/webservices/cron.php(588): CronExec()
    #3 {main}
      thrown in /var/www/html/itop/env-production/auto-notifikasi-duitku/main.auto-notifikasi-duitku.php on line 24
    <p>iTop: An error occurred, check server error log for more information.</p>
    

    Thankss

     

    Last edit: barakbar 2021-07-05
  • barakbar

    barakbar - 2021-07-06

    Hey,

    after I've been struggling all this time, finally I was able to make the notification appear,....but an error like this appears:

    PHP Fatal error:  Uncaught Symfony\Component\Debug\Exception\FatalThrowableError: Cannot access protected property UserRequest::$m_iKey in /var/www/html/itop/env-production/auto-notifikasi/main.auto-notifikasi.php:31
    Stack trace:
    #0 /var/www/html/itop/webservices/cron.php(103): AutoNotify->Process()
    #1 /var/www/html/itop/webservices/cron.php(287): RunTask()
    #2 /var/www/html/itop/webservices/cron.php(588): CronExec()
    #3 {main}
      thrown in /var/www/html/itop/env-production/auto-notifikasi/main.auto-notifikasi.php on line 31
    <p>iTop: An error occurred, check server error log for more information.</p>
    

    this is my code:

    <?php
    
    //Membuat Background Task
    
    class AutoNotify implements iBackgroundProcess
    {
    
        public function GetPeriodicity()
        {
            return 30; //setiap detik
        }
    
        public function Process($iTimeLimit)
        {
    
            CMDBObject::SetTrackInfo("Automatic - Notifikasi ketika Ticket Berstatus Resolved tetapi tidak di Close");
    
        $aReport = array();
                $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRequest AS u WHERE u.status = ('resolved')"));
                while ((time() < $iTimeLimit) && $oNotify = $oSet->Fetch())
                {
                        $oNotify->Get('ref');
    
                        $sClass = get_class($oNotify);
                        $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
                        $oSetTrigger = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList') AND state ='resolved'"));
                        while ($oTrigger = $oSetTrigger->Fetch())
                        {
                            $oTrigger->DoActivate($oNotify->ToArgs('this'));
                        }
                        return $oNotify->m_iKey;    
                }
        }
    }
    

    where is the error in the above code?

    Thankss,,

     
  • barakbar

    barakbar - 2021-07-06

    it turns out I didn't add this to the following syntax:

    return $oNotify->$m_iKey;
    

    Notifications have appeared but can't send a lot of notifications, for example:
    I have request A and request B, both have resolved status, when the notification keeps popping up on Request A, request B won't get a notification until request A is closed, is it possible to send notifications to Request A and Request B at the same time?

    Thankss

     
  • barakbar

    barakbar - 2021-07-12

    Hiiiii,

    So I can use auto notification, and I want a recently completed ticket not to get a notification for about 3 days, after 3 days a new ticket with a resolved status will get a notification, can it be like that?

    I use this query:

    SELECT UserRequest AS u WHERE u.status = 'resolved' AND u.resolution_date < DATE_SUB(NOW(), INTERVAL 3 DAY)

    Akbar.
    Thankss

     

    Last edit: barakbar 2021-07-12

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.