dolibarr 25.0.0-alpha
notify.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2018 Philippe Grand <philippe.grand@atoo-net.com>
6 * Copyright (C) 2021 Thibault FOUCART <support@ptibogxiv.net>
7 * Copyright (C) 2022 Anthony Berton <anthony.berton@bb2a.fr>
8 * Copyright (C) 2023 William Mead <william.mead@manchenumerique.fr>
9 * Copyright (C) 2024 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
10 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
11 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
12 * Copyright (C) 2026 Pierre Ardoin <developpeur@lesmetiersdubatiment.fr>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
33require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
34
35
39class Notify
40{
44 public $id;
45
49 public $db;
50
54 public $type;
55
59 public $threshold;
60
64 public $context;
65
69 public $event;
70
74 public $socid;
75
79 public $contact_id;
80
84 public $fk_user;
85
89 public $email;
90
91
97 public $datec;
98
104 public $datem;
105
109 public $error = '';
110
114 public $errors = array();
115
119 public $author;
123 public $ref;
127 public $date;
131 public $duree;
135 public $note;
136
140 public $fk_project;
141
145 public static $arrayofnotifsupported = array(
146 'BILL_CANCEL',
147 'BILL_VALIDATE',
148 'BILL_PAYED',
149 'ORDER_CANCEL',
150 'ORDER_CREATE',
151 'ORDER_VALIDATE',
152 'ORDER_CLOSE',
153 'PROPAL_VALIDATE',
154 'PROPAL_CLOSE_SIGNED',
155 'PROPAL_CLOSE_REFUSED',
156 'FICHINTER_VALIDATE',
157 'FICHINTER_MODIFY',
158 'FICHINTER_CLOSE',
159 'FICHINTER_ADD_CONTACT',
160 'ORDER_SUPPLIER_CANCEL',
161 'ORDER_SUPPLIER_VALIDATE',
162 'ORDER_SUPPLIER_APPROVE',
163 'ORDER_SUPPLIER_SUBMIT',
164 'ORDER_SUPPLIER_REFUSE',
165 'SHIPPING_MODIFY',
166 'SHIPPING_VALIDATE',
167 'EXPENSE_REPORT_VALIDATE',
168 'EXPENSE_REPORT_APPROVE',
169 'HOLIDAY_VALIDATE',
170 'HOLIDAY_APPROVE',
171 'ACTION_CREATE',
172 'CONTRACT_MODIFY',
173 'STOCKTRANSFER_CREATE',
174 'STOCKTRANSFER_MODIFY',
175 'STOCKTRANSFER_VALIDATE',
176 'STOCKTRANSFER_UNVALIDATE',
177 'STOCKTRANSFER_CLOSE'
178 );
179
185 public function __construct($db)
186 {
187 $this->db = $db;
188 }
189
190
200 public function confirmMessage($action, $socid, $object)
201 {
202 global $langs;
203 $langs->load("mails");
204
205 // Get full list of all notifications subscribed for $action, $socid and $object
206 $listofnotiftodo = $this->getNotificationsArray($action, $socid, $object, 0);
207
208 if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER')) {
209 foreach ($listofnotiftodo as $val) {
210 if ($val['type'] == 'touser') {
211 unset($listofnotiftodo[$val['email']]);
212 //$listofnotiftodo = array_merge($listofnotiftodo);
213 }
214 }
215 }
216 if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT')) {
217 foreach ($listofnotiftodo as $val) {
218 if ($val['type'] == 'tocontact') {
219 unset($listofnotiftodo[$val['email']]);
220 //$listofnotiftodo = array_merge($listofnotiftodo);
221 }
222 }
223 }
224 if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX')) {
225 foreach ($listofnotiftodo as $val) {
226 if ($val['type'] == 'tofixedemail') {
227 unset($listofnotiftodo[$val['email']]);
228 //$listofnotiftodo = array_merge($listofnotiftodo);
229 }
230 }
231 }
232
233 $texte = '';
234 $nb = -1;
235 if (is_array($listofnotiftodo)) {
236 $nb = count($listofnotiftodo);
237 }
238 if ($nb < 0) {
239 $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"').$langs->trans("ErrorFailedToGetListOfNotificationsToSend");
240 } elseif ($nb == 0) {
241 $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"').$langs->trans("NoNotificationsWillBeSent");
242 } elseif ($nb == 1) {
243 $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"').$langs->trans("ANotificationsWillBeSent");
244 } else { // Always >= 2 if ($nb >= 2) {
245 $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"').$langs->trans("SomeNotificationsWillBeSent", $nb);
246 }
247
248 if (is_array($listofnotiftodo)) {
249 $i = 0;
250 foreach ($listofnotiftodo as $val) {
251 if ($i) {
252 $texte .= ', ';
253 } else {
254 $texte .= ' (';
255 }
256 if ($val['isemailvalid']) {
257 $texte .= $val['email'];
258 } else {
259 $texte .= $val['emaildesc'];
260 }
261 $i++;
262 }
263 if ($i) {
264 $texte .= ')';
265 }
266 }
267
268 return $texte;
269 }
270
277 public function delete($user = null)
278 {
279 $error = 0;
280
281 dol_syslog(get_class($this)."::delete ".$this->id, LOG_DEBUG);
282
283 $this->db->begin();
284
285 if (!$error) {
286 $sql = "DELETE FROM ".MAIN_DB_PREFIX."notify_def";
287 $sql .= " WHERE rowid = ".((int) $this->id);
288 $sql .= " AND entity IN (".getEntity('notify_def').")";
289
290 if (!$this->db->query($sql)) {
291 $error++;
292 $this->errors[] = $this->db->lasterror();
293 }
294 }
295
296 if (!$error) {
297 $this->db->commit();
298 return 1;
299 } else {
300 $this->db->rollback();
301 return -1 * $error;
302 }
303 }
304
312 public function create($user = null, $notrigger = 0)
313 {
314 global $conf;
315
316 $now = dol_now();
317
318 $error = 0;
319
320 // Check parameters
321 if (empty($this->socid)) {
322 $this->error = 'BadValueForParameter';
323 $this->errors[] = $this->error;
324 return -1;
325 }
326
327 if (empty($this->datec)) {
328 $this->datec = $now;
329 }
330
331 $this->db->begin();
332
333 $sql = "INSERT INTO ".MAIN_DB_PREFIX."notify_def (entity, fk_soc, fk_action, fk_contact, type, datec)";
334 $sql .= " VALUES (".((int) $conf->entity).", ".((int) $this->socid).", ".((int) $this->event).", ".((int) $this->contact_id).",";
335 $sql .= "'".$this->db->escape($this->type)."', '".$this->db->idate($this->datec)."')";
336
337 $resql = $this->db->query($sql);
338 if ($resql) {
339 if ($this->db->affected_rows($resql)) {
340 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."notify_def");
341 }
342 } else {
343 $error++;
344 $this->error = $this->db->lasterror();
345 $this->errors[] = $this->error;
346 }
347
348 if (!$error) {
349 $this->db->commit();
350 return $this->id;
351 } else {
352 $this->db->rollback();
353 return -1;
354 }
355 }
356
365 public function fetch($id, $socid = 0, $type = 'email')
366 {
367 if (empty($id) && empty($socid)) {
368 return -1;
369 }
370
371 $sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem";
372 $sql .= " FROM ".MAIN_DB_PREFIX."notify_def";
373
374 if ($id) {
375 $sql .= " WHERE rowid = ".((int) $id);
376 } elseif ($socid > 0) {
377 $sql .= " WHERE fk_soc = ".((int) $socid);
378 if ($type) {
379 $sql .= " AND type = '".$this->db->escape($type)."'";
380 }
381 }
382
383 $resql = $this->db->query($sql);
384 if ($resql) {
385 if ($this->db->num_rows($resql)) {
386 $obj = $this->db->fetch_object($resql);
387
388 $this->id = $obj->rowid;
389 $this->type = $obj->type;
390 $this->event = $obj->event;
391 $this->socid = $obj->socid;
392 $this->contact_id = $obj->contact_id;
393 $this->fk_user = $obj->fk_user;
394 $this->email = $obj->email;
395 $this->threshold = $obj->threshold;
396 $this->context = $obj->context;
397 $this->datec = $this->db->jdate($obj->datec);
398 $this->datem = $this->db->jdate($obj->datem);
399 }
400 $this->db->free($resql);
401
402 return 1;
403 } else {
404 dol_print_error($this->db);
405 return -1;
406 }
407 }
408
416 public function update($user = null, $notrigger = 0)
417 {
418 global $langs;
419
420 $error = 0;
421
422 if (!$this->id) {
423 return -1;
424 }
425
426 $this->db->begin();
427
428 $sql = "UPDATE ".MAIN_DB_PREFIX."notify_def SET";
429 $sql .= " type = '".$this->db->escape($this->type)."'";
430 // $sql .= ",fk_user = ".((int) $this->fk_user);
431 // $sql .= ",email = '".$this->db->escape($this->email)."'";
432 // $sql .= ",threshold = '".$this->db->escape($this->threshold)."'";
433 // $sql .= ",context = '".$this->db->escape($this->context)."'";
434 $sql .= ",fk_soc = ".((int) $this->socid);
435 $sql .= ",fk_action = ".((int) $this->event);
436 $sql .= ",fk_contact = ".((int) $this->contact_id);
437 $sql .= " WHERE rowid = ".((int) $this->id);
438 $sql .= " AND entity IN (".getEntity('notify_def').")";
439
440 $result = $this->db->query($sql);
441 if (!$result) {
442 $error++;
443 if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
444 $this->error = $langs->trans('ErrorDuplicateField');
445 } else {
446 $this->error = $this->db->lasterror();
447 }
448 $this->errors[] = $this->error;
449 }
450
451 if (!$error) {
452 $this->db->commit();
453 return 1;
454 } else {
455 $this->db->rollback();
456 return -1;
457 }
458 }
459
470 public function getNotificationsArray($notifcode, $socid = 0, $object = null, $userid = 0, $scope = array('thirdparty', 'user', 'global'))
471 {
472 global $conf, $user;
473
474 $error = 0;
475 $resarray = array();
476
477 $valueforthreshold = 0;
478 if (is_object($object)) {
479 $valueforthreshold = $object->total_ht;
480 }
481
482 $sqlnotifcode = '';
483 if ($notifcode) {
484 if (is_numeric($notifcode)) {
485 $sqlnotifcode = " AND n.fk_action = ".((int) $notifcode); // Old usage
486 } else {
487 $sqlnotifcode = " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
488 }
489 }
490
491 // Subscription per contact
492 if (!$error) {
493 if ($socid >= 0 && in_array('thirdparty', $scope)) {
494 $sql = "SELECT a.code, c.email, c.rowid, c.statut as status";
495 $sql .= " FROM ".$this->db->prefix()."notify_def as n,";
496 $sql .= " ".$this->db->prefix()."socpeople as c,";
497
498 $sql .= " ".$this->db->prefix()."c_action_trigger as a,";
499 $sql .= " ".$this->db->prefix()."societe as s";
500 $sql .= " WHERE n.fk_contact = c.rowid";
501 $sql .= " AND a.rowid = n.fk_action";
502 $sql .= " AND n.fk_soc = s.rowid";
503 $sql .= $sqlnotifcode;
504 $sql .= " AND s.entity IN (".getEntity('societe').")";
505 $sql .= " AND n.entity IN (".getEntity('notify_def').")";
506 if ($socid > 0) {
507 $sql .= " AND s.rowid = ".((int) $socid);
508 }
509
510 dol_syslog(__METHOD__." ".$notifcode.", ".$socid, LOG_DEBUG);
511
512 $resql = $this->db->query($sql);
513 if ($resql) {
514 $num = $this->db->num_rows($resql);
515 $i = 0;
516 while ($i < $num) {
517 $obj = $this->db->fetch_object($resql);
518 // we want to notify only if contact is enable
519 if ($obj && $obj->status == 1) {
520 $newval2 = trim($obj->email);
521 $isvalid = isValidEmail($newval2);
522 if (empty($resarray[$newval2])) {
523 $resarray[$newval2] = array('type' => 'tocontact', 'code' => trim($obj->code), 'emaildesc' => 'Contact id '.$obj->rowid, 'email' => $newval2, 'contactid' => $obj->rowid, 'isemailvalid' => $isvalid);
524 }
525 }
526 $i++;
527 }
528 } else {
529 $error++;
530 $this->error = $this->db->lasterror();
531 }
532 }
533 }
534
535 // Subscription per user
536 if (!$error) {
537 if ($userid >= 0 && in_array('user', $scope)) {
538 $sql = "SELECT a.code, c.email, c.rowid";
539 $sql .= " FROM ".$this->db->prefix()."notify_def as n,";
540 $sql .= " ".$this->db->prefix()."user as c,";
541 $sql .= " ".$this->db->prefix()."c_action_trigger as a";
542 $sql .= " WHERE n.fk_user = c.rowid";
543 $sql .= " AND a.rowid = n.fk_action";
544 $sql .= $sqlnotifcode;
545 $sql .= " AND c.entity IN (".getEntity('user').")";
546 $sql .= " AND n.entity IN (".getEntity('notify_def').")";
547 if ($userid > 0) {
548 $sql .= " AND c.rowid = ".((int) $userid);
549 }
550
551 dol_syslog(__METHOD__." ".$notifcode.", ".$socid, LOG_DEBUG);
552
553 $resql = $this->db->query($sql);
554 if ($resql) {
555 $num = $this->db->num_rows($resql);
556 $i = 0;
557 while ($i < $num) {
558 $obj = $this->db->fetch_object($resql);
559 if ($obj) {
560 $newval2 = trim($obj->email);
561 $isvalid = isValidEmail($newval2);
562 if (empty($resarray[$newval2])) {
563 $resarray[$newval2] = array('type' => 'touser', 'code' => trim($obj->code), 'emaildesc' => 'User id '.$obj->rowid, 'email' => $newval2, 'userid' => (int) $obj->rowid, 'isemailvalid' => $isvalid);
564 }
565 }
566 $i++;
567 }
568 } else {
569 $error++;
570 $this->error = $this->db->lasterror();
571 }
572 }
573 }
574
575 // Subscription global
576 if (!$error) {
577 if (in_array('global', $scope)) {
578 // List of notifications enabled for fixed email
579 foreach ($conf->global as $key => $val) {
580 if ($notifcode) {
581 if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
582 continue;
583 }
584 } else {
585 if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_.*_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
586 continue;
587 }
588 }
589
590 $threshold = (float) $reg[1];
591 if ($valueforthreshold < $threshold) {
592 continue;
593 }
594
595 $tmpemail = explode(',', $val);
596 foreach ($tmpemail as $key2 => $val2) {
597 $newval2 = trim($val2);
598 if ($newval2 == '__SUPERVISOREMAIL__') {
599 $newval2 = $this->getSupervisorEmail();
600 }
601 if ($newval2 == '__AUTHOREMAIL__') {
602 $newval2 = $this->getAuthorEmail($object);
603 }
604 if ($newval2) {
605 $isvalid = isValidEmail($newval2, 0);
606 if (empty($resarray[$newval2])) {
607 $resarray[$newval2] = array('type' => 'tofixedemail', 'code' => trim($key), 'emaildesc' => trim($val2), 'email' => $newval2, 'isemailvalid' => $isvalid);
608 }
609 }
610 }
611 }
612 }
613 }
614
615 if ($error) {
616 return -1;
617 }
618
619 return $resarray;
620 }
621
633 public function send($notifcode, $object, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
634 {
635 global $user, $conf, $langs, $mysoc;
636 global $hookmanager;
638 global $action;
639
640 // Complete the array Notify::$arrayofnotifsupported
641 if (!is_object($hookmanager)) {
642 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
643 $hookmanager = new HookManager($this->db);
644 }
645 $hookmanager->initHooks(array('notification'));
646
647 $parameters = array('notifcode' => $notifcode);
648 $reshook = $hookmanager->executeHooks('notifsupported', $parameters, $object, $action);
649 if (empty($reshook)) {
650 if (!empty($hookmanager->resArray['arrayofnotifsupported'])) {
651 Notify::$arrayofnotifsupported = array_merge(Notify::$arrayofnotifsupported, $hookmanager->resArray['arrayofnotifsupported']);
652 }
653 }
654
655 // If the trigger code is not managed by the Notification module
656 if (!in_array($notifcode, Notify::$arrayofnotifsupported)) {
657 return 0;
658 }
659
660 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
661
662 dol_syslog(get_class($this)."::send notifcode=".$notifcode.", object id=".$object->id);
663
664 $langs->load("other");
665
666 // Define $urlwithroot
667 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
668 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
669 //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
670
671 // Define some vars
672 $application = constant('DOL_APPLICATION_TITLE');
673 $applicationcustom = getDolGlobalString('MAIN_APPLICATION_TITLE');
674 if ($applicationcustom) {
675 $application = (preg_match('/^\+/', $applicationcustom) ? $application : '').$applicationcustom;
676 }
677
678 $from = getDolGlobalString('NOTIFICATION_EMAIL_FROM');
679 if (empty($from)) {
680 $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
681 }
682
683 $object_type = '';
684 $link = '';
685 $num = 0;
686 $error = 0;
687
688 $oldref = (empty($object->oldref) ? $object->ref : $object->oldref);
689 $newref = (empty($object->newref) ? $object->ref : $object->newref);
690
691 $sql = '';
692
693 // Check notification per third party @phan-suppress-next-line PhanUndeclaredProperty
694 if (!empty($object->socid) && $object->socid > 0) {
695 $sql .= "SELECT 'tocontactid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,";
696 $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type";
697 $sql .= " FROM ".$this->db->prefix()."socpeople as c,";
698 $sql .= " ".$this->db->prefix()."c_action_trigger as a,";
699 $sql .= " ".$this->db->prefix()."notify_def as n,";
700 $sql .= " ".$this->db->prefix()."societe as s";
701 $sql .= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action";
702 $sql .= " AND n.entity IN (".getEntity('notify_def').")";
703 $sql .= " AND n.fk_soc = s.rowid";
704 $sql .= " AND c.statut = 1";
705 if (is_numeric($notifcode)) {
706 $sql .= " AND n.fk_action = ".((int) $notifcode); // Old usage
707 } else {
708 $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
709 }
710 // @phan-suppress-next-line PhanUndeclaredProperty
711 $sql .= " AND s.rowid = ".((int) $object->socid);
712
713 $sql .= "\nUNION\n";
714 }
715
716 // Check notification per user
717 $sql .= "SELECT 'touserid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.lang as default_lang,";
718 $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type";
719 $sql .= " FROM ".$this->db->prefix()."user as c,";
720 $sql .= " ".$this->db->prefix()."c_action_trigger as a,";
721 $sql .= " ".$this->db->prefix()."notify_def as n";
722 $sql .= " WHERE n.fk_user = c.rowid AND a.rowid = n.fk_action";
723 $sql .= " AND n.entity IN (".getEntity('notify_def').")";
724 $sql .= " AND c.statut = 1";
725 if (is_numeric($notifcode)) {
726 $sql .= " AND n.fk_action = ".((int) $notifcode); // Old usage
727 } else {
728 $sql .= " AND a.code = '".$this->db->escape($notifcode)."'"; // New usage
729 }
730
731 // Check notification fixed
732 // TODO Move part found after, into a sql here
733
734
735 // Loop on all notifications enabled
736 $result = $this->db->query($sql);
737 if ($result) {
738 $num = $this->db->num_rows($result);
739 $projtitle = '';
740 if (is_object($object->project) || $object->fetchProject() > 0) {
741 $projtitle = '('.$object->project->title.')';
742 }
743
744 if ($num > 0) {
745 $i = 0;
746 while ($i < $num && !$error) { // For each notification couple defined (third party/actioncode)
747 $obj = $this->db->fetch_object($result);
748
749 $sendto = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
750 $notifcodedefid = $obj->adid;
751 $trackid = '';
752 if ($obj->type_target == 'tocontactid') {
753 $trackid = 'ctc'.$obj->cid;
754 }
755 if ($obj->type_target == 'touserid') {
756 $trackid = 'use'.$obj->cid;
757 }
758
759 if (dol_strlen($obj->email)) {
760 // Set output language
761 $outputlangs = $langs;
762 if ($obj->default_lang && $obj->default_lang != $langs->defaultlang) {
763 $outputlangs = new Translate('', $conf);
764 $outputlangs->setDefaultLang($obj->default_lang);
765 $outputlangs->loadLangs(array("main", "other"));
766 }
767
768 $appli = $mysoc->name;
769
770 $subject = '['.$appli.'] '.$outputlangs->transnoentitiesnoconv("DolibarrNotification").($projtitle ? ' '.$projtitle : '');
771
772 switch ($notifcode) {
773 case 'BILL_CANCEL':
774 $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
775 $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
776 $object_type = 'facture';
777 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoiceCanceled", $link);
778 break;
779 case 'BILL_VALIDATE':
780 $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
781 $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
782 $object_type = 'facture';
783 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
784 break;
785 case 'BILL_PAYED':
786 $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
787 $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
788 $object_type = 'facture';
789 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
790 break;
791 case 'ORDER_CANCEL':
792 $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
793 $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
794 $object_type = 'order';
795 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderCanceled", $link);
796 break;
797 case 'ORDER_VALIDATE':
798 $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
799 $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
800 $object_type = 'order';
801 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
802 break;
803 case 'ORDER_CLOSE':
804 $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
805 $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
806 $object_type = 'order';
807 $labeltouse = getDolGlobalString('ORDER_CLOSE_TEMPLATE');
808 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderClose", $link);
809 break;
810 case 'PROPAL_VALIDATE':
811 $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
812 $dir_output = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
813 $object_type = 'propal';
814 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
815 break;
816 case 'PROPAL_CLOSE_REFUSED':
817 $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
818 $dir_output = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
819 $object_type = 'propal';
820 $labeltouse = getDolGlobalString('PROPAL_CLOSE_REFUSED_TEMPLATE');
821 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedRefused", $link);
822 if (!empty($object->context['closedfromonlinesignature'])) {
823 $mesg .= ' - From online page';
824 }
825 break;
826 case 'PROPAL_CLOSE_SIGNED':
827 $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
828 $dir_output = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
829 $object_type = 'propal';
830 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
831 if (!empty($object->context['closedfromonlinesignature'])) {
832 $mesg .= ' - From online page';
833 }
834 break;
835 case 'FICHINTER_ADD_CONTACT':
836 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
837 $dir_output = $conf->ficheinter->dir_output;
838 $object_type = 'fichinter';
839 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
840 break;
841 case 'FICHINTER_VALIDATE':
842 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
843 $dir_output = $conf->ficheinter->dir_output;
844 $object_type = 'fichinter';
845 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
846 break;
847 case 'FICHINTER_MODIFY':
848 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
849 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
850 $dir_output = $conf->ficheinter->dir_output;
851 $object_type = 'fichinter';
852 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionModified", $link, $context_info);
853 break;
854 case 'FICHINTER_CLOSE':
855 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
856 $dir_output = $conf->ficheinter->dir_output;
857 $object_type = 'fichinter';
858 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionClosed", $link);
859 break;
860 case 'ORDER_SUPPLIER_VALIDATE':
861 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
862 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
863 $object_type = 'order_supplier';
864 $labeltouse = getDolGlobalString('ORDER_SUPPLIER_VALIDATE_TEMPLATE');
865 $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
866 $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderValidatedBy", $link, $user->getFullName($outputlangs));
867 $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
868 break;
869 case 'ORDER_SUPPLIER_CANCEL':
870 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
871 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
872 $object_type = 'order_supplier';
873 $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
874 $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderCanceledBy", $link, $user->getFullName($outputlangs));
875 $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
876 break;
877 case 'ORDER_SUPPLIER_APPROVE':
878 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
879 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
880 $object_type = 'order_supplier';
881 $labeltouse = getDolGlobalString('ORDER_SUPPLIER_APPROVE_TEMPLATE');
882 $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
883 $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderApprovedBy", $link, $user->getFullName($outputlangs));
884 $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
885 break;
886 case 'ORDER_SUPPLIER_SUBMIT':
887 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
888 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
889 $object_type = 'order_supplier';
890 $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
891 $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderSubmittedBy", $link, $user->getFullName($outputlangs));
892 $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
893 break;
894 case 'ORDER_SUPPLIER_REFUSE':
895 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
896 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
897 $object_type = 'order_supplier';
898 $labeltouse = getDolGlobalString('ORDER_SUPPLIER_REFUSE_TEMPLATE');
899 $mesg = $outputlangs->transnoentitiesnoconv("Hello").",\n\n";
900 $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderRefusedBy", $link, $user->getFullName($outputlangs));
901 $mesg .= "\n\n".$outputlangs->transnoentitiesnoconv("Sincerely").".\n\n";
902 break;
903 case 'SHIPPING_MODIFY':
904 $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
905 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
906 $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
907 $object_type = 'shipping';
908 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpeditionModified", $link, $context_info);
909 break;
910 case 'SHIPPING_VALIDATE':
911 $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
912 $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
913 $object_type = 'shipping';
914 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
915 break;
916 case 'EXPENSE_REPORT_VALIDATE':
917 $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
918 $dir_output = $conf->expensereport->dir_output;
919 $object_type = 'expensereport';
920 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
921 break;
922 case 'EXPENSE_REPORT_APPROVE':
923 $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
924 $dir_output = $conf->expensereport->dir_output;
925 $object_type = 'expensereport';
926 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
927 break;
928 case 'HOLIDAY_VALIDATE':
929 $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
930 $dir_output = $conf->holiday->dir_output;
931 $object_type = 'holiday';
932 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
933 break;
934 case 'HOLIDAY_APPROVE':
935 $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
936 $dir_output = $conf->holiday->dir_output;
937 $object_type = 'holiday';
938 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
939 break;
940 case 'ACTION_CREATE':
941 $link = '<a href="'.$urlwithroot.'/comm/action/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
942 $dir_output = $conf->agenda->dir_output;
943 $object_type = 'action';
944 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextActionAdded", $link);
945 break;
946 case 'CONTRACT_MODIFY':
947 $link = '<a href="'.$urlwithroot.'/contrat/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
948 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
949 $dir_output = rtrim(getMultidirOutput($object, '', 1), '/');
950 $object_type = 'contract';
951 $mesg = $outputlangs->transnoentitiesnoconv("EMailTextContractModified", $link, $context_info);
952 break;
953 default:
954 $object_type = $object->element;
955 $dir_output = $conf->$object_type->multidir_output[$object->entity ? $object->entity : $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, $object_type);
956 $template = $notifcode.'_TEMPLATE';
957 $mesg = $outputlangs->transnoentitiesnoconv('Notify_'.$notifcode).' '.$newref.' '.$dir_output;
958 break;
959 }
960
961 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
962 $formmail = new FormMail($this->db);
963 $arraydefaultmessage = null;
964
965 $template = $notifcode.'_TEMPLATE';
966 $labeltouse = getDolGlobalString($template);
967 if (!empty($labeltouse)) {
968 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $object_type, $user, $outputlangs, 0, 1, $labeltouse);
969 }
970 if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
971 if (method_exists($object, 'fetch_thirdparty') && empty($object->thirdparty)) {
972 $object->fetch_thirdparty();
973 }
974 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
975 complete_substitutions_array($substitutionarray, $outputlangs, $object);
976 // Note the substitution array should contains __REF__, __NEWREF__ ....
977 $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
978 $message = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
979 } else {
980 $message = $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name)."\n";
981 $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n";
982 $message .= "\n";
983 $message .= $mesg;
984 }
985
986 $ref = dol_sanitizeFileName($newref);
987 $pdf_path = $dir_output."/".$ref.".pdf";
988 if (!dol_is_file($pdf_path) || (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0 && !$arraydefaultmessage->joinfiles)) {
989 // We can't add PDF as it is not generated yet.
990 $filepdf = '';
991 } else {
992 $filepdf = $pdf_path;
993 $filename_list[] = $filepdf;
994 $mimetype_list[] = mime_content_type($filepdf);
995 $mimefilename_list[] = $ref.".pdf";
996 }
997
998 $labeltouse = !empty($labeltouse) ? $labeltouse : '';
999
1000 $sendto = $this->replaceSpecialRecipientToken($sendto, '__SUPERVISOREMAIL__', $this->getSupervisorEmail(1));
1001 $sendto = $this->replaceSpecialRecipientToken($sendto, '__AUTHOREMAIL__', $this->getAuthorEmail($object, 1));
1002
1003 $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'outputlangs' => $outputlangs, 'labeltouse' => $labeltouse);
1004 if (!isset($action)) {
1005 $action = '';
1006 }
1007
1008 $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1009 if (empty($reshook)) {
1010 if (!empty($hookmanager->resArray['files'])) {
1011 $filename_list = $hookmanager->resArray['files']['file'];
1012 $mimetype_list = $hookmanager->resArray['files']['mimefile'];
1013 $mimefilename_list = $hookmanager->resArray['files']['filename'];
1014 }
1015 if (!empty($hookmanager->resArray['subject'])) {
1016 $subject .= $hookmanager->resArray['subject'];
1017 }
1018 if (!empty($hookmanager->resArray['message'])) {
1019 $message .= $hookmanager->resArray['message'];
1020 }
1021 }
1022
1023 $mailfile = new CMailFile(
1024 $subject,
1025 $sendto,
1026 $from,
1027 $message,
1028 $filename_list,
1029 $mimetype_list,
1030 $mimefilename_list,
1031 '',
1032 '',
1033 0,
1034 -1,
1035 '',
1036 '',
1037 $trackid,
1038 '',
1039 'notification'
1040 );
1041
1042 if (! empty($mailfile->error) || ! empty($mailfile->errors)) {
1043 $this->error = $mailfile->error;
1044 $this->errors = $mailfile->errors;
1045 return -1;
1046 }
1047
1048 if ($mailfile->sendfile()) {
1049 if ($obj->type_target == 'touserid') {
1050 $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_user, type, objet_type, type_target, objet_id, email)";
1051 // @phan-suppress-next-line PhanUndeclaredProperty
1052 $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".($object->socid > 0 ? ((int) $object->socid) : 'null').", ".((int) $obj->cid).", '".$this->db->escape($obj->type)."', '".$this->db->escape($object_type)."', '".$this->db->escape($obj->type_target)."', ".((int) $object->id).", '".$this->db->escape($obj->email)."')";
1053 } else {
1054 $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, type_target, objet_id, email)";
1055 // @phan-suppress-next-line PhanUndeclaredProperty
1056 $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".($object->socid > 0 ? ((int) $object->socid) : 'null').", ".((int) $obj->cid).", '".$this->db->escape($obj->type)."', '".$this->db->escape($object_type)."', '".$this->db->escape($obj->type_target)."', ".((int) $object->id).", '".$this->db->escape($obj->email)."')";
1057 }
1058 if (!$this->db->query($sql)) {
1059 dol_print_error($this->db);
1060 }
1061 } else {
1062 $error++;
1063 $this->errors[] = $mailfile->error;
1064 }
1065 } else {
1066 dol_syslog("No notification sent for ".$sendto." because email is empty");
1067 }
1068 $i++;
1069 }
1070 } else {
1071 // @phan-suppress-next-line PhanUndeclaredProperty
1072 dol_syslog("No notification to thirdparty sent, nothing into notification setup for the thirdparty socid = ".(empty($object->socid) ? '' : $object->socid));
1073 }
1074 } else {
1075 $error++;
1076 $this->errors[] = $this->db->lasterror();
1077 dol_syslog("Failed to get list of notification to send ".$this->db->lasterror(), LOG_ERR);
1078 return -1;
1079 }
1080
1081 // Check notification using fixed email
1082 // TODO Move vars NOTIFICATION_FIXEDEMAIL into table llx_notify_def and include the case into previous loop of sql result
1083 if (!$error) {
1084 foreach ($conf->global as $key => $val) {
1085 $reg = array();
1086 if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_'.$notifcode.'_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
1087 continue;
1088 }
1089
1090 $sendto = $val;
1091
1092 $threshold = (float) $reg[1];
1093 if (!empty($object->total_ht) && $object->total_ht <= $threshold) {
1094 dol_syslog("A notification is requested for notifcode = ".$notifcode." but amount = ".$object->total_ht." so lower than threshold = ".$threshold.". We discard this notification");
1095 continue;
1096 }
1097
1098 $notifcodedefid = dol_getIdFromCode($this->db, $notifcode, 'c_action_trigger', 'code', 'rowid');
1099 if ($notifcodedefid <= 0) {
1100 dol_print_error($this->db, 'Failed to get id from code');
1101 }
1102 $trackid = '';
1103
1104 $object_type = '';
1105 $link = '';
1106 $num++;
1107
1108 $appli = $mysoc->name;
1109
1110 $subject = '['.$appli.'] '.$langs->transnoentitiesnoconv("DolibarrNotification").($projtitle ? ' '.$projtitle : '');
1111
1112 switch ($notifcode) {
1113 case 'BILL_VALIDATE':
1114 $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1115 $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
1116 $object_type = 'facture';
1117 $mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
1118 break;
1119 case 'BILL_PAYED':
1120 $link = '<a href="'.$urlwithroot.'/compta/facture/card.php?facid='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1121 $dir_output = $conf->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
1122 $object_type = 'facture';
1123 $mesg = $langs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
1124 break;
1125 case 'ORDER_VALIDATE':
1126 $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1127 $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
1128 $object_type = 'order';
1129 $mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
1130 break;
1131 case 'ORDER_CLOSE':
1132 $link = '<a href="'.$urlwithroot.'/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1133 $dir_output = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
1134 $object_type = 'order';
1135 $mesg = $langs->transnoentitiesnoconv("EMailTextOrderClose", $link);
1136 break;
1137 case 'PROPAL_VALIDATE':
1138 $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1139 $dir_output = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
1140 $object_type = 'propal';
1141 $mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
1142 break;
1143 case 'PROPAL_CLOSE_SIGNED':
1144 $link = '<a href="'.$urlwithroot.'/comm/propal/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1145 $dir_output = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
1146 $object_type = 'propal';
1147 $mesg = $langs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
1148 break;
1149 case 'FICHINTER_ADD_CONTACT':
1150 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1151 $dir_output = $conf->ficheinter->dir_output;
1152 $object_type = 'fichinter';
1153 $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
1154 break;
1155 case 'FICHINTER_VALIDATE':
1156 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1157 $dir_output = $conf->facture->dir_output;
1158 $object_type = 'fichinter';
1159 $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
1160 break;
1161 case 'FICHINTER_MODIFY':
1162 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1163 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
1164 $dir_output = $conf->ficheinter->dir_output;
1165 $object_type = 'fichinter';
1166 $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionModified", $link, $context_info);
1167 break;
1168 case 'FICHINTER_CLOSE':
1169 $link = '<a href="'.$urlwithroot.'/fichinter/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1170 $dir_output = $conf->facture->dir_output;
1171 $object_type = 'fichinter';
1172 $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionClosed", $link);
1173 break;
1174 case 'ORDER_SUPPLIER_CANCEL':
1175 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1176 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
1177 $object_type = 'order_supplier';
1178 $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
1179 $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderCanceledBy", $link, $user->getFullName($langs));
1180 $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
1181 break;
1182 case 'ORDER_SUPPLIER_VALIDATE':
1183 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1184 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
1185 $object_type = 'order_supplier';
1186 $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
1187 $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderValidatedBy", $link, $user->getFullName($langs));
1188 $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
1189 break;
1190 case 'ORDER_SUPPLIER_APPROVE':
1191 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1192 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
1193 $object_type = 'order_supplier';
1194 $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
1195 $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderApprovedBy", $link, $user->getFullName($langs));
1196 $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
1197 break;
1198 case 'ORDER_SUPPLIER_SUBMIT':
1199 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1200 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
1201 $object_type = 'order_supplier';
1202 $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
1203 $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderSubmittedBy", $link, $user->getFullName($langs));
1204 $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
1205 break;
1206 case 'ORDER_SUPPLIER_REFUSE':
1207 $link = '<a href="'.$urlwithroot.'/fourn/commande/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1208 $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object);
1209 $object_type = 'order_supplier';
1210 $mesg = $langs->transnoentitiesnoconv("Hello").",\n\n";
1211 $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderRefusedBy", $link, $user->getFullName($langs));
1212 $mesg .= "\n\n".$langs->transnoentitiesnoconv("Sincerely").".\n\n";
1213 break;
1214 case 'SHIPPING_MODIFY':
1215 $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1216 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
1217 $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
1218 $object_type = 'shipping';
1219 $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionModified", $link, $context_info);
1220 break;
1221 case 'SHIPPING_VALIDATE':
1222 $link = '<a href="'.$urlwithroot.'/expedition/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1223 $dir_output = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
1224 $object_type = 'shipping';
1225 $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
1226 break;
1227 case 'EXPENSE_REPORT_VALIDATE':
1228 $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1229 $dir_output = $conf->expensereport->dir_output;
1230 $object_type = 'expensereport';
1231 $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
1232 break;
1233 case 'EXPENSE_REPORT_APPROVE':
1234 $link = '<a href="'.$urlwithroot.'/expensereport/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1235 $dir_output = $conf->expensereport->dir_output;
1236 $object_type = 'expensereport';
1237 $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
1238 break;
1239 case 'HOLIDAY_VALIDATE':
1240 $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1241 $dir_output = $conf->holiday->dir_output;
1242 $object_type = 'holiday';
1243 $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
1244 break;
1245 case 'HOLIDAY_APPROVE':
1246 $link = '<a href="'.$urlwithroot.'/holiday/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1247 $dir_output = $conf->holiday->dir_output;
1248 $object_type = 'holiday';
1249 $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
1250 break;
1251 case 'ACTION_CREATE':
1252 $link = '<a href="'.$urlwithroot.'/comm/action/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1253 $dir_output = $conf->agenda->dir_output;
1254 $object_type = 'action';
1255 $mesg = $langs->transnoentitiesnoconv("EMailTextActionAdded", $link);
1256 break;
1257 case 'CONTRACT_MODIFY':
1258 $link = '<a href="'.$urlwithroot.'/contrat/card.php?id='.$object->id.'&entity='.$object->entity.'">'.$newref.'</a>';
1259 $context_info = array_key_exists('signature', $object->context) ? $object->getLibSignedStatus() : '';
1260 $dir_output = rtrim(getMultidirOutput($object, '', 1), '/');
1261 $object_type = 'contract';
1262 $mesg = $langs->transnoentitiesnoconv("EMailTextContractModified", $link, $context_info);
1263 break;
1264 default:
1265 $object_type = $object->element;
1266 $dir_output = $conf->$object_type->multidir_output[$object->entity ? $object->entity : $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, $object_type);
1267 $mesg = $langs->transnoentitiesnoconv('Notify_'.$notifcode).' '.$newref;
1268 break;
1269 }
1270 $ref = dol_sanitizeFileName($newref);
1271 $pdf_path = $dir_output."/".$ref.".pdf";
1272 if (!dol_is_file($pdf_path)) {
1273 // We can't add PDF as it is not generated yet.
1274 $filepdf = '';
1275 } else {
1276 $filepdf = $pdf_path;
1277 $filename_list[] = $pdf_path;
1278 $mimetype_list[] = mime_content_type($filepdf);
1279 $mimefilename_list[] = $ref.".pdf";
1280 }
1281
1282 // Set output language
1283 $outputlangs = $langs;
1284
1285 // if an e-mail template is configured for this notification code (for instance 'SHIPPING_VALIDATE_TEMPLATE', ...),
1286 // we fetch this template by its label. Otherwise, a default message content will be sent.
1287 $mailTemplateLabel = getDolGlobalString($notifcode.'_TEMPLATE');
1288 $emailTemplate = null;
1289 if (!empty($mailTemplateLabel)) {
1290 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
1291 $formmail = new FormMail($this->db);
1292 $emailTemplate = $formmail->getEMailTemplate($this->db, $object_type, $user, $outputlangs, 0, 1, $mailTemplateLabel);
1293 }
1294 if (!empty($mailTemplateLabel) && is_object($emailTemplate) && $emailTemplate->id > 0) {
1295 if (property_exists($object, 'thirdparty')) {
1296 if (!($object->thirdparty instanceof Societe)) {
1297 $object->fetch_thirdparty();
1298 }
1299
1300 if ($object->thirdparty instanceof Societe && $object->thirdparty->default_lang && $object->thirdparty->default_lang != $langs->defaultlang) {
1301 $outputlangs = new Translate('', $conf);
1302 $outputlangs->setDefaultLang($object->thirdparty->default_lang);
1303 $outputlangs->loadLangs(array('main', 'other'));
1304 }
1305 }
1306
1307 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
1308 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1309 $subject = make_substitutions($emailTemplate->topic, $substitutionarray, $outputlangs);
1310 $message = make_substitutions($emailTemplate->content, $substitutionarray, $outputlangs);
1311 } else {
1312 $message = '';
1313 $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name)."\n";
1314 $message .= "\n";
1315 $message .= $mesg;
1316
1317 $message = nl2br($message);
1318 }
1319
1320 $sendto = $this->replaceSpecialRecipientToken($sendto, '__SUPERVISOREMAIL__', $this->getSupervisorEmail(1));
1321 $sendto = $this->replaceSpecialRecipientToken($sendto, '__AUTHOREMAIL__', $this->getAuthorEmail($object, 1));
1322
1323 if ($sendto) {
1324 $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'subject' => &$subject, 'message' => &$message);
1325 $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1326 if (empty($reshook)) {
1327 if (!empty($hookmanager->resArray['files'])) {
1328 $filename_list = $hookmanager->resArray['files']['file'];
1329 $mimetype_list = $hookmanager->resArray['files']['mimefile'];
1330 $mimefilename_list = $hookmanager->resArray['files']['filename'];
1331 }
1332 if (!empty($hookmanager->resArray['subject'])) {
1333 $subject .= $hookmanager->resArray['subject'];
1334 }
1335 if (!empty($hookmanager->resArray['message'])) {
1336 $message .= $hookmanager->resArray['message'];
1337 }
1338 }
1339 $mailfile = new CMailFile(
1340 $subject,
1341 $sendto,
1342 $from,
1343 $message,
1344 $filename_list,
1345 $mimetype_list,
1346 $mimefilename_list,
1347 '',
1348 '',
1349 0,
1350 1,
1351 '',
1352 $trackid,
1353 '',
1354 '',
1355 'notification'
1356 );
1357
1358 if (! empty($mailfile->error) || ! empty($mailfile->errors)) {
1359 $this->error = $mailfile->error;
1360 $this->errors = $mailfile->errors;
1361 return -1;
1362 }
1363
1364 if ($mailfile->sendfile()) {
1365 $sql = "INSERT INTO ".$this->db->prefix()."notify (daten, fk_action, fk_soc, fk_contact, type, type_target, objet_type, objet_id, email)";
1366 // @phan-suppress-next-line PhanUndeclaredProperty
1367 $sql .= " VALUES ('".$this->db->idate(dol_now())."', ".((int) $notifcodedefid).", ".((!empty($object->socid) && $object->socid > 0) ? ((int) $object->socid) : 'null').", null, 'email', 'tofixedemail', '".$this->db->escape($object_type)."', ".((int) $object->id).", '".$this->db->escape($sendto)."')";
1368 if (!$this->db->query($sql)) {
1369 dol_print_error($this->db);
1370 }
1371 } else {
1372 $error++;
1373 $this->errors[] = $mailfile->error;
1374 }
1375 }
1376 }
1377 }
1378
1379 if (!$error) {
1380 return $num;
1381 } else {
1382 return -1 * $error;
1383 }
1384 }
1385
1392 private function getSupervisorEmail($withLabel = 0)
1393 {
1394 global $user;
1395
1396 if (empty($user->fk_user) || $user->fk_user <= 0) {
1397 return '';
1398 }
1399
1400 $supervisoruser = new User($this->db);
1401 $supervisoruser->fetch($user->fk_user);
1402 if (empty($supervisoruser->email)) {
1403 return '';
1404 }
1405
1406 if ($withLabel) {
1407 return trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname).' <'.$supervisoruser->email.'>');
1408 }
1409
1410 return trim((string) $supervisoruser->email);
1411 }
1412
1420 private function getAuthorEmail($object, $withLabel = 0)
1421 {
1422 if (!is_object($object)) {
1423 return '';
1424 }
1425
1426 $author = null;
1427
1428 // @phan-suppress-next-line PhanUndeclaredProperty
1429 if (isset($object->user_author) && is_object($object->user_author) && !empty($object->user_author->email)) {
1430 // @phan-suppress-next-line PhanUndeclaredProperty
1431 $author = $object->user_author;
1432 } else {
1433 $authorid = 0;
1434 foreach (array('fk_user_author', 'user_author_id', 'fk_user_creat') as $fieldname) {
1435 if (!empty($object->$fieldname)) {
1436 // @phan-suppress-next-line PhanUndeclaredProperty
1437 $authorid = (int) $object->$fieldname;
1438 break;
1439 }
1440 }
1441 if ($authorid > 0) {
1442 $author = new User($this->db);
1443 $author->fetch($authorid);
1444 }
1445 }
1446
1447 if (empty($author) || empty($author->email)) {
1448 return '';
1449 }
1450
1451 if ($withLabel) {
1452 return trim(dolGetFirstLastname($author->firstname, $author->lastname).' <'.$author->email.'>');
1453 }
1454
1455 return trim((string) $author->email);
1456 }
1457
1466 private function replaceSpecialRecipientToken($sendto, $token, $replacement)
1467 {
1468 if (!preg_match('/'.preg_quote($token, '/').'/', $sendto)) {
1469 return $sendto;
1470 }
1471
1472 dol_syslog("Replace the ".$token." key into recipient email string with ".$replacement);
1473 $sendto = preg_replace('/'.preg_quote($token, '/').'/', $replacement, $sendto);
1474 $sendto = preg_replace('/,\s*,/', ',', $sendto); // In some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email, , othermail" and it's not valid
1475 $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string
1476 $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string
1477
1478 return $sendto;
1479 }
1480}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
global $dolibarr_main_url_root
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Class to manage a HTML form to send a unitary email Usage: $formail = new FormMail($db) $formmail->pr...
Class to manage hooks.
Class to manage the table of subscription to notifications.
replaceSpecialRecipientToken($sendto, $token, $replacement)
Replace a special token inside recipient list.
fetch($id, $socid=0, $type='email')
Load record from database.
confirmMessage($action, $socid, $object)
Return message that say how many notification (and to which email) will occurs on requested event.
getNotificationsArray($notifcode, $socid=0, $object=null, $userid=0, $scope=array('thirdparty', 'user', 'global'))
Return number of notifications activated, for all or a given action code (and third party)
getSupervisorEmail($withLabel=0)
Return supervisor email.
getAuthorEmail($object, $withLabel=0)
Return author email of object.
send($notifcode, $object, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array())
Check if notification are active for couple action/company.
update($user=null, $notrigger=0)
Update record in database.
create($user=null, $notrigger=0)
Create notification information record.
__construct($db)
Constructor.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
global $mysoc
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as p label as s rowid as s nom as s email
Sender: Who sends the email ("Sender" has sent emails on behalf of "From").
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_is_file($pathoffile)
Return if path is a file.
dol_now($mode='gmt')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.