SuiteCRM : ajouter du JavaScript global

Dans SuiteCRM, on peut avoir besoin d’ajouter du JavaScript de manière globale. Dans mon cas, je souhaite régulièrement envoyer des actions à une application d’automatisation externe (n8n) pour accomplir des tâches variées pour mes clients.

Par exemple :

  • Création de commandes dans Woo ;
  • Mise à jour de factures ;
  • Envoi de vCard par e-mail ;
  • Génération de fichiers Excel ou PDF formatés ;
  • Exportation de données dans n’importe quel format ;

Je veux donc que ma fonction JavaScript tmcWebhook() soit disponible sur l’ensemble de l’application, en utilisant au mieux la logique de SuiteCRM. Le bénéfice est que mon intégration reste stable lors des mises à jour. Cette approche garantit également que les contrôles sur les accès aux scripts PHP sont les mêmes que partout ailleurs dans SuiteCRM.

Note : tous les fichiers sont dans le répertoire custom à la racine de l’installation. Ceci permet de ne modifier aucun fichier de base de SuiteCRM, et de rester stable après des mises à jour.

Cette approche fonctionne sur SuiteCRM 7.x — je ne l’ai pas encore testée sur SuiteCRM 8.x, alors que la migration en production devra se faire probablement d’ici la fin 2024.

Définir un Logic Hook pour charger la fonction JavaScript

D’abord, il faut ajouter un hook dans

custom/modules/logic_hooks.php
$hook_array['after_ui_frame'][] = array(
  1,
  'Adds TMC JavaScript for Webhook capability',  //Label
  'custom/include/tmcGlobal/tmcGlobal.php', //Include file
  'tmcHooks', //Class
  'load_TMC_JS' //Method
);

Avec les définitions dans

custom/include/tmcGlobal/tmcGlobal.php
<?php

if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

class tmcHooks{

  function load_TMC_JS($event,$arguments){
    global $sugar_config;

      if( (!isset($_REQUEST['sugar_body_only']) || $_REQUEST['sugar_body_only']!=true) && $_REQUEST['action']!='modulelistmenu' && $_REQUEST['action']!='Popup' && empty($_REQUEST['to_pdf']) && ( !empty($_REQUEST['module']) && $_REQUEST['module']!='ModuleBuilder') && empty($_REQUEST['to_csv'])){
        echo '<script type="text/javascript" src="custom/include/tmcGlobal/tmcWebhook.js"></script>';
        }
      }
    }
?>

Enfin, je mets le script que je veux rendre disponible dans :

custom/include/tmcGlobal/tmcWebhook.js
function tmcWebhook(server, user, record, action) {

    // ...
    // your logic here
    // ...

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'index.php?entryPoint=tmcWebhook', true);
    xhr.setRequestHeader('Content-Type', 'application/json');

    // ...
    // your logic here
    // ...
}

Cette fonction JavaScript tmcWebhook() sera maintenant disponible dans chaque module pour appeler l’Entry Point tmcWebhook, et lui passer les données (server, user, record, action). Il faut donc définir cet Entry Point.

Définir l’Entry Point

Définir l’Entry Point tmcWebhook permet de l’appeler depuis la fonction, et de sécuriser son accès. Je le fais en créant le fichier suivant :

custom/Extension/application/Ext/EntryPointRegistry/tmcWebhook.php
<?php

$entry_point_registry['tmcWebhook'] = array(
    'file' => 'custom/include/tmcGlobal/tmcWebhook.php',
    'auth' => true,
);

Je crée pour finir le fichier tmcWebhook.php qui reçoit les demandes :

custom/include/tmcGlobal/tmcWebhook.php
<?php

if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

// getting raw post data

$rawPostData = file_get_contents("php://input");
$postData = json_decode($rawPostData, true);

// Get POST variables
$server = $postData['server'] ?? '';
$user = $postData['user'] ?? '';
$record = $postData['record'] ?? '';
$action = $postData['action'] ?? '';

// ...

// ... rest of script

// ...

?>

Une fois ces fichiers en place, il faut exécuter « Réparations Rapides et Reconstructions » dans l’interface d’administration, pour que les changements soient pris en compte (Entry Point et Hook).

Voilà, la fonction JavaScript tmcWebhook() est maintenant disponible partout dans SuiteCRM. Dans un autre article, je donne deux exemples pour l’utiliser :

  • ajouter un bouton à un menu latéral ;
  • ajouter un bouton au menu des actions dans les fiches détaillées.

Il existe d’autres méthodes pour inclure du JavaScript dans des pages précises (par exemple, uniquement sur l’affichage d’une fiche Contact) ce qui peut être bien plus efficace pour des applications plus spécifiques. Dans le cas présent, il s’agit d’une fonction très légère et versatile, et que j’utilise à des endroits variés. C’est pourquoi j’ai choisi une approche très globale.