Changes

m
Line 1: Line 1:  +
<!-- BEGIN origin interlang links -->
 +
<!-- You can edit this section but do NOT remove these comments
 +
    Links below will be automatically replicated on translated pages by PolyglotBot -->
 +
[[fr:Système de Triggers]]
 +
[[es:Triggers-acciones]]
 +
[[zh:触发系统]]
 +
<!-- END interlang links -->
 +
 
{{TemplateDocDevEn}}
 
{{TemplateDocDevEn}}
   −
= Execute your own code on a Dolibarr's action =
+
=Execute your own code on a Dolibarr business event=
 
To execute personalized code after a Dolibarr event (create/modify/remove a third party/invoice/product or other), Dolibarr offers a mechanism of business triggers. This mechanism allows you to personalize a work-flow to have Dolibarr business events being synchronized into another application for example.
 
To execute personalized code after a Dolibarr event (create/modify/remove a third party/invoice/product or other), Dolibarr offers a mechanism of business triggers. This mechanism allows you to personalize a work-flow to have Dolibarr business events being synchronized into another application for example.
You can also use triggers to modify the behavior of Dolibarr itself: for example, to create automatically a contract when an invoice is validated.
+
You can also use triggers to modify the behavior of Dolibarr itself: for example, to create a contract automatically when an invoice is validated, a fill a log file when a record is deleted, ...
 +
 
 +
Note that triggers is a feature for developers that is limited to:
 +
* business CRUD events (Create | Read | Update | Delete).
 +
* change of the primary status of objects
 +
There is another feature for developers to inject custom code in the application called the [[Hooks system]]. Note, for historic reason, when you send an email, this generates also a trigger call even if this case is not among the 2 allowed.
   −
So, to add your own code that will be triggered by a Dolibarr trigger, this is the way to process:
      +
So, to add your own code that will be triggered by a Dolibarr trigger, this is the process:
   −
1) (only for Dolibarr >= v3.2.0) in your module descriptor file (eg: '''/mymodule/core/modules/modMyModule.class.php'''), add triggers->1 into module_parts array:
+
1) Copy the template trigger file '''htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php''' under the new name:
<source lang="php">
  −
// Defined all module parts (triggers, login, substitutions, menus, etc...) (0=disable,1=enable)
  −
$this->module_parts = array('triggers' => 1);
  −
//$this->module_parts = array('triggers' => 1,
  −
//              'login' => 0,
  −
//              'substitutions' => 0,
  −
//              'menus' => 0);
  −
</source>
  −
Then disable and reenable your module. This will add a record into table llx_const to say Dolibarr a trigger file must be searched into module directory '''/mymodule/core/triggers/'''
      +
*'''interface_99_all_''Xxx''.class.php'''
   −
2) Copy the trigger file '''htdocs/includes/triggers/interface_all_Demo.class.php''' under the new name:
  −
* '''interface_all_''Xxx''.class.php'''
   
or
 
or
* '''interface_mod''MyModule_Xxx''.class.php'''
+
 
where ''Xxx'' is a string of your choice startint with uppercase character and ''MyModule'' is the name of a module if you want that trigger is activated only if module MyModyle is activated. If you want the trigger to be always active, use ''all'' instead of  modMyModule.
+
*'''interface_99_mod''MyModule_Xxx''.class.php'''
 +
 
 +
where ''Xxx'' is a string of your choice starting with uppercase character, ''99'' is the priority number for the execution of your trigger (1 being the top priority) and ''MyModule'' is the name of a module if you want that trigger is activated only if module MyModule is activated. If you want the trigger to be always active, use ''all'' instead of  modMyModule.
 
This new file must be saved inside same directory.
 
This new file must be saved inside same directory.
 +
 
Note: Value you can use for modMyModule are values found in directory
 
Note: Value you can use for modMyModule are values found in directory
''htdocs/includes/modules''.
+
''htdocs/core/modules''.
 +
 
 +
'''WARNING''': All those parameters are necessary for the trigger to be detected and executed! Eg: if you forget the priority number, your trigger won't be detected!
    
For example, you can name your new trigger file:  
 
For example, you can name your new trigger file:  
''htdocs/includes/triggers/interface_modFacture_Myworkflow.class.php''
+
''htdocs/core/triggers/interface_99_modFacture_Myworkflow.class.php''
   −
By creating such a file with name as in the example, your new trigger file will be executed each time a Dolibarr business event occurs but only if the module Facture is enabled.
+
By creating such a file with a name like the example, your new trigger file will be executed each time a Dolibarr business event occurs but only if the module Facture is enabled.
 
  −
'''Note''': starting from Dolibarr v3.2.x, you have to place triggers inside the '''core/''' folder instead of includes/ (eg: htdocs/core/triggers/interface_modMyModule_Xxx.class.php).
  −
 
  −
'''Note2''': You can also place the triggers in your own module's subdirectly. Eg: if your module resides in htdocs/mymodule/, then you can place your triggers inside htdocs/mymodule/core/triggers/
      +
'''Note''': If you develop a full module, you can also place the trigger file in your own module's sub-directory. Eg: if your module resides in htdocs/mymodule/, then you can place your triggers inside htdocs/mymodule/core/triggers/. But for this, you must declare the trigger into your module descriptor file (eg: '''/mymodule/core/modules/modMyModule.class.php'''). For this, add into this file triggers->1 into module_parts array:
 +
<syntaxhighlight lang="php">
 +
// Defined all module parts (triggers, login, substitutions, menus, etc...) (0=disable,1=enable)
 +
$this->module_parts = array('triggers' => 1);
 +
//$this->module_parts = array('triggers' => 1,
 +
//              'login' => 0,
 +
//              'substitutions' => 0,
 +
//              'menus' => 0);
 +
</syntaxhighlight>
 +
Then disable and reenable your module. This will add a record into [[Table llx_const]] to tell Dolibarr that a trigger file must be searched in the module directory '''htdocs/mymodule/core/triggers/'''
   −
3) Edit the file ''interface_modMyModule_Myworkflow.class.php'' to rename class ''InterfaceDemo'' by ''InterfaceMyworkflow''
      +
2) Edit the file ''interface_99_modFacture_Myworkflow.class.php'' to modify its content by changing the class ''InterfaceMyModuleTriggers'' by ''InterfaceMyworkflow:''
   −
Then go on page Home-> System Infos -> Dolibarr -> Triggers.
+
Then go on page Home -> Admin Tools -> About Dolibarr ->Triggers.
 
Your new trigger file must appears in the list without any error message. This means preceding actions have been done successfully.
 
Your new trigger file must appears in the list without any error message. This means preceding actions have been done successfully.
      −
4) Return now to edition of file to add your own code inside function  ''run_trigger''.
+
3) Return now to edition of file to add your own code inside function  ''run_trigger''.
 
This function is called at each Dolibarr business event. Put your code according to events on which you want to run. Each event is identified by a code (see following chapter to get full list of codes). So you can react or no after an event by doing just a test on variable '''$action''':
 
This function is called at each Dolibarr business event. Put your code according to events on which you want to run. Each event is identified by a code (see following chapter to get full list of codes). So you can react or no after an event by doing just a test on variable '''$action''':
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
   function run_trigger($action,$object,$user,$langs,$conf)
 
   function run_trigger($action,$object,$user,$langs,$conf)
 
   {
 
   {
Line 67: Line 81:  
         ...
 
         ...
 
   }
 
   }
</source>
+
</syntaxhighlight>
    
You can do what you want into this coding part, if you check that function run_trigger returns a return code according to following rule:
 
You can do what you want into this coding part, if you check that function run_trigger returns a return code according to following rule:
Line 74: Line 88:     
You can also use, inside this function, the following preinitialized variables:
 
You can also use, inside this function, the following preinitialized variables:
* '''$object''' is the object on which action is done (see next chapter)
  −
* '''$user''' is the object containing all information of Dolibarr user that realizes the business event.
  −
* '''$langs''' is the object that contains the user language and translations strings
  −
* '''$conf''' is the object that contains all the Dolibarr configuration.
     −
5) Once your trigger file has been developed, last action is to test by using Dolibarr to execute the business event that should trigger your code. Warning, call of function '''run_trigger''' is encapsulated into a transaction. If your code return a KO code, the calling function may rollback the transaction (this depends on calling function).
+
*'''$object''' is the object on which action is done (see next chapter)
 +
*'''$user''' is the object containing all information of Dolibarr user that realizes the business event.
 +
*'''$langs''' is the object that contains the user language and translations strings
 +
*'''$conf''' is the object that contains all the Dolibarr configuration.
 +
 
 +
 
 +
4) Once your trigger file has been developed, last action is to test by using Dolibarr to execute the business event that should trigger your code. Warning, call of function '''run_trigger''' is encapsulated into a transaction. If your code return a KO code, the calling function may rollback the transaction (this depends on calling function).
 
Add log information inside your function '''run_trigger''' to know if your code is correctly triggered and runs correctly. For this, you can use the function
 
Add log information inside your function '''run_trigger''' to know if your code is correctly triggered and runs correctly. For this, you can use the function
 
dol_syslog("my log message", LOG_DEBUG);
 
dol_syslog("my log message", LOG_DEBUG);
   −
= List of known triggers actions =
+
=List of known triggers actions=
List of all events that launch triggers are available in [[Table llx c action trigger]]. This is a quick list of those events, identified by value of variable '''$action''' into trigger code and type of variable $object for each code:
+
 
 +
Here is a quick view of the events that cause triggers to be searched and executed. An event is characterized by the value of the code ''$action'', with the type of the object received in ''$object''.
 +
 
 +
Note: The [[Module Agenda En|Module Agenda]] and [[Module Notification]] use the table [[Table llx c action trigger]] as a list of known triggers. This avoid scanning the disk for this information, but this table is just a very limited list.
 +
 
 +
In general, the trigger action code begins with the name of the module followed by the character _.
    
{{TemplateListOfTriggers}}
 
{{TemplateListOfTriggers}}
 
This list may be not complete.
 
This list may be not complete.
   −
= Manage and create a new trigger's action =
+
=Manage and create a new trigger's action=
 +
 
 +
To manage events other than those above, you must modify the Dolibarr code to add the following sequence in the business methods of the classes of the objects handled:
 +
 
 +
<syntaxhighlight lang="php">
 +
// Call trigger
 +
$result = $this->call_trigger('CODE_TRIGGER', $user);
 +
if ($result <0) $error++;
 +
// End call triggers
 +
</syntaxhighlight>
   −
To manage other events on objects than the one defined before, you mist edit the Dolibarr code to add the following code inside the business method of the class file of the object:
+
To add context information (for example to dissociate 2 different cases called with the same Trigger code), it is possible to place this information in the properties ->context of the object on which the trigger is called. Example:
   −
<source lang="php">
+
<syntaxhighlight lang="php">
// Call triggers
+
// Call trigger
include_once(DOL_DOCUMENT_ROOT . "/interfaces.class.php");
+
$this->context = array('paramX'=>$valueX, 'anyparamofyourchoice'=>$anyvalue);
$interface=new Interfaces($this->db);
+
$result = $this->call_trigger('CODE_TRIGGER',$user);
$result=$interface->run_triggers('XXXXX_YYYYY',$this,$user,$langs,$conf);
+
if ($result < 0) $error++;        
if ($result < 0) { $error++; $this->errors=$interface->errors; }
   
// End call triggers
 
// End call triggers
</source>
+
</syntaxhighlight>
   −
Here, '''$this''' contains the business class with all information to send to the trigger functions. Replace 'XXXXX_YYYYY' by an event code not already used.
+
It will then be possible to add in the run_trigger method of any trigger file, an if which allows you to manage this code. The run_trigger method would then be of the form:
Then you will be able to add inside the run_trigger method, a "if" to manage this code. The run_trigger method will contains a part of code like this :
     −
<source lang="php">
+
<syntaxhighlight lang="php">
 
function run_trigger($action,$object,$user,$lang,$conf)
 
function run_trigger($action,$object,$user,$lang,$conf)
 
{
 
{
Line 112: Line 140:  
       // Data of action are stored into object $object
 
       // Data of action are stored into object $object
 
       // Setup, user and language are saved into $conf, $user and $lang
 
       // Setup, user and language are saved into $conf, $user and $lang
      <b>
   
       if ($action == 'XXXXX_YYYYY')
 
       if ($action == 'XXXXX_YYYYY')
 
       {
 
       {
 
           dol_syslog("Trigger for action '$action' launched. id=".$object->id);
 
           dol_syslog("Trigger for action '$action' launched. id=".$object->id);
 
       }
 
       }
      </b>
   
       elseif ($action == 'COMPANY_CREATE')
 
       elseif ($action == 'COMPANY_CREATE')
 
       {
 
       {
Line 129: Line 155:  
       ...
 
       ...
 
}
 
}
</source>
+
</syntaxhighlight>
 +
 
 +
'''Please note the following before adding additional calls to triggers:'''
 +
 
 +
The rule is to have only 1 trigger call per business CRUD event, even when several actions are done in the same transaction.
 +
As an example: When a new ticket is created with an already assigned user, only the TICKET_CREATE trigger is called, not additionally the TICKET_ASSIGNED trigger. It is the job of the trigger to intercept also this case to scan if an assignment is done directly during creation and to execute its custom code.
 +
 
   −
= Conclusion =
+
=Conclusion=
 
You can in few minutes, add an interface from Dolibarr towards another system (or why not towards Dolibarr itself), with no risk since you don't touch anything to Dolibarr files. You only "added" a new trigger file inside the trigger directory.
 
You can in few minutes, add an interface from Dolibarr towards another system (or why not towards Dolibarr itself), with no risk since you don't touch anything to Dolibarr files. You only "added" a new trigger file inside the trigger directory.
 
If this new interface can serve a lot of other users, you can package it into a tgz file (see page [[Module_development#Create_a_package_to_distribute_and_install_your_module]]) and submit it on the download area in section external contributions on official Dolibarr web site.
 
If this new interface can serve a lot of other users, you can package it into a tgz file (see page [[Module_development#Create_a_package_to_distribute_and_install_your_module]]) and submit it on the download area in section external contributions on official Dolibarr web site.
   −
= See also =
+
=See also=
* [[Hooks system]]
+
 
* [[Interfaces Dolibarr toward foreign systems]]
+
*[[Hooks system]]
* [[Interfaces from foreign systems toward Dolibarr]]
+
*[[Interfaces Dolibarr toward foreign systems]]
 +
*[[Interfaces from foreign systems toward Dolibarr]]