Système de Triggers


Ajouter son code sur un événement métier

Pour permettre de déclencher du code personnalisé en réaction à un événement Dolibarr (création/modification/suppression d'une société/facture/produit/utilisateur ou autre), Dolibarr propose un mécanisme de triggers métiers. Ce mécanisme vous permet de personnaliser un workflow afin que les événements de gestion Dolibarr soient répercutés dans une autre application par exemple. Rien n'empêche également de l'utiliser pour modifier le comportement de Dolibarr même: par exemple, pour que la validation d'une facture provoque la création d'un contrat automatiquement.

Notez que les Triggers sont une fonctionnalité pour les développeurs qui est limitée aux événements métiers CRUD (Créer | Lire (Read) | Mettre à jour (Update) | Supprimer (Delete)). Il existe une autre fonctionnalité permettant aux développeurs d'injecter du code personnalisé dans une application appelée le Système de Hooks.

Donc, pour ajouter son propre code qui sera déclenché par trigger, la procédure est la suivante:

1) Copier le fichier modèle htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php sous le nom:

  • interface_99_all_Xxx.class.php

ou bien

  • interface_99_modMonModule_Xxx.class.php

Xxx est une chaine de votre choix commençant par une majuscule, 99 est le numéro de priorité du trigger (01 étant le plus prioritaire), MonModule est le nom du module si votre trigger ne doit être activé que si le module MonModule est actif. Si on désire que le trigger soit toujours actif, on mettra all à la place de modMonModule. Il faut laisser ce nouveau fichier dans le même répertoire. Rem: Les valeurs utilisables pour modMonModule sont visibles dans le répertoire htdocs/core/modules. ATTENTION: Tous ces paramètres sont nécessaires pour que le trigger soit détecté! Ex: si vous oubliez le numéro de priorité, le module ne sera pas detecté!

Par exemple, on pourra nommer notre nouveau trigger: htdocs/core/triggers/interface_99_modFacture_Monworkflow.class.php

En créant un fichier nommé comme dans cet exemple, notre nouveau trigger sera déclenché à chaque évènement métier Dolibarr et à condition que le module Facture soit actif.

Note: Avec Dolibarr 3.2+, il est aussi possible de placer les fichiers triggers dans un sous-dossier de module. Ex: si le module réside dans htdocs/mymodule/, alors il est possible de placer les triggers dans htdocs/mymodule/core/triggers/. Mais dans ce cas, le trigger ne sera trouvé que si vous le déclarer dans le fichier descripteur de votre module. Pour cela, ajouter triggers->1 dans le tableau module_parts (ex: /monmodule/core/modules/modMonModule.class.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);

Puis désactiver et réactiver le module. Ceci aura pour effet d'ajouter une ligne dans la Table llx_const pour indiquer à Dolibarr qu'il faut aussi rechercher les triggers dans le répertoire de votre module htdocs/monmodule/core/triggers.


2) Editer ce fichier interface_99_modMonModule_Monworkflow.class.php afin de renommer la classe InterfaceDemo par InterfaceMonworkflow

Ensuite, accéder à la page Accueil-> Infos Systèmes -> Dolibarr -> Triggers. Votre fichier trigger doit apparaitre dans la liste sans erreur indiquant que les opérations précédentes ont été réalisées avec succès.


3) Revenez maintenant à l'édition du fichier trigger afin d'ajouter votre code dans la fonction runTrigger. Cette fonction est appelée à chaque évènement Dolibarr. Placer votre code en fonction du ou des évènements sur lesquels vous voulez réagir, chaque évènement étant identifié par un code (voir chapitres suivant pour la liste des codes), on peut réagir ou non à un évènement donné par un test sur la variable $action:

public function runtrigger($action,$object,$user,$langs,$conf)
{
      // Mettre ici le code à exécuter en réaction de l'action
      // Le type de l'évènement Dolibarr est stocké dans $action
      // Les données de l'action sont stockées dans $object
      // La configuration, utilisateur et langage sont dans $conf,$user et $lang
      if ($action == 'COMPANY_CREATE')
      {
          dol_syslog("Trigger for action '$action' launched. id=".$object->id);
      }
      elseif ($action == 'COMPANY_MODIFY')
      {        
          dol_syslog("Trigger for action '$action' launched. id=".$object->id);
      }
      elseif ($action == 'COMPANY_DELETE')
      ...
}

Vous pouvez faire ce que vous voulez dans cette portion de code du moment que la fonction runTrigger renvoie un code retour sur le principe suivant:

<0 si ko, 0 si aucune action faite, >0 si ok

Vous pouvez de plus dans cette fonction utiliser les objets suivant:

  • $object est l'objet sur lequel porte l'action (voir chapitre suivant)
  • $user est l'objet de l'utilisateur Dolibarr qui réalise l'action
  • $langs est l'objet qui contient la langue de l'utilisateur Dolibarr
  • $conf est l'objet qui contient toute la configuration de Dolibarr.


4) Une fois le code réalisé, il n'y a plus qu'à tester, en provoquant l'évènement déclencheur dans Dolibarr. Attention, l'appel au runTrigger et encapsuler dans un transaction. Si votre trigger renvoie un code ko, la fonction appelante peut annuler la transaction (ceci dépend de la fonction appelante). Ajouter des traces dans un fichier dans la fonction runTrigger afin de vous assurer que le code s'exécute bien. Vous pouvez pour cela si vous le désirer, utiliser la fonction dol_syslog("mon texte de trace", LOG_DEBUG);

Liste des événements gérés

Voici un vue rapide des événements qui provoquent une recherche et exécution de triggers. Un événement est caractérisés par la valeur du code $action, avec le type de l'objet reçu dans $object.

Remarque: Le Module Agenda et le Module Notification Fr utilise la table Table llx c action trigger comme liste de triggers connus. Cela évite de scanner le disque pour avoir cette information mais cette table ne contient qu'une liste très limité des triggers.

En général, le code action de trigger commence par le nom du module suivi du caractère _.

Trigger code ($action) Type object ($object)
USER_CREATE user.class.php
USER_MODIFY user.class.php
USER_DELETE user.class.php
USER_LOGIN user.class.php
USER_LOGIN_FAILED user.class.php
USER_LOGOUT user.class.php
USER_ENABLEDISABLE user.class.php
USER_NEW_PASSWORD user.class.php
USER_SETINGROUP user.class.php
USER_REMOVEFROMGROUP user.class.php
USERGROUP_CREATE (>= 12.0.0) usergroup.class.php
USERGROUP_MODIFY(>= 12.0.0) usergroup.class.php
USERGROUP_DELETE(>= 12.0.0) usergroup.class.php
GROUP_CREATE usergroup.class.php
GROUP_MODIFY usergroup.class.php
GROUP_DELETE (>= 3.3.0) usergroup.class.php
COMPANY_CREATE societe.class.php
COMPANY_MODIFY societe.class.php
COMPANY_DELETE societe.class.php
COMPANY_SENTBYMAIL (>= 3.5.0) societe.class.php
CONTACT_CREATE contact.class.php
CONTACT_MODIFY contact.class.php
CONTACT_DELETE contact.class.php
CONTACT_ENABLEDISABLE (>= 3.5.0) contact.class.php
PRODUCT_CREATE product.class.php
PRODUCT_MODIFY product.class.php
PRODUCT_PRICE_MODIFY product.class.php
PRODUCT_DELETE product.class.php
SUPPLIER_PRODUCT_BUYPRICE_UPDATE fournisseur.product.class.php
SUPPLIER_PRODUCT_BUYPRICE_CREATE fournisseur.product.class.php
ORDER_CREATE commande.class.php
ORDER_VALIDATE commande.class.php
ORDER_SENTBYMAIL commande.class.php
ORDER_DELETE commande.class.php
ORDER_CLASSIFY_BILLED commande.class.php
ORDER_CLONE commande.class.php
ORDER_CLOSE commande.class.php
ORDER_CANCEL commande.class.php
ORDER_REOPEN (>= 3.3.0) commande.class.php
ORDER_UNVALIDATE commande.class.php
COMMANDE_ADD_CONTACT commande.class.php
COMMANDE_DELETE_CONTACT commande.class.php
COMMANDE_DELETE_RESOURCE (>= 3.6.0) commande.class.php
LINEORDER_INSERT commande.class.php
LINEORDER_UPDATE commande.class.php
LINEORDER_DELETE commande.class.php
LINEORDER_DISPATCH (>= 3.4.0) commande.class.php
ORDER_SUPPLIER_CREATE fournisseur.commande.class.php
ORDER_SUPPLIER_CLONE fournisseur.commande.class.php
ORDER_SUPPLIER_VALIDATE fournisseur.commande.class.php
ORDER_SUPPLIER_SENTBYMAIL fournisseur.commande.class.php
ORDER_SUPPLIER_APPROVE fournisseur.commande.class.php
ORDER_SUPPLIER_REFUSE fournisseur.commande.class.php
ORDER_SUPPLIER_CANCEL fournisseur.commande.class.php
ORDER_SUPPLIER_DELETE fournisseur.commande.class.php
ORDER_SUPPLIER_DISPATCH (>= 3.4.0) fournisseur.commande.class.php
ORDER_SUPPLIER_ADD_CONTACT fournisseur.commande.class.php
ORDER_SUPPLIER_DELETE_CONTACT fournisseur.commande.class.php
ORDER_SUPPLIER_DELETE_RESOURCE (>= 3.6.0) fournisseur.commande.class.php
LINEORDER_SUPPLIER_CREATE fournisseur.commande.class.php
LINEORDER_SUPPLIER_UPDATE fournisseur.commande.class.php
LINEORDER_SUPPLIER_DELETE (>= 3.6.0) fournisseur.commande.class.php
PROPAL_CREATE propal.class.php
PROPAL_DELETE propal.class.php
PROPAL_CLONE propal.class.php
PROPAL_REOPEN (>= 3.5.0) propal.class.php
PROPAL_VALIDATE propal.class.php
PROPAL_CLOSE_SIGNED propal.class.php
PROPAL_CLOSE_REFUSED propal.class.php
PROPAL_SENTBYMAIL propal.class.php
PROPAL_MODIFY propal.class.php
PROPAL_ADD_CONTACT propal.class.php
PROPAL_DELETE_CONTACT propal.class.php
PROPAL_DELETE_RESOURCE (>= 3.6.0) propal.class.php
LINEPROPAL_INSERT propal.class.php
LINEPROPAL_UPDATE propal.class.php
LINEPROPAL_DELETE propal.class.php
CONTRACT_CREATE contrat.class.php
CONTRACT_VALIDATE contrat.class.php
CONTRACT_SERVICE_ACTIVATE contrat.class.php
CONTRACT_SERVICE_CLOSE contrat.class.php
CONTRACT_DELETE contrat.class.php
CONTRAT_ADD_CONTACT contrat.class.php
CONTRAT_DELETE_CONTACT contrat.class.php
CONTRAT_DELETE_RESOURCE (>= 3.6.0) contrat.class.php
LINECONTRACT_INSERT contrat.class.php
LINECONTRACT_MODIFY contrat.class.php
LINECONTRACT_DELETE contrat.class.php
BILL_CREATE facture.class.php
BILL_MODIFY facture.class.php
BILL_CLONE facture.class.php
BILL_VALIDATE facture.class.php
BILL_UNVALIDATE (>= 3.4.0) facture.class.php
BILL_PAYED facture.class.php
BILL_UNPAYED facture.class.php
BILL_CANCEL facture.class.php
BILL_DELETE facture.class.php
BILL_SENTBYMAIL facture.class.php
FACTURE_ADD_CONTACT facture.class.php
FACTURE_DELETE_CONTACT facture.class.php
FACTURE_DELETE_RESOURCE (>= 3.6.0) facture.class.php
LINEBILL_INSERT facture.class.php
LINEBILL_UPDATE facture.class.php
LINEBILL_DELETE facture.class.php
BILL_SUPPLIER_CREATE fournisseur.facture.class.php
BILL_SUPPLIER_MODIFY fournisseur.facture.class.php
BILL_SUPPLIER_DELETE fournisseur.facture.class.php
BILL_SUPPLIER_VALIDATE fournisseur.facture.class.php
BILL_SUPPLIER_PAYED fournisseur.facture.class.php
BILL_SUPPLIER_UNPAYED fournisseur.facture.class.php
BILL_SUPPLIER_SENTBYMAIL fournisseur.facture.class.php
INVOICE_SUPPLIER_ADD_CONTACT fournisseur.facture.class.php
INVOICE_SUPPLIER_DELETE_CONTACT fournisseur.facture.class.php
INVOICE_SUPPLIER_DELETE_RESOURCE (>= 3.6.0) fournisseur.facture.class.php
LINEBILL_SUPPLIER_CREATE fournisseur.facture.class.php
LINEBILL_SUPPLIER_UPDATE fournisseur.facture.class.php
LINEBILL_SUPPLIER_DELETE (>= 3.4.0) fournisseur.facture.class.php
PAYMENT_CUSTOMER_CREATE paiement.class.php
PAYMENT_DELETE (<= 3.8) paiement.class.php
PAYMENT_CUSTOMER_DELETE (>= 3.9) paiement.class.php
PAYMENT_ADD_TO_BANK paiement.class.php
PAYMENT_SUPPLIER_CREATE paiementfourn.class.php
PAYMENT_SUPPLIER_DELETE (>= 3.9) paiement.class.php
PAYMENT_SALARY_CREATE (>= 3.6.0) paymentsalary.class.php
PAYMENT_SALARY_MODIFY (>= 3.6.0) paymentsalary.class.php
PAYMENT_SALARY_DELETE (>= 3.6.0) paymentsalary.class.php
FICHINTER_CREATE fichinter.class.php
FICHINTER_MODIFY fichinter.class.php
FICHINTER_DELETE fichinter.class.php
FICHINTER_VALIDATE fichinter.class.php
FICHINTER_SENTBYMAIL fichinter.class.php
FICHINTER_ADD_CONTACT fichinter.class.php
FICHINTER_DELETE_CONTACT fichinter.class.php
FICHINTER_DELETE_RESOURCE (>= 3.6.0) fichinter.class.php
LINEFICHINTER_CREATE (>= 3.5.0) fichinter.class.php
LINEFICHINTER_UPDATE (>= 3.5.0) fichinter.class.php
LINEFICHINTER_DELETE (>= 3.5.0) fichinter.class.php
MEMBER_CREATE adherent.class.php
MEMBER_VALIDATE adherent.class.php
MEMBER_SUBSCRIPTION adherent.class.php
MEMBER_MODIFY adherent.class.php
MEMBER_RESILIATE adherent.class.php
MEMBER_NEW_PASSWORD adherent.class.php
MEMBER_DELETE adherent.class.php
CATEGORY_CREATE category.class.php
CATEGORY_MODIFY category.class.php
CATEGORY_DELETE category.class.php
CATEGORY_LINK (>= 3.5.0) category.class.php
CATEGORY_UNLINK (>= 3.5.0) category.class.php
SHIPPING_CREATE expedition.class.php
SHIPPING_VALIDATE expedition.class.php
SHIPPING_MODIFY expedition.class.php
SHIPPING_DELETE expedition.class.php
SHIPPING_SENTBYMAIL expedition.class.php
DELIVERY_VALIDATE livraison.class.php
DELIVERY_DELETE livraison.class.php
ACTION_CREATE actioncomm.class.php
ACTION_MODIFY actioncomm.class.php
ACTION_DELETE actioncomm.class.php
ACTION_ADD_CONTACT actioncomm.class.php
ACTION_DELETE_CONTACT actioncomm.class.php
ACTION_DELETE_RESOURCE (>= 3.6.0) actioncomm.class.php
DEPLACEMENT_CREATE deplacement.class.php
DON_CREATE don.class.php
DON_MODIFY (>= 3.7.0) don.class.php
DON_DELETE (>= 3.7.0) don.class.php
LOCALTAX_CREATE localtax.class.php
LOCALTAX_MODIFY localtax.class.php
LOCALTAX_DELETE localtax.class.php
TVA_CREATE tva.class.php
TVA_MODIFY tva.class.php
TVA_DELETE tva.class.php
TVA_ADDPAYMENT tva.class.php
PROJECT_CREATE project.class.php
PROJECT_MODIFY project.class.php
PROJECT_DELETE project.class.php
PROJECT_VALIDATE project.class.php
PROJECT_CLOSE project.class.php
PROJECT_ADD_CONTACT project.class.php
PROJECT_DELETE_CONTACT project.class.php
PROJECT_DELETE_RESOURCE (>= 3.6.0) project.class.php
TASK_CREATE task.class.php
TASK_MODIFY task.class.php
TASK_DELETE task.class.php
TASK_TIMESPENT_CREATE task.class.php
TASK_TIMESPENT_MODIFY task.class.php
TASK_TIMESPENT_DELETE task.class.php
PROJECT_TASK_ADD_CONTACT task.class.php
PROJECT_TASK_DELETE_CONTACT task.class.php
PROJECT_TASK_DELETE_RESOURCE (>= 3.6.0) task.class.php
MYECMDIR_CREATE ecmdirectory.class.php
MYECMDIR_MODIFY ecmdirectory.class.php
MYECMDIR_DELETE ecmdirectory.class.php
STOCK_MOVEMENT mouvementstock.class.php
PAYBOX_PAYMENT_OK
PAYPAL_PAYMENT_OK
LINK_CREATE (>= 3.5.0) link.class.php
LINK_MODIFY (>= 3.5.0) link.class.php
LINK_DELETE (>= 3.5.0) link.class.php
OPENSURVEY_CREATE (>= 3.6.0) opensurveysondage.class.php
OPENSURVEY_DELETE (>= 3.6.0) opensurveysondage.class.php

Liste non exhaustive.

Créer de nouveaux événements Triggers

Pour gérer d'autres événements que ceux ci-dessus, il faut modifier le code Dolibarr pour y ajouter la séquence suivante dans les méthodes métiers des classes des objects manipulés:

// Call trigger
$result=$this->call_trigger('CODE_TRIGGER',$user);
if ($result < 0) $error++;          
// End call triggers

Pour ajouter des informations de context (par exemple pour dissocier 2 cas différents appelés avec le même code Trigger), il est possible de placer ces informations dans la propriétés ->context de l'object sur lequel porte l'appel du trigger. Exemple:

// Call trigger
$this->context = array('paramX'=>$valueX, 'anyparamofyourchoice'=>$anyvalue);
$result=$this->call_trigger('CODE_TRIGGER',$user);
if ($result < 0) $error++;          
// End call triggers


Il sera alors possible d'ajouter dans la méthode runTrigger de tout fichier trigger, un if qui permet de gérer ce code. La méthode runTrigger serait alors de la forme :

function run_trigger($action,$object,$user,$lang,$conf)
{
      // Mettre ici le code à exécuter en réaction de l'action
      // Le type de l'évènement Dolibarr est stocké dans $action
      // Les données de l'action sont stockées dans $object
      // La configuration, utilisateur et langage sont dans $conf,$user et $lang
      if ($action == 'XXXXX_YYYYY')
      {
          dol_syslog("Trigger for action '$action' launched. id=".$object->id);
      }
      elseif ($action == 'COMPANY_CREATE')
      {
          dol_syslog("Trigger for action '$action' launched. id=".$object->id);
      }
      elseif ($action == 'COMPANY_MODIFY')
      {        
          dol_syslog("Trigger for action '$action' launched. id=".$object->id);
      }
      elseif ($action == 'COMPANY_DELETE')
      ...
}

Conclusion

Vous pouvez donc en quelques minutes, ajouter une interface Dolibarr vers exterieur sans risque puisqu'on ne touche pas au code Dolibarr, on s'est contenté de placer un nouveau fichier trigger dans le répertoire des triggers. Si cette interface peut être utile à d'autre, n'hésitez pas à la packager en tgz (voir la page Développement_module#Créer_un_package_pour_livrer_et_installer_votre_module) et de la soumettre dans l'espace des téléchargement-contributions sur le site de Dolibarr.

Voir aussi