dolibarr 22.0.5
html.formmail.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2015-2017 Marcos García <marcosgdf@gmail.com>
6 * Copyright (C) 2015-2017 Nicolas ZABOURI <info@inovea-conseil.com>
7 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
9 * Copyright (C) 2023 Anthony Berton <anthony.berton@bb2a.fr>
10 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
11 *
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
32require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
33
34
41class FormMail extends Form
42{
46 public $db;
47
53 public $withform;
54
58 public $fromname;
59
63 public $frommail;
64
68 public $fromtype;
69
73 public $fromid;
74
78 public $fromalsorobot;
79
83 public $totype;
84
88 public $toid;
89
93 public $replytoname;
94
98 public $replytomail;
99
103 public $toname;
104
108 public $tomail;
109
113 public $trackid;
114
118 public $inreplyto;
119
123 public $withsubstit; // Show substitution array
127 public $withfrom;
128
132 public $withto; // Show recipient emails
136 public $withreplyto;
137
143 public $withtofree;
147 public $withtocc;
151 public $withtoccc;
155 public $withtopic;
159 public $witherrorsto;
160
164 public $withfile;
165
169 public $withlayout;
170
174 public $withaiprompt;
175
179 public $withmaindocfile;
183 public $withbody;
184
188 public $withfromreadonly;
192 public $withreplytoreadonly;
196 public $withtoreadonly;
200 public $withtoccreadonly;
204 public $witherrorstoreadonly;
208 public $withtocccreadonly;
212 public $withtopicreadonly;
216 public $withbodyreadonly;
220 public $withfilereadonly;
224 public $withdeliveryreceipt;
228 public $withcancel;
232 public $withdeliveryreceiptreadonly;
236 public $withfckeditor;
237
241 public $ckeditortoolbar;
242
246 public $substit = array();
247
251 public $substit_lines = array();
252
256 public $param = array();
257
261 public $withtouser = array();
265 public $withtoccuser = array();
266
270 public $lines_model;
271
275 public $withoptiononeemailperrecipient;
276
277
283 public function __construct($db)
284 {
285 $this->db = $db;
286
287 $this->withform = 1;
288
289 $this->withfrom = 1;
290 $this->withto = 1;
291 $this->withtofree = 1;
292 $this->withtocc = 1;
293 $this->withtoccc = '0';
294 $this->witherrorsto = 0;
295 $this->withtopic = 1;
296 $this->withfile = 0; // 1=Add section "Attached files". 2=Can add files.
297 $this->withmaindocfile = 0; // 1=Add a checkbox "Attach also main document" for mass actions (checked by default), -1=Add checkbox (not checked by default)
298 $this->withbody = 1;
299
300 $this->withfromreadonly = 1;
301 $this->withreplytoreadonly = 1;
302 $this->withtoreadonly = 0;
303 $this->withtoccreadonly = 0;
304 $this->withtocccreadonly = 0;
305 $this->witherrorstoreadonly = 0;
306 $this->withtopicreadonly = 0;
307 $this->withfilereadonly = 0;
308 $this->withbodyreadonly = 0;
309 $this->withdeliveryreceiptreadonly = 0;
310 $this->withfckeditor = -1; // -1 = Auto
311 }
312
313 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
319 public function clear_attached_files()
320 {
321 // phpcs:enable
322 global $conf, $user;
323 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
324
325 // Set tmp user directory
326 $vardir = $conf->user->dir_output."/".$user->id;
327 $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
328 if (is_dir($upload_dir)) {
329 dol_delete_dir_recursive($upload_dir);
330 }
331
332 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
333 unset($_SESSION["listofpaths".$keytoavoidconflict]);
334 unset($_SESSION["listofnames".$keytoavoidconflict]);
335 unset($_SESSION["listofmimes".$keytoavoidconflict]);
336 }
337
338 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
347 public function add_attached_files($path, $file = '', $type = '')
348 {
349 // phpcs:enable
350 $listofpaths = array();
351 $listofnames = array();
352 $listofmimes = array();
353
354 if (empty($file)) {
355 $file = basename($path);
356 }
357 if (empty($type)) {
358 $type = dol_mimetype($file);
359 }
360
361 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
362 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
363 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
364 }
365 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
366 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
367 }
368 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
369 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
370 }
371 if (!in_array($file, $listofnames)) {
372 $listofpaths[] = $path;
373 $listofnames[] = $file;
374 $listofmimes[] = $type;
375 $_SESSION["listofpaths".$keytoavoidconflict] = implode(';', $listofpaths);
376 $_SESSION["listofnames".$keytoavoidconflict] = implode(';', $listofnames);
377 $_SESSION["listofmimes".$keytoavoidconflict] = implode(';', $listofmimes);
378 }
379 }
380
381 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
388 public function remove_attached_files($keytodelete)
389 {
390 // phpcs:enable
391 $listofpaths = array();
392 $listofnames = array();
393 $listofmimes = array();
394
395 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
396 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
397 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
398 }
399 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
400 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
401 }
402 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
403 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
404 }
405 if ($keytodelete >= 0) {
406 unset($listofpaths[$keytodelete]);
407 unset($listofnames[$keytodelete]);
408 unset($listofmimes[$keytodelete]);
409 $_SESSION["listofpaths".$keytoavoidconflict] = implode(';', $listofpaths);
410 $_SESSION["listofnames".$keytoavoidconflict] = implode(';', $listofnames);
411 $_SESSION["listofmimes".$keytoavoidconflict] = implode(';', $listofmimes);
412 //var_dump($_SESSION['listofpaths']);
413 }
414 }
415
416 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
422 public function get_attached_files()
423 {
424 // phpcs:enable
425 $listofpaths = array();
426 $listofnames = array();
427 $listofmimes = array();
428
429 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
430 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
431 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
432 }
433 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
434 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
435 }
436 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
437 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
438 }
439 return array('paths' => $listofpaths, 'names' => $listofnames, 'mimes' => $listofmimes);
440 }
441
442 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
453 public function show_form($addfileaction = 'addfile', $removefileaction = 'removefile')
454 {
455 // phpcs:enable
456 print $this->get_form($addfileaction, $removefileaction);
457 }
458
459 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
470 public function get_form($addfileaction = 'addfile', $removefileaction = 'removefile')
471 {
472 // phpcs:enable
473 global $conf, $langs, $user, $hookmanager, $form;
474
475 if (!is_object($form)) {
476 $form = new Form($this->db);
477 }
478
479 // Required to show editor assistants
480 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
481 $formfile = new FormFile($this->db);
482
483 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formai.class.php';
484 $formai = new FormAI($this->db);
485
486 // Load translation files required by the page
487 $langs->loadLangs(array('other', 'mails', 'members'));
488
489 // Clear temp files. Must be done before call of triggers, at beginning (mode = init), or when we select a new template
490 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
491 $this->clear_attached_files();
492 }
493
494 // Call hook getFormMail
495 $hookmanager->initHooks(array('formmail'));
496
497 $parameters = array(
498 'addfileaction' => $addfileaction,
499 'removefileaction' => $removefileaction,
500 'trackid' => $this->trackid
501 );
502 $reshook = $hookmanager->executeHooks('getFormMail', $parameters, $this);
503
504 if (!empty($reshook)) {
505 return $hookmanager->resPrint;
506 } else {
507 $out = '';
508
509 $disablebademails = 1;
510
511 // Define output language
512 $outputlangs = $langs;
513 $newlang = '';
514 if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($this->param['langsmodels'])) {
515 $newlang = $this->param['langsmodels'];
516 }
517 if (!empty($newlang)) {
518 $outputlangs = new Translate("", $conf);
519 $outputlangs->setDefaultLang($newlang);
520 $outputlangs->load('other');
521 }
522
523 // Get message template for $this->param["models"] into c_email_templates
524 $arraydefaultmessage = -1;
525 if ($this->param['models'] != 'none') {
526 $model_id = 0;
527 if (array_key_exists('models_id', $this->param)) {
528 $model_id = $this->param["models_id"];
529 }
530
531 $arraydefaultmessage = $this->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id, 1, '', ($model_id > 0 ? -1 : 1)); // If $model_id is empty, preselect the first one
532 }
533
534 // Define list of attached files
535 $listofpaths = array();
536 $listofnames = array();
537 $listofmimes = array();
538 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
539
540 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
541 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
542 foreach ($this->param['fileinit'] as $path) {
543 if (!empty($path)) {
544 $this->add_attached_files($path);
545 }
546 }
547 }
548 }
549
550 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
551 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
552 }
553 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
554 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
555 }
556 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
557 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
558 }
559
560
561 $out .= "\n".'<!-- Begin form mail type='.$this->param["models"].' --><div id="mailformdiv"></div>'."\n";
562 if ($this->withform == 1) {
563 $out .= '<form method="POST" name="mailform" id="mailform" enctype="multipart/form-data" action="'.$this->param["returnurl"].'#formmail">'."\n";
564
565 $out .= '<a id="formmail" name="formmail"></a>';
566 $out .= '<input style="display:none" type="submit" id="sendmailhidden" name="sendmail">';
567 $out .= '<input type="hidden" name="token" value="'.newToken().'" />';
568 $out .= '<input type="hidden" name="trackid" value="'.$this->trackid.'" />';
569 $out .= '<input type="hidden" name="inreplyto" value="'.$this->inreplyto.'" />';
570 }
571 if (!empty($this->withfrom)) {
572 if (!empty($this->withfromreadonly)) {
573 $out .= '<input type="hidden" id="fromname" name="fromname" value="'.$this->fromname.'" />';
574 $out .= '<input type="hidden" id="frommail" name="frommail" value="'.$this->frommail.'" />';
575 }
576 }
577 foreach ($this->param as $key => $value) {
578 if (is_array($value)) {
579 $out .= "<!-- param key=".$key." is array, we do not output input field for it -->\n";
580 } else {
581 $out .= '<input type="hidden" id="'.$key.'" name="'.$key.'" value="'.$value.'" />'."\n";
582 }
583 }
584
585 $modelmail_array = array();
586 if ($this->param['models'] != 'none') {
587 $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
588 if ($result < 0) {
589 setEventMessages($this->error, $this->errors, 'errors');
590 }
591
592 foreach ($this->lines_model as $line) {
593 $reg = array();
594 if (preg_match('/\‍((.*)\‍)/', $line->label, $reg)) {
595 $labeltouse = $langs->trans($reg[1]); // langs->trans when label is __(xxx)__
596 } else {
597 $labeltouse = $line->label;
598 }
599
600 // We escape the $labeltouse to store it into $modelmail_array.
601 $modelmail_array[$line->id] = dol_escape_htmltag($labeltouse);
602 if ($line->lang) {
603 $modelmail_array[$line->id] .= ' '.picto_from_langcode($line->lang);
604 }
605 if ($line->private) {
606 $modelmail_array[$line->id] .= ' - <span class="opacitymedium">'.dol_escape_htmltag($langs->trans("Private")).'</span>';
607 }
608 }
609 }
610
611 // Zone to select email template
612 if (count($modelmail_array) > 0) {
613 $model_mail_selected_id = GETPOSTISSET('modelmailselected') ? GETPOSTINT('modelmailselected') : ($arraydefaultmessage->id > 0 ? $arraydefaultmessage->id : 0);
614
615 // If list of template is filled
616 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
617
618 $out .= $this->selectarray('modelmailselected', $modelmail_array, $model_mail_selected_id, $langs->trans('SelectMailModel'), 0, 0, '', 0, 0, 0, '', 'minwidth100', 1, '', 0, 1);
619 if ($user->admin) {
620 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
621 }
622
623 $out .= ' &nbsp; ';
624 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
625 $out .= ' &nbsp; ';
626 $out .= '</div>';
627 } elseif (!empty($this->param['models']) && in_array($this->param['models'], array(
628 'propal_send', 'order_send', 'facture_send',
629 'shipping_send', 'fichinter_send', 'supplier_proposal_send', 'order_supplier_send',
630 'invoice_supplier_send', 'thirdparty', 'contract', 'user', 'recruitmentcandidature_send', 'product_send', 'all'
631 ))) {
632 // If list of template is empty
633 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
634 $out .= '<span class="opacitymedium">'.$langs->trans('SelectMailModel').':</span> ';
635 $out .= '<select name="modelmailselected" disabled="disabled"><option value="none">'.$langs->trans("NoTemplateDefined").'</option></select>'; // Do not put 'disabled' on 'option' tag, it is already on 'select' and it makes chrome crazy.
636 if ($user->admin) {
637 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
638 }
639 $out .= ' &nbsp; ';
640 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" disabled="disabled" id="modelselected">';
641 $out .= ' &nbsp; ';
642 $out .= '</div>';
643 } else {
644 $out .= '<!-- No template available for $this->param["models"] = '.$this->param['models'].' -->';
645 }
646
647
648 $out .= '<table class="tableforemailform boxtablenotop centpercent">'."\n";
649
650 // Substitution array/string
651 $helpforsubstitution = '';
652 if (is_array($this->substit) && count($this->substit)) {
653 $helpforsubstitution .= $langs->trans('AvailableVariables').' :<br><br><span class="small">'."\n";
654 }
655 foreach ($this->substit as $key => $val) {
656 // Do not show deprecated variables into the tooltip help of substitution variables
657 if (in_array($key, array('__NEWREF__', '__REFCLIENT__', '__REFSUPPLIER__', '__SUPPLIER_ORDER_DATE_DELIVERY__', '__SUPPLIER_ORDER_DELAY_DELIVERY__'))) {
658 continue;
659 }
660 $helpforsubstitution .= $key.' -> '.$langs->trans(dol_string_nohtmltag(dolGetFirstLineOfText((string) $val))).'<br>';
661 }
662 if (is_array($this->substit) && count($this->substit)) {
663 $helpforsubstitution .= '</span>';
664 }
665
666 /*
667 if (!empty($this->withsubstit)) { // Unset or set ->withsubstit=0 to disable this.
668 $out .= '<tr><td colspan="2" class="right">';
669 if (is_numeric($this->withsubstit)) {
670 $out .= $form->textwithpicto($langs->trans("EMailTestSubstitutionReplacedByGenericValues"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // Old usage
671 } else {
672 $out .= $form->textwithpicto($langs->trans('AvailableVariables'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // New usage
673 }
674 $out .= "</td></tr>\n";
675 }*/
676
677 // From
678 if (!empty($this->withfrom)) {
679 if (!empty($this->withfromreadonly)) {
680 $out .= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
681
682 // $this->fromtype is the default value to use to select sender
683 if (!($this->fromtype === 'user' && $this->fromid > 0)
684 && !($this->fromtype === 'company')
685 && !($this->fromtype === 'robot')
686 && !preg_match('/user_aliases/', $this->fromtype)
687 && !preg_match('/global_aliases/', $this->fromtype)
688 && !preg_match('/senderprofile/', $this->fromtype)
689 ) {
690 // Use this->fromname and this->frommail or error if not defined
691 $out .= $this->fromname;
692 if ($this->frommail) {
693 $out .= ' &lt;'.$this->frommail.'&gt;';
694 } else {
695 if ($this->fromtype) {
696 $langs->load('errors');
697 $out .= '<span class="warning"> &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt; </span>';
698 }
699 }
700 } else {
701 $liste = array();
702
703 // Add user email
704 if (empty($user->email)) {
705 $langs->load('errors');
706 $s = $user->getFullName($langs).' &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt;';
707 } else {
708 $s = $user->getFullName($langs).' &lt;'.$user->email.'&gt;';
709 }
710 $liste['user'] = array('label' => $s, 'data-html' => $s);
711
712 // Add also company main email
713 if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
714 $s = (!getDolGlobalString('MAIN_INFO_SOCIETE_NOM') ? $conf->global->MAIN_INFO_SOCIETE_EMAIL : $conf->global->MAIN_INFO_SOCIETE_NOM).' &lt;' . getDolGlobalString('MAIN_INFO_SOCIETE_MAIL').'&gt;';
715 $liste['company'] = array('label' => $s, 'data-html' => $s);
716 }
717
718 // Add also email aliases if there is some
719 $listaliases = array(
720 'user_aliases' => (empty($user->email_aliases) ? '' : $user->email_aliases),
721 'global_aliases' => getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES'),
722 );
723
724 if (!empty($arraydefaultmessage->email_from)) {
725 $templatemailfrom = ' &lt;'.$arraydefaultmessage->email_from.'&gt;';
726 $liste['from_template_'.$arraydefaultmessage->id] = array('label' => $templatemailfrom, 'data-html' => $templatemailfrom);
727 }
728
729 // Also add robot email
730 if (!empty($this->fromalsorobot)) {
731 if (getDolGlobalString('MAIN_MAIL_EMAIL_FROM') && getDolGlobalString('MAIN_MAIL_EMAIL_FROM') != getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
732 $s = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
733 if ($this->frommail) {
734 $s .= ' &lt;' . getDolGlobalString('MAIN_MAIL_EMAIL_FROM').'&gt;';
735 }
736 $liste['main_from'] = array('label' => $s, 'data-html' => $s);
737 }
738 }
739
740 // Add also email aliases from the c_email_senderprofile table
741 $sql = "SELECT rowid, label, email FROM ".$this->db->prefix()."c_email_senderprofile";
742 $sql .= " WHERE active = 1 AND (private = 0 OR private = ".((int) $user->id).") AND entity IN (".getEntity('c_email_senderprofile').")";
743 $sql .= " ORDER BY position";
744 $resql = $this->db->query($sql);
745 if ($resql) {
746 $num = $this->db->num_rows($resql);
747 $i = 0;
748 while ($i < $num) {
749 $obj = $this->db->fetch_object($resql);
750 if ($obj) {
751 $listaliases['senderprofile_'.$obj->rowid] = $obj->label.' <'.$obj->email.'>';
752 }
753 $i++;
754 }
755 } else {
756 dol_print_error($this->db);
757 }
758
759 foreach ($listaliases as $typealias => $listalias) {
760 $posalias = 0;
761 $listaliasarray = explode(',', $listalias);
762 foreach ($listaliasarray as $listaliasval) {
763 $posalias++;
764 $listaliasval = trim($listaliasval);
765 if ($listaliasval) {
766 $listaliasval = preg_replace('/</', '&lt;', $listaliasval);
767 $listaliasval = preg_replace('/>/', '&gt;', $listaliasval);
768 if (!preg_match('/&lt;/', $listaliasval)) {
769 $listaliasval = '&lt;'.$listaliasval.'&gt;';
770 }
771 $liste[$typealias.'_'.$posalias] = array('label' => $listaliasval, 'data-html' => $listaliasval);
772 }
773 }
774 }
775
776 // Using ajaxcombo here make the '<email>' no more visible on list because <emailofuser> is not a valid html tag,
777 // so we transform before each record into $liste to be printable with ajaxcombo by replacing <> into ()
778 // $liste['senderprofile_0_0'] = array('label'=>'rrr', 'data-html'=>'rrr &lt;aaaa&gt;');
779 foreach ($liste as $key => $val) {
780 if (!empty($liste[$key]['data-html'])) {
781 $liste[$key]['data-html'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $liste[$key]['data-html']);
782 $liste[$key]['data-html'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $liste[$key]['data-html']);
783 }
784 }
785 $out .= ' '.$form->selectarray('fromtype', $liste, empty($arraydefaultmessage->email_from) ? $this->fromtype : 'from_template_'.$arraydefaultmessage->id, 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 1, '', $disablebademails);
786 }
787
788 $out .= "</td></tr>\n";
789 } else {
790 $out .= '<tr><td class="fieldrequired width200">'.$langs->trans("MailFrom")."</td><td>";
791 $out .= $langs->trans("Name").':<input type="text" id="fromname" name="fromname" class="maxwidth200onsmartphone" value="'.$this->fromname.'" />';
792 $out .= '&nbsp; &nbsp; ';
793 $out .= $langs->trans("EMail").':&lt;<input type="text" id="frommail" name="frommail" class="maxwidth200onsmartphone" value="'.$this->frommail.'" />&gt;';
794 $out .= "</td></tr>\n";
795 }
796 }
797
798 // To
799 if (!empty($this->withto) || is_array($this->withto)) {
800 $out .= $this->getHtmlForTo();
801 }
802
803 // To User
804 if (!empty($this->withtouser) && is_array($this->withtouser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
805 $out .= '<tr><td>';
806 $out .= $langs->trans("MailToUsers");
807 $out .= '</td><td>';
808
809 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
810 $tmparray = $this->withtouser;
811 foreach ($tmparray as $key => $val) {
812 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
813 }
814 $withtoselected = GETPOST("receiveruser", 'array'); // Array of selected value
815 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
816 $withtoselected = array_keys($tmparray);
817 }
818 $out .= $form->multiselectarray("receiveruser", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, "");
819 $out .= "</td></tr>\n";
820 }
821
822 // With option for one email per recipient
823 if (!empty($this->withoptiononeemailperrecipient)) {
824 if (abs($this->withoptiononeemailperrecipient) == 1) {
825 $out .= '<tr><td class="minwidth200">';
826 $out .= $langs->trans("GroupEmails");
827 $out .= '</td><td>';
828 $out .= ' <input type="checkbox" id="oneemailperrecipient" value="1" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> ';
829 $out .= '<label for="oneemailperrecipient">';
830 $out .= $form->textwithpicto($langs->trans("OneEmailPerRecipient"), $langs->trans("WarningIfYouCheckOneRecipientPerEmail"), 1, 'help');
831 $out .= '</label>';
832 //$out .= '<span class="hideonsmartphone opacitymedium">';
833 //$out .= ' - ';
834 //$out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
835 //$out .= '</span>';
836 if (getDolGlobalString('MASS_ACTION_EMAIL_ON_DIFFERENT_THIRPARTIES_ADD_CUSTOM_EMAIL')) {
837 if (!empty($this->withto) && !is_array($this->withto)) {
838 $out .= ' '.$langs->trans("or").' <input type="email" name="emailto" value="">';
839 }
840 }
841 $out .= '</td></tr>';
842 } else {
843 $out .= '<tr><td><input type="hidden" name="oneemailperrecipient" value="1"></td><td></td></tr>';
844 }
845 }
846
847 // CC
848 if (!empty($this->withtocc) || is_array($this->withtocc)) {
849 $out .= $this->getHtmlForCc();
850 }
851
852 // To User cc
853 if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
854 $out .= '<tr><td>';
855 $out .= $langs->trans("MailToCCUsers");
856 $out .= '</td><td>';
857
858 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
859 $tmparray = $this->withtoccuser;
860 foreach ($tmparray as $key => $val) {
861 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
862 }
863 $withtoselected = GETPOST("receiverccuser", 'array'); // Array of selected value
864 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
865 $withtoselected = array_keys($tmparray);
866 }
867 $out .= $form->multiselectarray("receiverccuser", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, "");
868 $out .= "</td></tr>\n";
869 }
870
871 // CCC
872 if (!empty($this->withtoccc) || is_array($this->withtoccc)) {
873 $out .= $this->getHtmlForWithCcc();
874 }
875
876 // Replyto
877 if (!empty($this->withreplyto)) {
878 if ($this->withreplytoreadonly) {
879 $out .= '<input type="hidden" id="replyname" name="replyname" value="'.$this->replytoname.'" />';
880 $out .= '<input type="hidden" id="replymail" name="replymail" value="'.$this->replytomail.'" />';
881 $out .= "<tr><td>".$langs->trans("MailReply")."</td><td>".$this->replytoname.($this->replytomail ? (" &lt;".$this->replytomail."&gt;") : "");
882 $out .= "</td></tr>\n";
883 }
884 }
885
886 // Errorsto
887 if (!empty($this->witherrorsto)) {
888 $out .= $this->getHtmlForWithErrorsTo();
889 }
890
891 // Ask delivery receipt
892 if (!empty($this->withdeliveryreceipt) && getDolGlobalInt('MAIN_EMAIL_SUPPORT_ACK')) {
893 $out .= $this->getHtmlForDeliveryreceipt();
894 }
895
896 // Topic
897 if (!empty($this->withtopic)) {
898 $out .= $this->getHtmlForTopic($arraydefaultmessage, $helpforsubstitution);
899 }
900
901 // Attached files
902 if (!empty($this->withfile)) {
903 $out .= '<tr>';
904 $out .= '<td class="tdtop">'.$langs->trans("MailFile").'</td>';
905
906 $out .= '<td>';
907
908 if ($this->withmaindocfile) {
909 // withmaindocfile is set to 1 or -1 to show the checkbox (-1 = checked or 1 = not checked)
910 if (GETPOSTISSET('sendmail')) {
911 $this->withmaindocfile = (GETPOST('addmaindocfile', 'alpha') ? -1 : 1);
912 } elseif (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
913 // If a template was selected, we use setup of template to define if join file checkbox is selected or not.
914 $this->withmaindocfile = ($arraydefaultmessage->joinfiles ? -1 : 1);
915 }
916 }
917
918 if (!empty($this->withmaindocfile)) {
919 if ($this->withmaindocfile == 1) {
920 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" />';
921 } elseif ($this->withmaindocfile == -1) {
922 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" checked="checked" />';
923 }
924 if (getDolGlobalString('MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND')) {
925 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDocOrLastGenerated").'.</label><br>';
926 } else {
927 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDoc").'.</label><br>';
928 }
929 }
930
931 if (is_numeric($this->withfile)) {
932 // TODO Trick to have param removedfile containing nb of file to delete. But this does not works without javascript
933 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
934 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
935 $out .= 'jQuery(document).ready(function () {';
936 $out .= ' jQuery(".removedfile").click(function() {';
937 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
938 $out .= ' });';
939 $out .= '})';
940 $out .= '</script>'."\n";
941 if (count($listofpaths)) {
942 foreach ($listofpaths as $key => $val) {
943 $relativepathtofile = substr($val, (strlen(DOL_DATA_ROOT) - strlen($val)));
944
945 $entity = (isset($this->param['object_entity']) ? $this->param['object_entity'] : $conf->entity);
946 if ($entity > 1) {
947 $relativepathtofile = str_replace('/'.$entity.'/', '/', $relativepathtofile);
948 }
949 // Try to extract data from full path
950 $formfile_params = array();
951 preg_match('#^(/)(\w+)(/)(.+)$#', $relativepathtofile, $formfile_params);
952
953 $out .= '<div id="attachfile_'.$key.'">';
954 // Preview of attachment
955 $out .= img_mime($listofnames[$key]).$listofnames[$key];
956
957 $out .= ' '.$formfile->showPreview(array(), $formfile_params[2], $formfile_params[4], 0, ($entity == 1 ? '' : 'entity='.((int) $entity)));
958
959 if (!$this->withfilereadonly) {
960 $out .= ' <input type="image" style="border: 0px;" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/delete.png" value="'.($key + 1).'" class="removedfile input-nobottom" id="removedfile_'.$key.'" name="removedfile_'.$key.'" />';
961 //$out.= ' <a href="'.$_SERVER["PHP_SELF"].'?removedfile='.($key+1).'&id=removedfile_'.$key.'">'.img_delete($langs->trans("Remove"), 'id="removedfile_'.$key.'" name="removedfile_'.$key.'"', 'removedfile input-nobottom').'</a>';
962 }
963 $out .= '<br></div>';
964 }
965 } /*elseif (empty($this->withmaindocfile)) {
966 //$out .= '<span class="opacitymedium">'.$langs->trans("NoAttachedFiles").'</span><br>';
967 }*/
968 if ($this->withfile == 2) {
969 $maxfilesizearray = getMaxFileSizeArray();
970 $maxmin = $maxfilesizearray['maxmin'];
971 if ($maxmin > 0) {
972 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
973 }
974 // Can add other files
975 if (!getDolGlobalString('FROM_MAIL_DONT_USE_INPUT_FILE_MULTIPLE')) {
976 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile[]" value="'.$langs->trans("Upload").'" multiple />';
977 } else {
978 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
979 }
980 $out .= ' ';
981 $out .= '<input type="submit" class="button smallpaddingimp" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
982 }
983 } else {
984 $out .= $this->withfile;
985 }
986
987 $out .= "</td></tr>\n";
988 }
989
990 // Message (+ Links to choose layout or ai prompt)
991 if (!empty($this->withbody)) {
992 $defaultmessage = GETPOST('message', 'restricthtml');
993 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
994 if ($arraydefaultmessage && $arraydefaultmessage->content) {
995 $defaultmessage = (string) $arraydefaultmessage->content;
996 } elseif (!is_numeric($this->withbody)) {
997 $defaultmessage = $this->withbody;
998 }
999 }
1000
1001 // Complete substitution array with the url to make online payment
1002 $paymenturl = '';
1003 // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
1004 require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
1005 $validpaymentmethod = getValidOnlinePaymentMethods('');
1006
1007 if (empty($this->substit['__REF__'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
1008 $paymenturl = '';
1009 } else {
1010 $langs->loadLangs(array('paypal', 'other'));
1011 $typeforonlinepayment = 'free';
1012 if ($this->param["models"] == 'order' || $this->param["models"] == 'order_send') {
1013 $typeforonlinepayment = 'order'; // TODO use detection on something else than template
1014 }
1015 if ($this->param["models"] == 'invoice' || $this->param["models"] == 'facture_send') {
1016 $typeforonlinepayment = 'invoice'; // TODO use detection on something else than template
1017 }
1018 if ($this->param["models"] == 'member') {
1019 $typeforonlinepayment = 'member'; // TODO use detection on something else than template
1020 }
1021 $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']);
1022 $paymenturl = $url;
1023 }
1024
1025 if (count($validpaymentmethod) > 0 && $paymenturl) {
1026 $langs->load('other');
1027 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = str_replace('\n', "\n", $langs->transnoentities("PredefinedMailContentLink", $paymenturl));
1028 $this->substit['__ONLINE_PAYMENT_URL__'] = $paymenturl;
1029 } elseif (count($validpaymentmethod) > 0) {
1030 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = '__ONLINE_PAYMENT_TEXT_AND_URL__';
1031 $this->substit['__ONLINE_PAYMENT_URL__'] = '__ONLINE_PAYMENT_URL__';
1032 } else {
1033 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = '';
1034 $this->substit['__ONLINE_PAYMENT_URL__'] = '';
1035 }
1036
1037 $this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'] = '';
1038
1039 // Generate the string with the template for lines repeated and filled for each line
1040 $lines = '';
1041 $defaultlines = $arraydefaultmessage->content_lines;
1042 if (isset($defaultlines)) {
1043 foreach ($this->substit_lines as $lineid => $substit_line) {
1044 $lines .= make_substitutions($defaultlines, $substit_line)."\n";
1045 }
1046 }
1047 $this->substit['__LINES__'] = $lines;
1048
1049 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1050
1051 // Deal with format differences between message and some substitution variables (text / HTML)
1052 $atleastonecomponentishtml = 0;
1053 if (strpos($defaultmessage, '__USER_SIGNATURE__') !== false && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1054 $atleastonecomponentishtml++;
1055 }
1056 if (strpos($defaultmessage, '__SENDEREMAIL_SIGNATURE__') !== false && dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
1057 $atleastonecomponentishtml++;
1058 }
1059 if (strpos($defaultmessage, '__ONLINE_PAYMENT_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
1060 $atleastonecomponentishtml++;
1061 }
1062 if (strpos($defaultmessage, '__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'])) {
1063 $atleastonecomponentishtml++;
1064 }
1065 if (dol_textishtml($defaultmessage)) {
1066 $atleastonecomponentishtml++;
1067 }
1068 if ($atleastonecomponentishtml) {
1069 if (!dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1070 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1071 }
1072 if (!dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
1073 $this->substit['__SENDEREMAIL_SIGNATURE__'] = dol_nl2br($this->substit['__SENDEREMAIL_SIGNATURE__']);
1074 }
1075 if (!dol_textishtml($this->substit['__LINES__'])) {
1076 $this->substit['__LINES__'] = dol_nl2br($this->substit['__LINES__']);
1077 }
1078 if (!dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
1079 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = dol_nl2br($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']);
1080 }
1081 if (!dol_textishtml($defaultmessage)) {
1082 $defaultmessage = dol_nl2br($defaultmessage);
1083 }
1084 }
1085
1086 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1087 $defaultmessage = GETPOST("message", "restricthtml");
1088 } else {
1089 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1090 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1091 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1092 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1093 }
1094
1095 $out .= '<tr>';
1096 $out .= '<td class="tdtop">';
1097 $out .= $form->textwithpicto($langs->trans('MailText'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
1098 $out .= '</td>';
1099 $out .= '<td class="tdtop">';
1100
1101 $formmail = $this;
1102 $showlinktolayout = ($formmail->withfckeditor && getDolGlobalInt('MAIN_EMAIL_USE_LAYOUT')) ? $formmail->withlayout : '';
1103 $showlinktolayoutlabel = $langs->trans("FillMessageWithALayout");
1104 $showlinktoai = ($formmail->withaiprompt && isModEnabled('ai')) ? 'textgenerationemail' : '';
1105 $showlinktoailabel = $langs->trans("AIEnhancements");
1106 $formatforouput = '';
1107 $htmlname = 'message';
1108
1109 $formai->substit = $this->substit;
1110 $formai->substit_lines = $this->substit_lines;
1111
1112 // Fill $out
1113 $db = $this->db;
1114 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
1115
1116 $out .= '</td>';
1117 $out .= '</tr>';
1118
1119 $out .= '<tr>';
1120 $out .= '<td colspan="2">';
1121 if ($this->withbodyreadonly) {
1122 $out .= nl2br($defaultmessage);
1123 $out .= '<input type="hidden" id="message" name="message" disabled value="'.$defaultmessage.'" />';
1124 } else {
1125 if (!isset($this->ckeditortoolbar)) {
1126 $this->ckeditortoolbar = 'dolibarr_mailings';
1127 }
1128
1129 // Editor wysiwyg
1130 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1131 if ($this->withfckeditor == -1) {
1132 if (getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) {
1133 $this->withfckeditor = 1;
1134 } else {
1135 $this->withfckeditor = 0;
1136 }
1137 }
1138
1139 $doleditor = new DolEditor('message', $defaultmessage, '', 280, $this->ckeditortoolbar, 'In', true, true, $this->withfckeditor, 8, '95%');
1140 $out .= $doleditor->Create(1);
1141 }
1142 $out .= "</td></tr>\n";
1143 }
1144
1145 $out .= '</table>'."\n";
1146
1147 if ($this->withform == 1 || $this->withform == -1) {
1148 $out .= '<div class="center">';
1149 $out .= '<input type="submit" class="button button-add" id="sendmail" name="sendmail" value="'.$langs->trans("SendMail").'"';
1150 // Add a javascript test to avoid to forget to submit file before sending email
1151 if ($this->withfile == 2 && $conf->use_javascript_ajax) {
1152 $out .= ' onClick="if (document.mailform.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1153 }
1154 $out .= ' />';
1155 if ($this->withcancel) {
1156 $out .= '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'" />';
1157 }
1158 $out .= '</div>'."\n";
1159 }
1160
1161 if ($this->withform == 1) {
1162 $out .= '</form>'."\n";
1163 }
1164
1165 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1166 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1167 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1168 $out .= 'jQuery(document).ready(function () {';
1169 $out .= ' $(document).on("keypress", \'#mailform\', function (e) { /* Note this is called at every key pressed ! */
1170 var code = e.keyCode || e.which;
1171 if (code == 13) {
1172 console.log("Enter was intercepted and blocked");
1173 e.preventDefault();
1174 return false;
1175 }
1176 });';
1177 $out .= ' })';
1178 $out .= '</script>';
1179 }
1180
1181 $out .= "<!-- End form mail -->\n";
1182
1183 return $out;
1184 }
1185 }
1186
1192 public function getHtmlForTo()
1193 {
1194 global $langs, $form;
1195 $out = '<tr><td class="fieldrequired">';
1196 if ($this->withtofree) {
1197 $out .= $form->textwithpicto($langs->trans("MailTo"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1198 } else {
1199 $out .= $langs->trans("MailTo");
1200 }
1201 $out .= '</td><td>';
1202 if ($this->withtoreadonly) {
1203 if (!empty($this->toname) && !empty($this->tomail)) {
1204 $out .= '<input type="hidden" id="toname" name="toname" value="'.$this->toname.'" />';
1205 $out .= '<input type="hidden" id="tomail" name="tomail" value="'.$this->tomail.'" />';
1206 if ($this->totype == 'thirdparty') {
1207 $soc = new Societe($this->db);
1208 $soc->fetch($this->toid);
1209 $out .= $soc->getNomUrl(1);
1210 } elseif ($this->totype == 'contact') {
1211 $contact = new Contact($this->db);
1212 $contact->fetch($this->toid);
1213 $out .= $contact->getNomUrl(1);
1214 } else {
1215 $out .= $this->toname;
1216 }
1217 $out .= ' &lt;'.$this->tomail.'&gt;';
1218 if ($this->withtofree) {
1219 $out .= '<br>'.$langs->trans("and").' <input class="minwidth200" id="sendto" name="sendto" spellcheck="false" value="'.(!is_array($this->withto) && !is_numeric($this->withto) ? (GETPOSTISSET("sendto") ? GETPOST("sendto") : $this->withto) : "").'" />';
1220 }
1221 } else {
1222 // Note withto may be a text like 'AllRecipientSelected'
1223 $out .= (!is_array($this->withto) && !is_numeric($this->withto)) ? $this->withto : "";
1224 }
1225 } else {
1226 // The free input of email
1227 if (!empty($this->withtofree)) {
1228 $out .= '<input class="minwidth200" id="sendto" name="sendto" spellcheck="false" value="'.(($this->withtofree && !is_numeric($this->withtofree)) ? $this->withtofree : (!is_array($this->withto) && !is_numeric($this->withto) ? (GETPOSTISSET("sendto") ? GETPOST("sendto") : $this->withto) : "")).'" />';
1229 }
1230 // The select combo
1231 if (!empty($this->withto) && is_array($this->withto)) {
1232 if (!empty($this->withtofree)) {
1233 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1234 }
1235
1236 $tmparray = $this->withto;
1237 foreach ($tmparray as $key => $val) {
1238 if (is_array($val)) {
1239 $label = $val['label'];
1240 } else {
1241 $label = $val;
1242 }
1243
1244 $tmparray[$key] = array();
1245 $tmparray[$key]['id'] = $key;
1246
1247 $tmparray[$key]['label'] = $label;
1248 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1249 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1250 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1251
1252 $tmparray[$key]['labelhtml'] = $label;
1253 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1254 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1255 }
1256
1257 $withtoselected = GETPOST("receiver", 'array'); // Array of selected value
1258 if (!getDolGlobalInt('MAIN_MAIL_NO_WITH_TO_SELECTED')) {
1259 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
1260 $withtoselected = array_keys($tmparray);
1261 }
1262 }
1263
1264 $out .= $form->multiselectarray("receiver", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, 0);
1265 }
1266 }
1267 $out .= "</td></tr>\n";
1268 return $out;
1269 }
1270
1276 public function getHtmlForCc()
1277 {
1278 global $langs, $form;
1279 $out = '<tr><td>';
1280 $out .= $form->textwithpicto($langs->trans("MailCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1281 $out .= '</td><td>';
1282 if ($this->withtoccreadonly) {
1283 $out .= (!is_array($this->withtocc) && !is_numeric($this->withtocc)) ? $this->withtocc : "";
1284 } else {
1285 $out .= '<input class="minwidth200" id="sendtocc" name="sendtocc" value="'.(GETPOST("sendtocc", "alpha") ? GETPOST("sendtocc", "alpha") : ((!is_array($this->withtocc) && !is_numeric($this->withtocc)) ? $this->withtocc : '')).'" />';
1286 if (!empty($this->withtocc) && is_array($this->withtocc)) {
1287 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1288
1289 $tmparray = $this->withtocc;
1290 foreach ($tmparray as $key => $val) {
1291 if (is_array($val)) {
1292 $label = $val['label'];
1293 } else {
1294 $label = $val;
1295 }
1296
1297 $tmparray[$key] = array();
1298 $tmparray[$key]['id'] = $key;
1299
1300 $tmparray[$key]['label'] = $label;
1301 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1302 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1303 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1304
1305 $tmparray[$key]['labelhtml'] = $label;
1306 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1307 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1308 }
1309
1310 $withtoccselected = GETPOST("receivercc", 'array'); // Array of selected value
1311
1312 $out .= $form->multiselectarray("receivercc", $tmparray, $withtoccselected, 0, 0, 'inline-block minwidth500', 0, 0);
1313 }
1314 }
1315 $out .= "</td></tr>\n";
1316 return $out;
1317 }
1318
1325 public function getHtmlForWithCcc()
1326 {
1327 global $langs, $form;
1328
1329 $out = '<tr><td>';
1330 $out .= $form->textwithpicto($langs->trans("MailCCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1331 $out .= '</td><td>';
1332 if (!empty($this->withtocccreadonly)) {
1333 $out .= (!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : "";
1334 } else {
1335 $out .= '<input class="minwidth200" id="sendtoccc" name="sendtoccc" value="'.(GETPOSTISSET("sendtoccc") ? GETPOST("sendtoccc", "alpha") : ((!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />';
1336 if (!empty($this->withtoccc) && is_array($this->withtoccc)) {
1337 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1338
1339 $tmparray = $this->withtoccc;
1340 foreach ($tmparray as $key => $val) {
1341 if (is_array($val)) {
1342 $label = $val['label'];
1343 } else {
1344 $label = $val;
1345 }
1346 $tmparray[$key] = array();
1347 $tmparray[$key]['id'] = $key;
1348
1349 $tmparray[$key]['label'] = $label;
1350 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1351 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1352 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1353
1354 $tmparray[$key]['labelhtml'] = $label;
1355 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1356 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1357 }
1358
1359 $withtocccselected = GETPOST("receiverccc", 'array'); // Array of selected value
1360
1361 $out .= $form->multiselectarray("receiverccc", $tmparray, $withtocccselected, 0, 0, 'inline-block minwidth500', 0, 0);
1362 }
1363 }
1364
1365 $showinfobcc = '';
1366 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1367 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO');
1368 }
1369 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1370 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO');
1371 }
1372 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1373 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO');
1374 }
1375 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1376 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO');
1377 }
1378 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1379 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO');
1380 }
1381 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'invoice_supplier_send') {
1382 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO');
1383 }
1384 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROJECT_TO') && !empty($this->param['models']) && $this->param['models'] == 'project') { // don't know why there is not '_send' at end of this models name.
1385 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROJECT_TO');
1386 }
1387 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO') && !empty($this->param['models']) && $this->param['models'] == 'shipping_send') {
1388 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO');
1389 }
1390 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO') && !empty($this->param['models']) && $this->param['models'] == 'reception_send') {
1391 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO');
1392 }
1393 if ($showinfobcc) {
1394 $out .= ' + '.$showinfobcc;
1395 }
1396 $out .= "</td></tr>\n";
1397 return $out;
1398 }
1399
1405 public function getHtmlForWithErrorsTo()
1406 {
1407 global $langs;
1408
1409 //if (! $this->errorstomail) $this->errorstomail=$this->frommail;
1410 $errorstomail = getDolGlobalString('MAIN_MAIL_ERRORS_TO', (!empty($this->errorstomail) ? $this->errorstomail : ''));
1411 if ($this->witherrorstoreadonly) {
1412 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1413 $out .= '<input type="hidden" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1414 $out .= $errorstomail;
1415 $out .= "</td></tr>\n";
1416 } else {
1417 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1418 $out .= '<input class="minwidth200" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1419 $out .= "</td></tr>\n";
1420 }
1421 return $out;
1422 }
1423
1429 public function getHtmlForDeliveryreceipt()
1430 {
1431 global $langs;
1432
1433 $out = '<tr><td><label for="deliveryreceipt">'.$langs->trans("DeliveryReceipt").'</label></td><td>';
1434
1435 if (!empty($this->withdeliveryreceiptreadonly)) {
1436 $out .= yn($this->withdeliveryreceipt);
1437 } else {
1438 $defaultvaluefordeliveryreceipt = 0;
1439 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_PROPAL') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1440 $defaultvaluefordeliveryreceipt = 1;
1441 }
1442 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_PROPOSAL') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1443 $defaultvaluefordeliveryreceipt = 1;
1444 }
1445 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1446 $defaultvaluefordeliveryreceipt = 1;
1447 }
1448 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_INVOICE') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1449 $defaultvaluefordeliveryreceipt = 1;
1450 }
1451 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1452 $defaultvaluefordeliveryreceipt = 1;
1453 }
1454 //$out .= $form->selectyesno('deliveryreceipt', (GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt), 1);
1455 $out .= '<input type="checkbox" id="deliveryreceipt" name="deliveryreceipt" value="1"'.((GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt) ? ' checked="checked"' : '').'>';
1456 }
1457 $out .= "</td></tr>\n";
1458 return $out;
1459 }
1460
1468 public function getHtmlForTopic($arraydefaultmessage, $helpforsubstitution)
1469 {
1470 global $langs, $form;
1471
1472 $defaulttopic = GETPOST('subject', 'restricthtml');
1473
1474 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
1475 if ($arraydefaultmessage && $arraydefaultmessage->topic) {
1476 $defaulttopic = $arraydefaultmessage->topic;
1477 } elseif (!is_numeric($this->withtopic)) {
1478 $defaulttopic = $this->withtopic;
1479 }
1480 }
1481
1482 $defaulttopic = make_substitutions($defaulttopic, $this->substit);
1483
1484 $out = '<tr>';
1485 $out .= '<td class="fieldrequired">';
1486 $out .= $form->textwithpicto($langs->trans('MailTopic'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
1487 $out .= '</td>';
1488 $out .= '<td>';
1489 if ($this->withtopicreadonly) {
1490 $out .= $defaulttopic;
1491 $out .= '<input type="hidden" class="quatrevingtpercent" id="subject" name="subject" value="'.$defaulttopic.'" />';
1492 } else {
1493 $out .= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'.((GETPOSTISSET("subject") && !GETPOST('modelselected')) ? GETPOST("subject") : ($defaulttopic ? $defaulttopic : '')).'" />';
1494 }
1495 $out .= "</td></tr>\n";
1496 return $out;
1497 }
1498
1506 public function getEmailLayoutSelector($htmlContent = 'message', $showlinktolayout = 'email')
1507 {
1508 global $conf, $db, $websitepage, $langs;
1509
1510 require_once DOL_DOCUMENT_ROOT.'/core/lib/emaillayout.lib.php';
1511 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1512 require_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php';
1513 require_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
1514
1515 $out = '<div id="template-selector" class="template-selector email-layout-container hidden" style="display:none;">';
1516
1517 // Define list of email layouts to use
1518 $layouts = array(
1519 'empty' => 'empty',
1520 );
1521
1522 // Search available layouts on disk
1523 $arrayoflayoutemplates = dol_dir_list(DOL_DOCUMENT_ROOT.'/install/doctemplates/maillayout/', 'files', 0, '\.html$');
1524 foreach ($arrayoflayoutemplates as $layouttemplatefile) {
1525 $layoutname = preg_replace('/\.html$/i', '', $layouttemplatefile['name']);
1526
1527 // Exclude some layouts for some use cases
1528 if ($layoutname == 'news' && (!in_array($showlinktolayout, array('emailing', 'websitepage')) || !isModEnabled('website'))) {
1529 continue;
1530 }
1531 if ($layoutname == 'products' && (!in_array($showlinktolayout, array('emailing', 'websitepage')) || (!isModEnabled('product') && !isModEnabled('service')))) {
1532 continue;
1533 }
1534
1535 $layouts[$layoutname] = ucfirst($layoutname);
1536 }
1537 //}
1538 // TODO Add a hook to allow to complete the list
1539
1540 foreach ($layouts as $layout => $templateFunction) {
1541 $contentHtml = getHtmlOfLayout($layout);
1542
1543 $out .= '<div class="template-option" data-template="'.$layout.'" data-content="'.htmlentities($contentHtml).'">';
1544 $out .= '<img class="maillayout" alt="'.$layout.'" src="'.DOL_URL_ROOT.'/theme/common/maillayout/'.$layout.'.png" />';
1545 $out .= '<span class="template-option-text">'.$langs->trans($templateFunction).'</span>';
1546 $out .= '</div>';
1547 }
1548 $out .= '</div>';
1549
1550 // Prepare the array for multiselect
1551
1552 // Fetch blogs
1553 $blogArray = array();
1554 if (isModEnabled('website')) {
1555 $websitepage = new WebsitePage($this->db);
1556 $arrayofblogs = $websitepage->fetchAll('', 'ASC,DESC', 'fk_website,date_creation', 0, 0, array('type_container' => 'blogpost'));
1557
1558 if (empty($conf->cache['websiteurl'])) {
1559 $conf->cache['websiteurl'] = array();
1560 }
1561
1562 if (!empty($arrayofblogs)) {
1563 foreach ($arrayofblogs as $blog) {
1564 if (!isset($conf->cache['websiteurl'][$blog->id])) {
1565 $tmpwebsite = new Website($db);
1566 $tmpwebsite->fetch($blog->fk_website);
1567 $conf->cache['websiteurl'][$blog->fk_website] = (empty($tmpwebsite->virtualhost) ? $tmpwebsite->ref : $tmpwebsite->virtualhost);
1568 }
1569
1570 $labelwebsite = $conf->cache['websiteurl'][$blog->fk_website];
1571 //$blog->fk_website
1572
1573 $blogArray[$blog->id] = array(
1574 'id' => $blog->id,
1575 'label' => '['.$labelwebsite.' '.$blog->type_container.' '.$blog->id.'] '.dol_trunc($blog->title, 40),
1576 'labelhtml' => '<span class="opacitymedium">['.$labelwebsite.' '.$blog->type_container.' '.$blog->id.']</span> '.dol_trunc($blog->title, 40),
1577 );
1578 }
1579 }
1580 }
1581
1582 // Use the multiselect array function to create the dropdown
1583 $out .= '<div id="post-dropdown-container" class="email-layout-container hidden" style="display:none;">';
1584 $out .= '<label for="blogpost-select">Select Posts: </label>';
1585 $out .= '<!-- select component for selection of products -->'."\n";
1586 $out .= self::multiselectarray('blogpost-select', $blogArray, array(), 0, 0, 'minwidth200');
1587 $out .= '</div>';
1588
1589 $out .= '<!-- Js code to manage choice of an email layout -->'."\n";
1590 $out .= '<script type="text/javascript">
1591 $(document).ready(function() {
1592 $(".template-option").click(function() {
1593 var template = $(this).data("template");
1594 var subject = jQuery("#subject").val();
1595 var fromtype = jQuery("#fromtype").val();
1596 var sendto = jQuery("#sendto").val();
1597 var sendtocc = jQuery("#sendtocc").val();
1598 var sendtoccc = jQuery("#sendtoccc").val();
1599
1600 console.log("We choose a layout for email template=" + template + ", subject="+subject);
1601
1602 $(".template-option").removeClass("selected");
1603 $(this).addClass("selected");
1604
1605 if (template === "news") {
1606 $("#post-dropdown-container").show();
1607 console.log("Displaying dropdown for news template");
1608 } else {
1609 $("#post-dropdown-container").hide();
1610
1611 var csrfToken = "' .newToken().'";
1612 $.ajax({
1613 type: "POST",
1614 url: "'.DOL_URL_ROOT.'/core/ajax/mailtemplate.php",
1615 data: {
1616 token: csrfToken,
1617 template: template,
1618 subject: subject,
1619 fromtype: fromtype,
1620 sendto: sendto,
1621 sendtocc: sendtocc,
1622 sendtoccc: sendtoccc,
1623 selectedPosts: "[]"
1624 },
1625 success: function(response) {
1626 jQuery("#'.$htmlContent.'").val(response);
1627 var editorInstance = CKEDITOR.instances["'.$htmlContent.'"];
1628 if (editorInstance) {
1629 editorInstance.setData(response);
1630 }
1631 },
1632 error: function(xhr, status, error) {
1633 console.error("An error occurred: " + xhr.responseText);
1634 }
1635 });
1636 }
1637 });
1638
1639 $("#blogpost-select").change(function() {
1640 var selectedIds = $(this).val();
1641 var contentHtml = $(".template-option.selected").data("content");
1642
1643 updateSelectedPostsContent(contentHtml, selectedIds);
1644 });
1645
1646 function updateSelectedPostsContent(contentHtml, selectedIds) {
1647 var csrfToken = "' .newToken().'";
1648 $.ajax({
1649 type: "POST",
1650 url: "/core/ajax/getnews.php",
1651 data: {
1652 selectedIds: JSON.stringify(selectedIds),
1653 token : csrfToken
1654 },
1655 success: function(response) {
1656 var selectedPosts = JSON.parse(response);
1657 var subject = $("#subject").val();
1658
1659 contentHtml = contentHtml.replace(/__SUBJECT__/g, subject);
1660
1661 $.ajax({
1662 type: "POST",
1663 url: "/core/ajax/mailtemplate.php",
1664 data: {
1665 token: csrfToken,
1666 template: template,
1667 subject: subject,
1668 fromtype: fromtype,
1669 sendto: sendto,
1670 sendtocc: sendtocc,
1671 sendtoccc: sendtoccc,
1672 selectedPosts: selectedIds.join(",")
1673 },
1674 success: function(response) {
1675 jQuery("#'.$htmlContent.'").val(response);
1676 var editorInstance = CKEDITOR.instances["'.$htmlContent.'"];
1677 if (editorInstance) {
1678 editorInstance.setData(response);
1679 }
1680 },
1681 error: function(xhr, status, error) {
1682 console.error("An error occurred: " + xhr.responseText);
1683 }
1684 });
1685 },
1686 error: function(xhr, status, error) {
1687 console.error("An error occurred: " + xhr.responseText);
1688 }
1689 });
1690 }
1691 });
1692 </script>';
1693
1694 return $out;
1695 }
1696
1714 public function getEMailTemplate($dbs, $type_template, $user, $outputlangs, $id = 0, $active = 1, $label = '', $defaultfortype = -1)
1715 {
1716 global $conf;
1717
1718 if ($id == -2 && empty($label)) {
1719 $this->error = 'LabelIsMandatoryWhenIdIs-2or-3';
1720 return -1;
1721 }
1722
1723 $ret = new ModelMail($dbs);
1724
1725 $languagetosearch = (is_object($outputlangs) ? $outputlangs->defaultlang : '');
1726 // Define $languagetosearchmain to fall back on main language (for example to get 'es_ES' for 'es_MX')
1727 $tmparray = explode('_', $languagetosearch);
1728 $languagetosearchmain = $tmparray[0].'_'.strtoupper($tmparray[0]);
1729 if ($languagetosearchmain == $languagetosearch) {
1730 $languagetosearchmain = '';
1731 }
1732
1733 $sql = "SELECT rowid, entity, module, label, type_template, topic, email_from, joinfiles, content, content_lines, lang, email_from, email_to, email_tocc, email_tobcc";
1734 $sql .= " FROM ".$dbs->prefix().'c_email_templates';
1735 $sql .= " WHERE (type_template = '".$dbs->escape($type_template)."' OR type_template = '".$dbs->escape($type_template)."_send' OR type_template = 'all')";
1736 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1737 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // Get all public or private owned
1738 if ($active >= 0) {
1739 $sql .= " AND active = ".((int) $active);
1740 }
1741 if ($defaultfortype >= 0) {
1742 $sql .= " AND defaultfortype = ".((int) $defaultfortype);
1743 }
1744 if ($label) {
1745 $sql .= " AND label = '".$dbs->escape($label)."'";
1746 }
1747 if (!($id > 0) && $languagetosearch) {
1748 $sql .= " AND (lang = '".$dbs->escape($languagetosearch)."'".($languagetosearchmain ? " OR lang = '".$dbs->escape($languagetosearchmain)."'" : "")." OR lang IS NULL OR lang = '')";
1749 }
1750 if ($id > 0) {
1751 $sql .= " AND rowid = ".(int) $id;
1752 }
1753 if ($id == -1) {
1754 $sql .= " AND position = 0";
1755 }
1756 $sql .= " AND entity IN(".getEntity('c_email_templates', 1).")";
1757 if ($languagetosearch) {
1758 $sql .= $dbs->order("position,lang,label", "ASC,DESC,ASC"); // We want line with lang set first, then with lang null or ''
1759 } else {
1760 $sql .= $dbs->order("position,lang,label", "ASC,ASC,ASC"); // If no language provided, we give priority to lang not defined
1761 }
1762 //$sql .= $dbs->plimit(1);
1763 //print $sql;
1764
1765 $resql = $dbs->query($sql);
1766 if (!$resql) {
1767 dol_print_error($dbs);
1768 return -1;
1769 }
1770
1771 // Get first found
1772 while (1) {
1773 $obj = $dbs->fetch_object($resql);
1774
1775 if ($obj) {
1776 // If template is for a module, check module is enabled; if not, take next template
1777 if ($obj->module) {
1778 $tempmodulekey = $obj->module;
1779 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
1780 continue;
1781 }
1782 }
1783
1784 // If a record was found
1785 $ret->id = (int) $obj->rowid;
1786 $ret->module = (string) $obj->module;
1787 $ret->label = (string) $obj->label;
1788 $ret->lang = $obj->lang;
1789 $ret->topic = $obj->topic;
1790 $ret->content = (string) $obj->content;
1791 $ret->content_lines = (string) $obj->content_lines;
1792 $ret->joinfiles = $obj->joinfiles;
1793 $ret->email_from = (string) $obj->email_from;
1794
1795 break;
1796 } else {
1797 // If no record found
1798 if ($id == -2) {
1799 // Not found with the provided label
1800 return -1;
1801 } else {
1802 // If there is no template at all
1803 $defaultmessage = '';
1804
1805 if ($type_template == 'body') {
1806 // Special case to use this->withbody as content
1807 $defaultmessage = (string) $this->withbody;
1808 } elseif ($type_template == 'facture_send' || $type_template == 'facture' || $type_template == 'facture_relance') {
1809 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoice");
1810 } elseif ($type_template == 'propal_send' || $type_template == 'propal') {
1811 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendProposal");
1812 } elseif ($type_template == 'supplier_proposal_send' || $type_template == 'supplier_proposal') {
1813 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierProposal");
1814 } elseif ($type_template == 'order_send' || $type_template == 'order') {
1815 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendOrder");
1816 } elseif ($type_template == 'order_supplier_send' || $type_template == 'order_supplier') {
1817 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierOrder");
1818 } elseif ($type_template == 'invoice_supplier_send' || $type_template == 'invoice_supplier') {
1819 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierInvoice");
1820 } elseif ($type_template == 'shipping_send' || $type_template == 'shipping') {
1821 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendShipping");
1822 } elseif ($type_template == 'fichinter_send' || $type_template == 'fichinter') {
1823 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendFichInter");
1824 } elseif ($type_template == 'actioncomm_send' || $type_template == 'actioncomm') {
1825 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendActionComm");
1826 } elseif (!empty($type_template)) {
1827 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentGeneric");
1828 }
1829
1830 $ret->label = 'default';
1831 $ret->lang = $outputlangs->defaultlang;
1832 $ret->topic = '';
1833 $ret->joinfiles = 1;
1834 $ret->content = $defaultmessage;
1835 $ret->content_lines = '';
1836
1837 break;
1838 }
1839 }
1840 }
1841
1842 $dbs->free($resql);
1843
1844 return $ret;
1845 }
1846
1856 public function isEMailTemplate($type_template, $user, $outputlangs)
1857 {
1858 $sql = "SELECT label, topic, content, lang";
1859 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
1860 $sql .= " WHERE type_template='".$this->db->escape($type_template)."'";
1861 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1862 $sql .= " AND (fk_user is NULL or fk_user = 0 or fk_user = ".((int) $user->id).")";
1863 if (is_object($outputlangs)) {
1864 $sql .= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')";
1865 }
1866 $sql .= $this->db->order("lang,label", "ASC");
1867 //print $sql;
1868
1869 $resql = $this->db->query($sql);
1870 if ($resql) {
1871 $num = $this->db->num_rows($resql);
1872 $this->db->free($resql);
1873 return $num;
1874 } else {
1875 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
1876 return -1;
1877 }
1878 }
1879
1890 public function fetchAllEMailTemplate($type_template, $user, $outputlangs, $active = 1)
1891 {
1892 global $db, $conf;
1893
1894 $sql = "SELECT rowid, module, label, topic, content, content_lines, lang, fk_user, private, position";
1895 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
1896 $sql .= " WHERE type_template IN ('".$this->db->escape($type_template)."', 'all')";
1897 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1898 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // See all public templates or templates I own.
1899 if ($active >= 0) {
1900 $sql .= " AND active = ".((int) $active);
1901 }
1902 //if (is_object($outputlangs)) $sql.= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')"; // Return all languages
1903 $sql .= $this->db->order("position,lang,label", "ASC");
1904 //print $sql;
1905
1906 $resql = $this->db->query($sql);
1907 if ($resql) {
1908 $num = $this->db->num_rows($resql);
1909 $this->lines_model = array();
1910 while ($obj = $this->db->fetch_object($resql)) {
1911 // If template is for a module, check module is enabled.
1912 if ($obj->module) {
1913 $tempmodulekey = $obj->module;
1914 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
1915 continue;
1916 }
1917 }
1918
1919 $line = new ModelMail($db);
1920 $line->id = (int) $obj->rowid;
1921 $line->label = (string) $obj->label;
1922 $line->lang = $obj->lang;
1923 $line->fk_user = $obj->fk_user;
1924 $line->private = $obj->private;
1925 $line->position = $obj->position;
1926 $line->topic = $obj->topic;
1927 $line->content = $obj->content;
1928 $line->content_lines = $obj->content_lines;
1929
1930 $this->lines_model[] = $line;
1931 }
1932 $this->db->free($resql);
1933 return $num;
1934 } else {
1935 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
1936 return -1;
1937 }
1938 }
1939
1940
1941
1950 public function setSubstitFromObject($object, $outputlangs)
1951 {
1952 global $extrafields;
1953
1954 $parameters = array();
1955 $tmparray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
1956 complete_substitutions_array($tmparray, $outputlangs, null, $parameters);
1957
1958 $this->substit = $tmparray;
1959
1960 // Fill substit_lines with each object lines content
1961 if (is_array($object->lines)) {
1962 foreach ($object->lines as $line) {
1963 $substit_line = array(
1964 '__PRODUCT_REF__' => isset($line->product_ref) ? $line->product_ref : '',
1965 '__PRODUCT_LABEL__' => isset($line->product_label) ? $line->product_label : '',
1966 '__PRODUCT_DESCRIPTION__' => isset($line->product_desc) ? $line->product_desc : '',
1967 '__LABEL__' => isset($line->label) ? $line->label : '',
1968 '__DESCRIPTION__' => isset($line->desc) ? $line->desc : '',
1969 '__DATE_START_YMD__' => dol_print_date($line->date_start, 'day', false, $outputlangs),
1970 '__DATE_END_YMD__' => dol_print_date($line->date_end, 'day', false, $outputlangs),
1971 '__QUANTITY__' => $line->qty,
1972 '__SUBPRICE__' => price($line->subprice),
1973 '__AMOUNT__' => price($line->total_ttc),
1974 '__AMOUNT_EXCL_TAX__' => price($line->total_ht)
1975 );
1976
1977 // Create dynamic tags for __PRODUCT_EXTRAFIELD_FIELD__
1978 if (!empty($line->fk_product)) {
1979 if (!is_object($extrafields)) {
1980 $extrafields = new ExtraFields($this->db);
1981 }
1982 $product = new Product($this->db);
1983 $product->fetch($line->fk_product, '', '', '1');
1984 $product->fetch_optionals();
1985
1986 $extrafields->fetch_name_optionals_label($product->table_element, true);
1987
1988 if (!empty($extrafields->attributes[$product->table_element]['label']) && is_array($extrafields->attributes[$product->table_element]['label']) && count($extrafields->attributes[$product->table_element]['label']) > 0) {
1989 foreach ($extrafields->attributes[$product->table_element]['label'] as $key => $label) {
1990 $substit_line['__PRODUCT_EXTRAFIELD_'.strtoupper($key).'__'] = isset($product->array_options['options_'.$key]) ? $product->array_options['options_'.$key] : '';
1991 }
1992 }
1993 }
1994
1995 $this->substit_lines[$line->id] = $substit_line; // @phan-suppress-current-line PhanTypeMismatchProperty
1996 }
1997 }
1998 }
1999
2008 public static function getAvailableSubstitKey($mode = 'formemail', $object = null)
2009 {
2010 global $langs;
2011
2012 $tmparray = array();
2013 if ($mode == 'formemail' || $mode == 'formemailwithlines' || $mode == 'formemailforlines') {
2014 $parameters = array('mode' => $mode);
2015 $tmparray = getCommonSubstitutionArray($langs, 2, null, $object); // Note: On email templated edition, this is null because it is related to all type of objects
2016 complete_substitutions_array($tmparray, $langs, null, $parameters);
2017
2018 if ($mode == 'formwithlines') {
2019 $tmparray['__LINES__'] = '__LINES__'; // Will be set by the get_form function
2020 }
2021 if ($mode == 'formforlines') {
2022 $tmparray['__QUANTITY__'] = '__QUANTITY__'; // Will be set by the get_form function
2023 }
2024 }
2025
2026 if ($mode == 'emailing') {
2027 $parameters = array('mode' => $mode);
2028 $tmparray = getCommonSubstitutionArray($langs, 2, array('object', 'objectamount'), $object); // Note: On email templated edition, this is null because it is related to all type of objects
2029 complete_substitutions_array($tmparray, $langs, null, $parameters);
2030
2031 // For mass emailing, we have different keys specific to the data into tagerts list
2032 $tmparray['__ID__'] = 'IdRecord';
2033 $tmparray['__EMAIL__'] = 'EMailRecipient';
2034 $tmparray['__LASTNAME__'] = 'Lastname';
2035 $tmparray['__FIRSTNAME__'] = 'Firstname';
2036 $tmparray['__MAILTOEMAIL__'] = 'TagMailtoEmail';
2037 $tmparray['__OTHER1__'] = 'Other1';
2038 $tmparray['__OTHER2__'] = 'Other2';
2039 $tmparray['__OTHER3__'] = 'Other3';
2040 $tmparray['__OTHER4__'] = 'Other4';
2041 $tmparray['__OTHER5__'] = 'Other5';
2042
2043 $tmparray['__THIRDPARTY_CUSTOMER_CODE__'] = 'CustomerCode'; // If source is a thirdparty
2044
2045 $tmparray['__CHECK_READ__'] = $langs->trans('TagCheckMail');
2046 $tmparray['__UNSUBSCRIBE__'] = $langs->trans('TagUnsubscribe');
2047 $tmparray['__UNSUBSCRIBE_URL__'] = $langs->trans('TagUnsubscribe').' (URL)';
2048
2049 $onlinepaymentenabled = 0;
2050 if (isModEnabled('paypal')) {
2051 $onlinepaymentenabled++;
2052 }
2053 if (isModEnabled('paybox')) {
2054 $onlinepaymentenabled++;
2055 }
2056 if (isModEnabled('stripe')) {
2057 $onlinepaymentenabled++;
2058 }
2059 if ($onlinepaymentenabled && getDolGlobalString('PAYMENT_SECURITY_TOKEN')) {
2060 $tmparray['__SECUREKEYPAYMENT__'] = getDolGlobalString('PAYMENT_SECURITY_TOKEN');
2061 if (getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
2062 if (isModEnabled('member')) {
2063 $tmparray['__SECUREKEYPAYMENT_MEMBER__'] = 'SecureKeyPAYMENTUniquePerMember';
2064 }
2065 if (isModEnabled('don')) {
2066 $tmparray['__SECUREKEYPAYMENT_DONATION__'] = 'SecureKeyPAYMENTUniquePerDonation';
2067 }
2068 if (isModEnabled('invoice')) {
2069 $tmparray['__SECUREKEYPAYMENT_INVOICE__'] = 'SecureKeyPAYMENTUniquePerInvoice';
2070 }
2071 if (isModEnabled('order')) {
2072 $tmparray['__SECUREKEYPAYMENT_ORDER__'] = 'SecureKeyPAYMENTUniquePerOrder';
2073 }
2074 if (isModEnabled('contract')) {
2075 $tmparray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'SecureKeyPAYMENTUniquePerContractLine';
2076 }
2077
2078 //Online payment link
2079 if (isModEnabled('member')) {
2080 $tmparray['__ONLINEPAYMENTLINK_MEMBER__'] = 'OnlinePaymentLinkUniquePerMember';
2081 }
2082 if (isModEnabled('don')) {
2083 $tmparray['__ONLINEPAYMENTLINK_DONATION__'] = 'OnlinePaymentLinkUniquePerDonation';
2084 }
2085 if (isModEnabled('invoice')) {
2086 $tmparray['__ONLINEPAYMENTLINK_INVOICE__'] = 'OnlinePaymentLinkUniquePerInvoice';
2087 }
2088 if (isModEnabled('order')) {
2089 $tmparray['__ONLINEPAYMENTLINK_ORDER__'] = 'OnlinePaymentLinkUniquePerOrder';
2090 }
2091 if (isModEnabled('contract')) {
2092 $tmparray['__ONLINEPAYMENTLINK_CONTRACTLINE__'] = 'OnlinePaymentLinkUniquePerContractLine';
2093 }
2094 }
2095 } else {
2096 /* No need to show into tooltip help, option is not enabled
2097 $vars['__SECUREKEYPAYMENT__']='';
2098 $vars['__SECUREKEYPAYMENT_MEMBER__']='';
2099 $vars['__SECUREKEYPAYMENT_INVOICE__']='';
2100 $vars['__SECUREKEYPAYMENT_ORDER__']='';
2101 $vars['__SECUREKEYPAYMENT_CONTRACTLINE__']='';
2102 */
2103 }
2104 if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
2105 $tmparray['__PUBLICLINK_NEWMEMBERFORM__'] = 'BlankSubscriptionForm';
2106 }
2107 }
2108
2109 foreach ($tmparray as $key => $val) {
2110 if (empty($val)) {
2111 $tmparray[$key] = $key;
2112 }
2113 }
2114
2115 return $tmparray;
2116 }
2117}
2118
2119
2120require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
2121
2127class ModelMail extends CommonObject
2128{
2132 public $element = 'email_template';
2133
2137 public $table_element = 'c_email_templates';
2138
2139
2140 // BEGIN MODULEBUILDER PROPERTIES
2144 public $fields = array(
2145 "rowid" => array("type" => "integer", "label" => "TechnicalID", 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => -1,),
2146 "module" => array("type" => "varchar(32)", "label" => "Module", 'enabled' => 1, 'position' => 20, 'notnull' => 0, 'visible' => -1,),
2147 "type_template" => array("type" => "varchar(32)", "label" => "Typetemplate", 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,),
2148 "lang" => array("type" => "varchar(6)", "label" => "Lang", 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,),
2149 "private" => array("type" => "smallint(6)", "label" => "Private", 'enabled' => 1, 'position' => 35, 'notnull' => 1, 'visible' => -1,),
2150 "fk_user" => array("type" => "integer:User:user/class/user.class.php", "label" => "Fkuser", 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1, "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150",),
2151 "datec" => array("type" => "datetime", "label" => "DateCreation", 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,),
2152 "tms" => array("type" => "timestamp", "label" => "DateModification", 'enabled' => 1, 'position' => 50, 'notnull' => 1, 'visible' => -1,),
2153 "label" => array("type" => "varchar(255)", "label" => "Label", 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1, "css" => "minwidth300", "cssview" => "wordbreak", "csslist" => "tdoverflowmax150",),
2154 "position" => array("type" => "smallint(6)", "label" => "Position", 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2155 "active" => array("type" => "integer", "label" => "Active", 'enabled' => 1, 'position' => 65, 'notnull' => 1, 'visible' => -1, 'alwayseditable' => 1,),
2156 "topic" => array("type" => "text", "label" => "Topic", 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2157 "content" => array("type" => "mediumtext", "label" => "Content", 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2158 "content_lines" => array("type" => "text", "label" => "Contentlines", "enabled" => "getDolGlobalString('MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES')", 'position' => 80, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2159 "enabled" => array("type" => "varchar(255)", "label" => "Enabled", 'enabled' => 1, 'position' => 85, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2160 "joinfiles" => array("type" => "varchar(255)", "label" => "Joinfiles", 'enabled' => 1, 'position' => 90, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2161 "email_from" => array("type" => "varchar(255)", "label" => "Emailfrom", 'enabled' => 1, 'position' => 95, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2162 "email_to" => array("type" => "varchar(255)", "label" => "Emailto", 'enabled' => 1, 'position' => 100, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2163 "email_tocc" => array("type" => "varchar(255)", "label" => "Emailtocc", 'enabled' => 1, 'position' => 105, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2164 "email_tobcc" => array("type" => "varchar(255)", "label" => "Emailtobcc", 'enabled' => 1, 'position' => 110, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2165 "defaultfortype" => array("type" => "smallint(6)", "label" => "Defaultfortype", 'enabled' => 1, 'position' => 115, 'notnull' => 0, 'visible' => -1, 'alwayseditable' => 1,),
2166 );
2170 public $rowid;
2174 public $type_template;
2178 public $datec;
2182 public $tms;
2186 public $active;
2190 public $enabled;
2194 public $defaultfortype;
2195
2199 public $id;
2200
2204 public $label;
2205
2209 public $fk_user;
2210
2214 public $private;
2215
2219 public $topic;
2220
2224 public $content;
2228 public $content_lines;
2229
2233 public $lang;
2237 public $joinfiles;
2238
2242 public $email_from;
2246 public $email_to;
2250 public $email_tocc;
2254 public $email_tobcc;
2255
2259 public $module;
2260
2264 public $position;
2265 // END MODULEBUILDER PROPERTIES
2266
2267
2268
2274 public function __construct(DoliDB $db)
2275 {
2276 global $langs;
2277
2278 $this->db = $db;
2279 $this->ismultientitymanaged = 0;
2280 $this->isextrafieldmanaged = 1;
2281
2282 // @phan-suppress-next-line PhanTypeMismatchProperty
2283 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
2284 $this->fields['rowid']['visible'] = 0;
2285 }
2286 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
2287 $this->fields['entity']['enabled'] = 0;
2288 }
2289
2290 // Example to show how to set values of fields definition dynamically
2291 /*if ($user->hasRight('test', 'mailtemplate', 'read')) {
2292 $this->fields['myfield']['visible'] = 1;
2293 $this->fields['myfield']['noteditable'] = 0;
2294 }*/
2295
2296 // Unset fields that are disabled
2297 foreach ($this->fields as $key => $val) {
2298 if (isset($val['enabled']) && empty($val['enabled'])) {
2299 unset($this->fields[$key]);
2300 }
2301 }
2302
2303 // Translate some data of arrayofkeyval
2304 if (is_object($langs)) {
2305 foreach ($this->fields as $key => $val) {
2306 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
2307 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
2308 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
2309 }
2310 }
2311 }
2312 }
2313 }
2314
2315
2325 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
2326 {
2327 // The table llx_c_email_templates has no field ref. The field ref was named "label" instead. So we change the call to fetchCommon.
2328 //$result = $this->fetchCommon($id, $ref, '', $noextrafields);
2329 $result = $this->fetchCommon($id, '', (empty($ref) ? '' : " AND t.label = '".$this->db->escape($ref)."'"), $noextrafields);
2330
2331 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
2332 $this->fetchLines($noextrafields);
2333 }
2334 return $result;
2335 }
2336}
print $object position
Definition edit.php:206
Class to manage a WYSIWYG editor.
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
static selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='minwidth75', $addjscombo=1, $moreparamonempty='', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
get_attached_files()
Return list of attached files (stored in SECTION array)
getHtmlForWithErrorsTo()
get Html For WithErrorsTo
getHtmlForTopic($arraydefaultmessage, $helpforsubstitution)
Return Html section for the Topic of message.
clear_attached_files()
Clear list of attached files in send mail form (also stored in session)
fetchAllEMailTemplate($type_template, $user, $outputlangs, $active=1)
Find if template exists and are available for current user, then set them into $this->lines_model.
getHtmlForCc()
get html For CC
getHtmlForTo()
get html For To
add_attached_files($path, $file='', $type='')
Add a file into the list of attached files (stored in SECTION array)
getHtmlForWithCcc()
get html For WithCCC This information is show when MAIN_EMAIL_USECCC is set.
remove_attached_files($keytodelete)
Remove a file from the list of attached files (stored in SECTION array)
__construct($db)
Constructor.
getHtmlForDeliveryreceipt()
get Html For Asking for Delivery Receipt
getEMailTemplate($dbs, $type_template, $user, $outputlangs, $id=0, $active=1, $label='', $defaultfortype=-1)
Return templates of email with type = $type_template or type = 'all'.
show_form($addfileaction='addfile', $removefileaction='removefile')
Show the form to input an email this->withfile: 0=No attaches files, 1=Show attached files,...
get_form($addfileaction='addfile', $removefileaction='removefile')
Get the form to input an email this->withfile: 0=No attaches files, 1=Show attached files,...
Class for Position.
Class to manage translations.
Class to manage Dolibarr users.
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").
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_htmlentities($string, $flags=ENT_QUOTES|ENT_SUBSTITUTE, $encoding='UTF-8', $double_encode=false)
Replace htmlentities functions.
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_textishtml($msg, $option=0)
Return if a text is a html content.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
$conf db user
Active Directory does not allow anonymous connections.
Definition repair.php:162
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:158
getMaxFileSizeArray()
Return the max allowed for file upload.