interface_50_modTicket_TicketEmail.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <?php
  2. /*
  3. * Copyright (C) 2014-2016 Jean-François Ferry <hello@librethic.io>
  4. * 2016 Christophe Battarel <christophe@altairis.fr>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * \file htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php
  21. * \ingroup core
  22. * \brief File of trigger for ticket module
  23. */
  24. require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
  25. /**
  26. * Class of triggers for ticket module
  27. */
  28. class InterfaceTicketEmail extends DolibarrTriggers
  29. {
  30. /**
  31. * Constructor
  32. *
  33. * @param DoliDB $db Database handler
  34. */
  35. public function __construct($db)
  36. {
  37. $this->db = $db;
  38. $this->name = preg_replace('/^Interface/i', '', get_class($this));
  39. $this->family = "ticket";
  40. $this->description = "Triggers of the module ticket to send notifications to internal users and to third-parties";
  41. $this->version = self::VERSION_DOLIBARR; // 'development', 'experimental', 'dolibarr' or version
  42. $this->picto = 'ticket';
  43. }
  44. /**
  45. * Function called when a Dolibarrr business event is done.
  46. * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers
  47. *
  48. * @param string $action Event action code
  49. * @param Object $object Object
  50. * @param User $user Object user
  51. * @param Translate $langs Object langs
  52. * @param conf $conf Object conf
  53. * @return int <0 if KO, 0 if no triggered ran, >0 if OK
  54. */
  55. public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
  56. {
  57. $ok = 0;
  58. if (empty($conf->ticket) || empty($conf->ticket->enabled)) {
  59. return 0; // Module not active, we do nothing
  60. }
  61. switch ($action) {
  62. case 'TICKET_ASSIGNED':
  63. dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
  64. if ($object->fk_user_assign > 0 && $object->fk_user_assign != $user->id) {
  65. $userstat = new User($this->db);
  66. $res = $userstat->fetch($object->fk_user_assign);
  67. if ($res > 0) {
  68. // Send email to notification email
  69. if (empty($conf->global->TICKET_DISABLE_ALL_MAILS)) {
  70. // Init to avoid errors
  71. $filepath = array();
  72. $filename = array();
  73. $mimetype = array();
  74. // Send email to assigned user
  75. $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketAssignedToYou');
  76. $message = '<p>'.$langs->transnoentities('TicketAssignedEmailBody', $object->track_id, dolGetFirstLastname($user->firstname, $user->lastname))."</p>";
  77. $message .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
  78. $message .= '<li>'.$langs->trans('Type').' : '.$object->type_label.'</li>';
  79. $message .= '<li>'.$langs->trans('Category').' : '.$object->category_label.'</li>';
  80. $message .= '<li>'.$langs->trans('Severity').' : '.$object->severity_label.'</li>';
  81. // Extrafields
  82. if (is_array($object->array_options) && count($object->array_options) > 0) {
  83. foreach ($object->array_options as $key => $value) {
  84. $message .= '<li>'.$langs->trans($key).' : '.$value.'</li>';
  85. }
  86. }
  87. $message .= '</ul>';
  88. $message .= '<p>'.$langs->trans('Message').' : <br>'.$object->message.'</p>';
  89. $message .= '<p><a href="'.dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id.'">'.$langs->trans('SeeThisTicketIntomanagementInterface').'</a></p>';
  90. $sendto = $userstat->email;
  91. $from = dolGetFirstLastname($user->firstname, $user->lastname).'<'.$user->email.'>';
  92. $message = dol_nl2br($message);
  93. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  94. $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
  95. $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
  96. }
  97. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  98. $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, '', '', 0, -1);
  99. if ($mailfile->error) {
  100. setEventMessages($mailfile->error, $mailfile->errors, 'errors');
  101. } else {
  102. $result = $mailfile->sendfile();
  103. }
  104. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  105. $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
  106. }
  107. }
  108. $ok = 1;
  109. } else {
  110. $this->error = $userstat->error;
  111. $this->errors = $userstat->errors;
  112. }
  113. }
  114. break;
  115. case 'TICKET_CREATE':
  116. dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
  117. $langs->load('ticket');
  118. $subject_admin = 'TicketNewEmailSubjectAdmin';
  119. $body_admin = 'TicketNewEmailBodyAdmin';
  120. $subject_customer = 'TicketNewEmailSubjectCustomer';
  121. $body_customer = 'TicketNewEmailBodyCustomer';
  122. $see_ticket_customer = 'TicketNewEmailBodyInfosTrackUrlCustomer';
  123. // Send email to notification email
  124. if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && empty($object->context['disableticketemail'])) {
  125. $sendto = empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) ? '' : $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
  126. if ($sendto) {
  127. $this->composeAndSendAdminMessage($sendto, $subject_admin, $body_admin, $object, $langs);
  128. }
  129. }
  130. // Send email to customer
  131. if (empty($conf->global->TICKET_DISABLE_CUSTOMER_MAILS) && empty($object->context['disableticketemail']) && $object->notify_tiers_at_create) {
  132. $sendto = '';
  133. //if contact selected send to email's contact else send to email's thirdparty
  134. $contactid = GETPOST('contactid', 'alpha');
  135. $res = 0;
  136. if (!empty($contactid)) {
  137. $contact = new Contact($this->db);
  138. $res = $contact->fetch($contactid);
  139. }
  140. if ($res > 0 && !empty($contact->email) && !empty($contact->statut)) {
  141. $sendto = $contact->email;
  142. } elseif (!empty($object->fk_soc)) {
  143. $object->fetch_thirdparty();
  144. $sendto = $object->thirdparty->email;
  145. }
  146. if ($sendto) {
  147. $this->composeAndSendCustomerMessage($sendto, $subject_customer, $body_customer, $see_ticket_customer, $object, $langs);
  148. }
  149. }
  150. $ok = 1;
  151. break;
  152. case 'TICKET_DELETE':
  153. dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
  154. break;
  155. case 'TICKET_MODIFY':
  156. dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
  157. break;
  158. case 'TICKET_CLOSE':
  159. dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
  160. $langs->load('ticket');
  161. $subject_admin = 'TicketCloseEmailSubjectAdmin';
  162. $body_admin = 'TicketCloseEmailBodyAdmin';
  163. $subject_customer = 'TicketCloseEmailSubjectCustomer';
  164. $body_customer = 'TicketCloseEmailBodyCustomer';
  165. $see_ticket_customer = 'TicketCloseEmailBodyInfosTrackUrlCustomer';
  166. // Send email to notification email
  167. if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && empty($object->context['disableticketemail'])) {
  168. $sendto = empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) ? '' : $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
  169. if ($sendto) {
  170. $this->composeAndSendAdminMessage($sendto, $subject_admin, $body_admin, $object, $langs);
  171. }
  172. }
  173. // Send email to customer.
  174. if (empty($conf->global->TICKET_DISABLE_CUSTOMER_MAILS) && empty($object->context['disableticketemail'])) {
  175. $linked_contacts = $object->listeContact(-1, 'thirdparty');
  176. $linked_contacts = array_merge($linked_contacts, $object->listeContact(-1, 'internal'));
  177. if (empty($linked_contacts) && !empty($conf->global->TICKET_NOTIFY_AT_CLOSING) && !empty($object->fk_soc)) {
  178. $object->fetch_thirdparty();
  179. $linked_contacts[] = $object->thirdparty->email;
  180. }
  181. $contactid = GETPOST('contactid', 'int');
  182. $res = 0;
  183. if ($contactid > 0) {
  184. $contact = new Contact($this->db);
  185. $res = $contact->fetch($contactid);
  186. if (! in_array($contact, $linked_contacts)) {
  187. $error_msg = $langs->trans('Error'). ': ';
  188. $error_msg .= $langs->transnoentities('TicketWrongContact');
  189. setEventMessages($error_msg, [], 'errors');
  190. $ok = 0;
  191. break;
  192. }
  193. }
  194. $sendto = '';
  195. if ($res > 0 && !empty($contact->email) && !empty($contact->statut)) {
  196. $sendto = $contact->email;
  197. } elseif ( !empty($linked_contacts) && ($contactid == -2 || (GETPOST('massaction', 'alpha') == 'close' && GETPOST('confirm', 'alpha') == 'yes'))) {
  198. // if sending to all contacts or sending to contacts while mass closing
  199. $temp_emails = [];
  200. foreach ($linked_contacts as $contact) {
  201. $temp_emails[] = $contact['email'];
  202. }
  203. $sendto = implode(", ", $temp_emails);
  204. unset($temp_emails);
  205. unset($linked_contacts);
  206. }
  207. if ($sendto) {
  208. $this->composeAndSendCustomerMessage($sendto, $subject_customer, $body_customer, $see_ticket_customer, $object, $langs);
  209. }
  210. }
  211. $ok = 1;
  212. break;
  213. }
  214. return $ok;
  215. }
  216. /**
  217. * Composes and sends a message concerning a ticket, to be sent to admin address.
  218. *
  219. * @param string $sendto Addresses to send the mail, format "first@address.net, second@address.net," etc.
  220. * @param string $base_subject email subject. Non-translated string.
  221. * @param string $body email body (first line). Non-translated string.
  222. * @param Ticket $object the ticket thet the email refers to
  223. * @param Translate $langs the translation object
  224. * @return void
  225. */
  226. private function composeAndSendAdminMessage($sendto, $base_subject, $body, Ticket $object, Translate $langs)
  227. {
  228. global $conf;
  229. // Init to avoid errors
  230. $filepath = array();
  231. $filename = array();
  232. $mimetype = array();
  233. /* Send email to admin */
  234. $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities($base_subject, $object->ref, $object->track_id);
  235. $message_admin = $langs->transnoentities($body, $object->track_id).'<br>';
  236. $message_admin .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
  237. $message_admin .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
  238. $message_admin .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
  239. $message_admin .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
  240. $message_admin .= '<li>'.$langs->trans('From').' : '.($object->email_from ? $object->email_from : ($object->fk_user_create > 0 ? $langs->trans('Internal') : '')).'</li>';
  241. // Extrafields
  242. $extraFields = new ExtraFields($this->db);
  243. $extraFields->fetch_name_optionals_label($object->table_element);
  244. if (is_array($object->array_options) && count($object->array_options) > 0) {
  245. foreach ($object->array_options as $key => $value) {
  246. $key = substr($key, 8); // remove "options_"
  247. $message_admin .= '<li>'.$langs->trans($extraFields->attributes[$object->element]['label'][$key]).' : '.$extraFields->showOutputField($key, $value, '', $object->table_element).'</li>';
  248. }
  249. }
  250. if ($object->fk_soc > 0) {
  251. $object->fetch_thirdparty();
  252. $message_admin .= '<li>'.$langs->trans('Company').' : '.$object->thirdparty->name.'</li>';
  253. }
  254. $message_admin .= '</ul>';
  255. $message = $object->message;
  256. if (!dol_textishtml($message)) {
  257. $message = dol_nl2br($message);
  258. }
  259. $message_admin .= '<p>'.$langs->trans('Message').' : <br><br>'.$message.'</p><br>';
  260. $message_admin .= '<p><a href="'.dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id.'">'.$langs->trans('SeeThisTicketIntomanagementInterface').'</a></p>';
  261. $from = $conf->global->MAIN_INFO_SOCIETE_NOM.'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
  262. $trackid = 'tic'.$object->id;
  263. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  264. $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
  265. $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
  266. }
  267. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  268. $mailfile = new CMailFile($subject, $sendto, $from, $message_admin, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
  269. if ($mailfile->error) {
  270. dol_syslog($mailfile->error, LOG_DEBUG);
  271. } else {
  272. $result = $mailfile->sendfile();
  273. }
  274. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  275. $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
  276. }
  277. }
  278. /**
  279. * Composes and sends a message concerning a ticket, to be sent to customer addresses.
  280. *
  281. * @param string $sendto Addresses to send the mail, format "first@address.net, second@address.net, " etc.
  282. * @param string $base_subject email subject. Non-translated string.
  283. * @param string $body email body (first line). Non-translated string.
  284. * @param string $see_ticket string indicating the ticket public address
  285. * @param Ticket $object the ticket thet the email refers to
  286. * @param Translate $langs the translation object
  287. * @return void
  288. */
  289. private function composeAndSendCustomerMessage($sendto, $base_subject, $body, $see_ticket, Ticket $object, Translate $langs)
  290. {
  291. global $conf, $user;
  292. // Init to avoid errors
  293. $filepath = array();
  294. $filename = array();
  295. $mimetype = array();
  296. $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities($base_subject);
  297. $message_customer = $langs->transnoentities($body, $object->track_id).'<br>';
  298. $message_customer .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
  299. $message_customer .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
  300. $message_customer .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
  301. $message_customer .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
  302. // Extrafields
  303. if (is_array($this->attributes[$object->table_element]['label'])) {
  304. foreach ($this->attributes[$object->table_element]['label'] as $key => $value) {
  305. $enabled = 1;
  306. if ($enabled && isset($this->attributes[$object->table_element]['list'][$key])) {
  307. $enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1);
  308. }
  309. $perms = 1;
  310. if ($perms && isset($this->attributes[$object->table_element]['perms'][$key])) {
  311. $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1);
  312. }
  313. $qualified = true;
  314. if (empty($enabled)) {
  315. $qualified = false;
  316. }
  317. if (empty($perms)) {
  318. $qualified = false;
  319. }
  320. if ($qualified) {
  321. $message_customer .= '<li>' . $langs->trans($key) . ' : ' . $value . '</li>';
  322. }
  323. }
  324. }
  325. $message_customer .= '</ul>';
  326. $message = $object->message;
  327. if (!dol_textishtml($message)) {
  328. $message = dol_nl2br($message);
  329. }
  330. $message_customer .= '<p>'.$langs->trans('Message').' : <br><br>'.$message.'</p><br>';
  331. $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id;
  332. $message_customer .= '<p>'.$langs->trans($see_ticket).' : <a href="'.$url_public_ticket.'">'.$url_public_ticket.'</a></p>';
  333. $message_customer .= '<p>'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'</p>';
  334. $from = (empty($conf->global->MAIN_INFO_SOCIETE_NOM) ? '' : $conf->global->MAIN_INFO_SOCIETE_NOM.' ').'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
  335. $trackid = 'tic'.$object->id;
  336. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  337. $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
  338. $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
  339. }
  340. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  341. $mailfile = new CMailFile($subject, $sendto, $from, $message_customer, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
  342. if ($mailfile->error) {
  343. dol_syslog($mailfile->error, LOG_DEBUG);
  344. } else {
  345. $result = $mailfile->sendfile();
  346. if ($result) {
  347. // update last_msg_sent date
  348. $object->fetch($object->id);
  349. $object->date_last_msg_sent = dol_now();
  350. $object->update($user);
  351. }
  352. }
  353. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  354. $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
  355. }
  356. }
  357. }