File: //proc/self/cwd/guiaweb/htdocs/core/triggers/interface_95_modZapier_ZapierTriggers.class.php
<?php
/* Copyright (C) 2017-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/core/triggers/interface_99_modZapier_ZapierTriggers.class.php
* \ingroup zapier
* \brief File for Zappier Triggers.
*/
require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
/**
* Class of triggers for Zapier module
*/
class InterfaceZapierTriggers extends DolibarrTriggers
{
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
public function __construct($db)
{
$this->db = $db;
$this->name = preg_replace('/^Interface/i', '', get_class($this));
$this->family = "technic";
$this->description = "Zapier triggers.";
$this->version = self::VERSIONS['dev'];
$this->picto = 'zapier';
}
/**
* Function called when a Dolibarr business event is done.
* All functions "runTrigger" are triggered if file
* is inside directory core/triggers
*
* @param string $action Event action code
* @param CommonObject $object Object
* @param User $user Object user
* @param Translate $langs Object langs
* @param Conf $conf Object conf
* @return int Return integer <0 if KO, 0 if no triggered ran, >0 if OK
*/
public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
{
if (empty($conf->zapier) || empty($conf->zapier->enabled)) {
// Module not active, we do nothing
return 0;
}
$logtriggeraction = false;
$sql = '';
if ($action != '') {
$actions = explode('_', $action);
$sql = 'SELECT rowid, url FROM '.MAIN_DB_PREFIX.'zapier_hook';
$sql .= ' WHERE module="'.$this->db->escape(strtolower($actions[0])).'" AND action="'.$this->db->escape(strtolower($actions[1])).'"';
//setEventMessages($sql, null);
}
switch ($action) {
// Users
case 'USER_CREATE':
$resql = $this->db->query($sql);
// TODO voir comment regrouper les webhooks en un post
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'USER_MODIFY':
$resql = $this->db->query($sql);
// TODO voir comment regrouper les webhooks en un post
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
//case 'USER_NEW_PASSWORD':
//case 'USER_ENABLEDISABLE':
//case 'USER_DELETE':
//case 'USER_LOGIN':
//case 'USER_LOGIN_FAILED':
//case 'USER_LOGOUT':
// Actions
case 'ACTION_MODIFY':
//$logtriggeraction = true;
break;
case 'ACTION_CREATE':
$resql = $this->db->query($sql);
// TODO voir comment regrouper les webhooks en un post
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$cleaned = cleanAgendaEventsDatas($cleaned);
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
//setEventMessages($obj['url'], null);
}
$logtriggeraction = true;
break;
case 'ACTION_DELETE':
//$logtriggeraction = true;
break;
// Groups
//case 'USERGROUP_CREATE':
//case 'USERGROUP_MODIFY':
//case 'USERGROUP_DELETE':
// Categories
// case 'CATEGORY_CREATE':
// case 'CATEGORY_MODIFY':
// case 'CATEGORY_DELETE':
// case 'CATEGORY_SET_MULTILANGS':
// Companies
case 'COMPANY_CREATE':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'COMPANY_MODIFY':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'COMPANY_DELETE':
//$logtriggeraction = true;
break;
// Contacts
case 'CONTACT_CREATE':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'CONTACT_MODIFY':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'CONTACT_DELETE':
break;
case 'CONTACT_ENABLEDISABLE':
break;
// Products
// case 'PRODUCT_CREATE':
// case 'PRODUCT_MODIFY':
// case 'PRODUCT_DELETE':
// case 'PRODUCT_PRICE_MODIFY':
// case 'PRODUCT_SET_MULTILANGS':
// case 'PRODUCT_DEL_MULTILANGS':
//Stock movement
// case 'STOCK_MOVEMENT':
//MYECMDIR
// case 'MYECMDIR_DELETE':
// case 'MYECMDIR_CREATE':
// case 'MYECMDIR_MODIFY':
// Sales orders
case 'ORDER_CREATE':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'ORDER_CLONE':
break;
case 'ORDER_VALIDATE':
break;
case 'ORDER_DELETE':
case 'ORDER_CANCEL':
case 'ORDER_SENTBYMAIL':
case 'ORDER_CLASSIFY_BILLED':
case 'ORDER_SETDRAFT':
case 'LINEORDER_INSERT':
case 'LINEORDER_MODIFY':
case 'LINEORDER_DELETE':
break;
// Supplier orders
// case 'ORDER_SUPPLIER_CREATE':
// case 'ORDER_SUPPLIER_CLONE':
// case 'ORDER_SUPPLIER_VALIDATE':
// case 'ORDER_SUPPLIER_DELETE':
// case 'ORDER_SUPPLIER_APPROVE':
// case 'ORDER_SUPPLIER_REFUSE':
// case 'ORDER_SUPPLIER_CANCEL':
// case 'ORDER_SUPPLIER_SENTBYMAIL':
// case 'ORDER_SUPPLIER_RECEIVE':
// case 'LINEORDER_SUPPLIER_DISPATCH':
// case 'LINEORDER_SUPPLIER_CREATE':
// case 'LINEORDER_SUPPLIER_MODIFY':
// Proposals
// case 'PROPAL_CREATE':
// case 'PROPAL_CLONE':
// case 'PROPAL_MODIFY':
// case 'PROPAL_VALIDATE':
// case 'PROPAL_SENTBYMAIL':
// case 'PROPAL_CLOSE_SIGNED':
// case 'PROPAL_CLOSE_REFUSED':
// case 'PROPAL_DELETE':
// case 'LINEPROPAL_INSERT':
// case 'LINEPROPAL_MODIFY':
// case 'LINEPROPAL_DELETE':
// SupplierProposal
// case 'SUPPLIER_PROPOSAL_CREATE':
// case 'SUPPLIER_PROPOSAL_CLONE':
// case 'SUPPLIER_PROPOSAL_MODIFY':
// case 'SUPPLIER_PROPOSAL_VALIDATE':
// case 'SUPPLIER_PROPOSAL_SENTBYMAIL':
// case 'SUPPLIER_PROPOSAL_CLOSE_SIGNED':
// case 'SUPPLIER_PROPOSAL_CLOSE_REFUSED':
// case 'SUPPLIER_PROPOSAL_DELETE':
// case 'LINESUPPLIER_PROPOSAL_INSERT':
// case 'LINESUPPLIER_PROPOSAL_MODIFY':
// case 'LINESUPPLIER_PROPOSAL_DELETE':
// Contracts
// case 'CONTRACT_CREATE':
// case 'CONTRACT_ACTIVATE':
// case 'CONTRACT_CANCEL':
// case 'CONTRACT_CLOSE':
// case 'CONTRACT_DELETE':
// case 'LINECONTRACT_INSERT':
// case 'LINECONTRACT_MODIFY':
// case 'LINECONTRACT_DELETE':
// Bills
// case 'BILL_CREATE':
// case 'BILL_CLONE':
// case 'BILL_MODIFY':
// case 'BILL_VALIDATE':
// case 'BILL_UNVALIDATE':
// case 'BILL_SENTBYMAIL':
// case 'BILL_CANCEL':
// case 'BILL_DELETE':
// case 'BILL_PAYED':
// case 'LINEBILL_INSERT':
// case 'LINEBILL_MODIFY':
// case 'LINEBILL_DELETE':
//Supplier Bill
// case 'BILL_SUPPLIER_CREATE':
// case 'BILL_SUPPLIER_MODIFY':
// case 'BILL_SUPPLIER_DELETE':
// case 'BILL_SUPPLIER_PAYED':
// case 'BILL_SUPPLIER_UNPAYED':
// case 'BILL_SUPPLIER_VALIDATE':
// case 'BILL_SUPPLIER_UNVALIDATE':
// case 'LINEBILL_SUPPLIER_CREATE':
// case 'LINEBILL_SUPPLIER_MODIFY':
// case 'LINEBILL_SUPPLIER_DELETE':
// Payments
// case 'PAYMENT_CUSTOMER_CREATE':
// case 'PAYMENT_SUPPLIER_CREATE':
// case 'PAYMENT_ADD_TO_BANK':
// case 'PAYMENT_DELETE':
// Online
// case 'PAYMENT_PAYBOX_OK':
// case 'PAYMENT_PAYPAL_OK':
// case 'PAYMENT_STRIPE_OK':
// Donation
// case 'DON_CREATE':
// case 'DON_MODIFY':
// case 'DON_DELETE':
// Interventions
// case 'FICHINTER_CREATE':
// case 'FICHINTER_MODIFY':
// case 'FICHINTER_VALIDATE':
// case 'FICHINTER_DELETE':
// case 'LINEFICHINTER_CREATE':
// case 'LINEFICHINTER_MODIFY':
// case 'LINEFICHINTER_DELETE':
// Members
case 'MEMBER_CREATE':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
case 'MEMBER_MODIFY':
$resql = $this->db->query($sql);
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
// case 'MEMBER_VALIDATE':
// case 'MEMBER_SUBSCRIPTION':
// case 'MEMBER_NEW_PASSWORD':
// case 'MEMBER_RESILIATE':
// case 'MEMBER_DELETE':
// Projects
// case 'PROJECT_CREATE':
// case 'PROJECT_MODIFY':
// case 'PROJECT_DELETE':
// Project tasks
// case 'TASK_CREATE':
// case 'TASK_MODIFY':
// case 'TASK_DELETE':
// Task time spent
// case 'TASK_TIMESPENT_CREATE':
// case 'TASK_TIMESPENT_MODIFY':
// case 'TASK_TIMESPENT_DELETE':
case 'TICKET_CREATE':
$resql = $this->db->query($sql);
// TODO voir comment regrouper les webhooks en un post
while ($resql && $obj = $this->db->fetch_array($resql)) {
$cleaned = cleanObjectDatas(dol_clone($object));
$json = json_encode($cleaned);
// call the zapierPostWebhook() function
zapierPostWebhook($obj['url'], $json);
}
$logtriggeraction = true;
break;
// case 'TICKET_MODIFY':
// break;
// case 'TICKET_DELETE':
// break;
// Shipping
// case 'SHIPPING_CREATE':
// case 'SHIPPING_MODIFY':
// case 'SHIPPING_VALIDATE':
// case 'SHIPPING_SENTBYMAIL':
// case 'SHIPPING_BILLED':
// case 'SHIPPING_CLOSED':
// case 'SHIPPING_REOPEN':
// case 'SHIPPING_DELETE':
}
if ($logtriggeraction) {
dol_syslog("Trigger '".$this->name."' for action '".$action."' launched by ".__FILE__." id=".$object->id);
}
return 0;
}
}
/**
* Post webhook in zapier with object data
*
* @param string $url Url provided by zapier
* @param string $json Data to send
* @return void
*/
function zapierPostWebhook($url, $json)
{
$headers = array('Accept: application/json', 'Content-Type: application/json');
// TODO disable wekhook if error ?
dol_syslog("Send message to Zapier with json size=".dol_strlen($json), LOG_DEBUG);
getURLContent($url, 'POSTALREADYFORMATED', $json, 1, $headers, array('http', 'https'), 0);
/*
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$output = curl_exec($ch);
curl_close($ch);
*/
}
/**
* Clean sensible object datas
*
* @param Object $toclean Object to clean
* @return Object Object with cleaned properties
*/
function cleanObjectDatas($toclean)
{
// Remove $db object property for object
unset($toclean->db);
// Remove linkedObjects. We should already have linkedObjectsIds that avoid huge responses
unset($toclean->linkedObjects);
unset($toclean->lines); // should be ->lines
unset($toclean->fields);
unset($toclean->oldline);
unset($toclean->error);
unset($toclean->errors);
unset($toclean->ref_previous);
unset($toclean->ref_next);
unset($toclean->projet); // Should be fk_project
unset($toclean->project); // Should be fk_project
unset($toclean->author); // Should be fk_user_author
unset($toclean->timespent_old_duration);
unset($toclean->timespent_id);
unset($toclean->timespent_duration);
unset($toclean->timespent_date);
unset($toclean->timespent_datehour);
unset($toclean->timespent_withhour);
unset($toclean->timespent_fk_user);
unset($toclean->timespent_note);
unset($toclean->labelStatus);
unset($toclean->labelStatusShort);
unset($toclean->element);
unset($toclean->fk_element);
unset($toclean->table_element);
unset($toclean->table_element_line);
unset($toclean->picto);
unset($toclean->skip_update_total);
unset($toclean->context);
// Remove the $oldcopy property because it is not supported by the JSON
// encoder. The following error is generated when trying to serialize
// it: "Error encoding/decoding JSON: Type is not supported"
// Note: Event if this property was correctly handled by the JSON
// encoder, it should be ignored because keeping it would let the API
// have a very strange behavior: calling PUT and then GET on the same
// resource would give different results:
// PUT /objects/{id} -> returns object with oldcopy = previous version of the object
// GET /objects/{id} -> returns object with oldcopy empty
unset($toclean->oldcopy);
// If object has lines, remove $db property
if (isset($toclean->lines) && count($toclean->lines) > 0) {
$nboflines = count($toclean->lines);
for ($i = 0; $i < $nboflines; $i++) {
cleanObjectDatas($toclean->lines[$i]);
}
}
// If object has linked objects, remove $db property
/*
if(isset($toclean->linkedObjects) && count($toclean->linkedObjects) > 0) {
foreach($toclean->linkedObjects as $type_object => $linked_object) {
foreach($linked_object as $toclean2clean) {
$this->cleanObjectDatas($toclean2clean);
}
}
}*/
return $toclean;
}
/**
* Clean sensible object datas
*
* @param Object $toclean Object to clean
* @return Object Object with cleaned properties
*/
function cleanAgendaEventsDatas($toclean)
{
unset($toclean->usermod);
unset($toclean->libelle);
//unset($toclean->array_options);
unset($toclean->context);
unset($toclean->canvas);
unset($toclean->contact);
unset($toclean->contact_id);
unset($toclean->thirdparty);
unset($toclean->user);
unset($toclean->origin);
unset($toclean->origin_id);
unset($toclean->ref_ext);
unset($toclean->statut);
unset($toclean->country);
unset($toclean->country_id);
unset($toclean->country_code);
unset($toclean->barcode_type);
unset($toclean->barcode_type_code);
unset($toclean->barcode_type_label);
unset($toclean->barcode_type_coder);
unset($toclean->mode_reglement_id);
unset($toclean->cond_reglement_id);
unset($toclean->cond_reglement);
unset($toclean->fk_delivery_address);
unset($toclean->shipping_method_id);
unset($toclean->fk_account);
unset($toclean->total_ht);
unset($toclean->total_tva);
unset($toclean->total_localtax1);
unset($toclean->total_localtax2);
unset($toclean->total_ttc);
unset($toclean->fk_incoterms);
unset($toclean->libelle_incoterms);
unset($toclean->location_incoterms);
unset($toclean->name);
unset($toclean->lastname);
unset($toclean->firstname);
unset($toclean->civility_id);
unset($toclean->contact);
unset($toclean->societe);
return $toclean;
}