dolibarr 21.0.0-beta
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 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 // Required to show preview wof mail attachments
476 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
477 $formfile = new FormFile($this->db);
478
479 if (!is_object($form)) {
480 $form = new Form($this->db);
481 }
482
483 // Load translation files required by the page
484 $langs->loadLangs(array('other', 'mails', 'members'));
485
486 // Clear temp files. Must be done before call of triggers, at beginning (mode = init), or when we select a new template
487 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
488 $this->clear_attached_files();
489 }
490
491 // Call hook getFormMail
492 $hookmanager->initHooks(array('formmail'));
493
494 $parameters = array(
495 'addfileaction' => $addfileaction,
496 'removefileaction' => $removefileaction,
497 'trackid' => $this->trackid
498 );
499 $reshook = $hookmanager->executeHooks('getFormMail', $parameters, $this);
500
501 if (!empty($reshook)) {
502 return $hookmanager->resPrint;
503 } else {
504 $out = '';
505
506 $disablebademails = 1;
507
508 // Define output language
509 $outputlangs = $langs;
510 $newlang = '';
511 if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($this->param['langsmodels'])) {
512 $newlang = $this->param['langsmodels'];
513 }
514 if (!empty($newlang)) {
515 $outputlangs = new Translate("", $conf);
516 $outputlangs->setDefaultLang($newlang);
517 $outputlangs->load('other');
518 }
519
520 // Get message template for $this->param["models"] into c_email_templates
521 $arraydefaultmessage = -1;
522 if ($this->param['models'] != 'none') {
523 $model_id = 0;
524 if (array_key_exists('models_id', $this->param)) {
525 $model_id = $this->param["models_id"];
526 }
527
528 $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
529 }
530
531 // Define list of attached files
532 $listofpaths = array();
533 $listofnames = array();
534 $listofmimes = array();
535 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
536
537 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
538 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
539 foreach ($this->param['fileinit'] as $path) {
540 if (!empty($path)) {
541 $this->add_attached_files($path);
542 }
543 }
544 }
545 }
546
547 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
548 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
549 }
550 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
551 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
552 }
553 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
554 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
555 }
556
557
558 $out .= "\n".'<!-- Begin form mail type='.$this->param["models"].' --><div id="mailformdiv"></div>'."\n";
559 if ($this->withform == 1) {
560 $out .= '<form method="POST" name="mailform" id="mailform" enctype="multipart/form-data" action="'.$this->param["returnurl"].'#formmail">'."\n";
561
562 $out .= '<a id="formmail" name="formmail"></a>';
563 $out .= '<input style="display:none" type="submit" id="sendmailhidden" name="sendmail">';
564 $out .= '<input type="hidden" name="token" value="'.newToken().'" />';
565 $out .= '<input type="hidden" name="trackid" value="'.$this->trackid.'" />';
566 $out .= '<input type="hidden" name="inreplyto" value="'.$this->inreplyto.'" />';
567 }
568 if (!empty($this->withfrom)) {
569 if (!empty($this->withfromreadonly)) {
570 $out .= '<input type="hidden" id="fromname" name="fromname" value="'.$this->fromname.'" />';
571 $out .= '<input type="hidden" id="frommail" name="frommail" value="'.$this->frommail.'" />';
572 }
573 }
574 foreach ($this->param as $key => $value) {
575 if (is_array($value)) {
576 $out .= "<!-- param key=".$key." is array, we do not output input field for it -->\n";
577 } else {
578 $out .= '<input type="hidden" id="'.$key.'" name="'.$key.'" value="'.$value.'" />'."\n";
579 }
580 }
581
582 $modelmail_array = array();
583 if ($this->param['models'] != 'none') {
584 $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
585 if ($result < 0) {
586 setEventMessages($this->error, $this->errors, 'errors');
587 }
588
589 foreach ($this->lines_model as $line) {
590 $reg = array();
591 if (preg_match('/\‍((.*)\‍)/', $line->label, $reg)) {
592 $labeltouse = $langs->trans($reg[1]); // langs->trans when label is __(xxx)__
593 } else {
594 $labeltouse = $line->label;
595 }
596
597 // We escape the $labeltouse to store it into $modelmail_array.
598 $modelmail_array[$line->id] = dol_escape_htmltag($labeltouse);
599 if ($line->lang) {
600 $modelmail_array[$line->id] .= ' '.picto_from_langcode($line->lang);
601 }
602 if ($line->private) {
603 $modelmail_array[$line->id] .= ' - <span class="opacitymedium">'.dol_escape_htmltag($langs->trans("Private")).'</span>';
604 }
605 }
606 }
607
608 // Zone to select email template
609 if (count($modelmail_array) > 0) {
610 $model_mail_selected_id = GETPOSTISSET('modelmailselected') ? GETPOSTINT('modelmailselected') : ($arraydefaultmessage->id > 0 ? $arraydefaultmessage->id : 0);
611
612 // If list of template is filled
613 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
614
615 $out .= $this->selectarray('modelmailselected', $modelmail_array, $model_mail_selected_id, $langs->trans('SelectMailModel'), 0, 0, '', 0, 0, 0, '', 'minwidth100', 1, '', 0, 1);
616 if ($user->admin) {
617 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
618 }
619
620 $out .= ' &nbsp; ';
621 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
622 $out .= ' &nbsp; ';
623 $out .= '</div>';
624 } elseif (!empty($this->param['models']) && in_array($this->param['models'], array(
625 'propal_send', 'order_send', 'facture_send',
626 'shipping_send', 'fichinter_send', 'supplier_proposal_send', 'order_supplier_send',
627 'invoice_supplier_send', 'thirdparty', 'contract', 'user', 'recruitmentcandidature_send', 'all'
628 ))) {
629 // If list of template is empty
630 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
631 $out .= '<span class="opacitymedium">'.$langs->trans('SelectMailModel').':</span> ';
632 $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.
633 if ($user->admin) {
634 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
635 }
636 $out .= ' &nbsp; ';
637 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" disabled="disabled" id="modelselected">';
638 $out .= ' &nbsp; ';
639 $out .= '</div>';
640 } else {
641 $out .= '<!-- No template available for $this->param["models"] = '.$this->param['models'].' -->';
642 }
643
644
645 $out .= '<table class="tableforemailform boxtablenotop centpercent">'."\n";
646
647 // Substitution array/string
648 $helpforsubstitution = '';
649 if (is_array($this->substit) && count($this->substit)) {
650 $helpforsubstitution .= $langs->trans('AvailableVariables').' :<br><br><span class="small">'."\n";
651 }
652 foreach ($this->substit as $key => $val) {
653 // Do not show deprecated variables into the tooltip help of substitution variables
654 if (in_array($key, array('__NEWREF__', '__REFCLIENT__', '__REFSUPPLIER__', '__SUPPLIER_ORDER_DATE_DELIVERY__', '__SUPPLIER_ORDER_DELAY_DELIVERY__'))) {
655 continue;
656 }
657 $helpforsubstitution .= $key.' -> '.$langs->trans(dol_string_nohtmltag(dolGetFirstLineOfText($val))).'<br>';
658 }
659 if (is_array($this->substit) && count($this->substit)) {
660 $helpforsubstitution .= '</span>';
661 }
662
663 /*
664 if (!empty($this->withsubstit)) { // Unset or set ->withsubstit=0 to disable this.
665 $out .= '<tr><td colspan="2" class="right">';
666 if (is_numeric($this->withsubstit)) {
667 $out .= $form->textwithpicto($langs->trans("EMailTestSubstitutionReplacedByGenericValues"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // Old usage
668 } else {
669 $out .= $form->textwithpicto($langs->trans('AvailableVariables'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // New usage
670 }
671 $out .= "</td></tr>\n";
672 }*/
673
674 // From
675 if (!empty($this->withfrom)) {
676 if (!empty($this->withfromreadonly)) {
677 $out .= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
678
679 // $this->fromtype is the default value to use to select sender
680 if (!($this->fromtype === 'user' && $this->fromid > 0)
681 && !($this->fromtype === 'company')
682 && !($this->fromtype === 'robot')
683 && !preg_match('/user_aliases/', $this->fromtype)
684 && !preg_match('/global_aliases/', $this->fromtype)
685 && !preg_match('/senderprofile/', $this->fromtype)
686 ) {
687 // Use this->fromname and this->frommail or error if not defined
688 $out .= $this->fromname;
689 if ($this->frommail) {
690 $out .= ' &lt;'.$this->frommail.'&gt;';
691 } else {
692 if ($this->fromtype) {
693 $langs->load('errors');
694 $out .= '<span class="warning"> &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt; </span>';
695 }
696 }
697 } else {
698 $liste = array();
699
700 // Add user email
701 if (empty($user->email)) {
702 $langs->load('errors');
703 $s = $user->getFullName($langs).' &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt;';
704 } else {
705 $s = $user->getFullName($langs).' &lt;'.$user->email.'&gt;';
706 }
707 $liste['user'] = array('label' => $s, 'data-html' => $s);
708
709 // Add also company main email
710 if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
711 $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;';
712 $liste['company'] = array('label' => $s, 'data-html' => $s);
713 }
714
715 // Add also email aliases if there is some
716 $listaliases = array(
717 'user_aliases' => (empty($user->email_aliases) ? '' : $user->email_aliases),
718 'global_aliases' => getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES'),
719 );
720
721 if (!empty($arraydefaultmessage->email_from)) {
722 $templatemailfrom = ' &lt;'.$arraydefaultmessage->email_from.'&gt;';
723 $liste['from_template_'.GETPOST('modelmailselected')] = array('label' => $templatemailfrom, 'data-html' => $templatemailfrom);
724 }
725
726 // Also add robot email
727 if (!empty($this->fromalsorobot)) {
728 if (getDolGlobalString('MAIN_MAIL_EMAIL_FROM') && getDolGlobalString('MAIN_MAIL_EMAIL_FROM') != getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
729 $s = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
730 if ($this->frommail) {
731 $s .= ' &lt;' . getDolGlobalString('MAIN_MAIL_EMAIL_FROM').'&gt;';
732 }
733 $liste['main_from'] = array('label' => $s, 'data-html' => $s);
734 }
735 }
736
737 // Add also email aliases from the c_email_senderprofile table
738 $sql = "SELECT rowid, label, email FROM ".$this->db->prefix()."c_email_senderprofile";
739 $sql .= " WHERE active = 1 AND (private = 0 OR private = ".((int) $user->id).")";
740 $sql .= " ORDER BY position";
741 $resql = $this->db->query($sql);
742 if ($resql) {
743 $num = $this->db->num_rows($resql);
744 $i = 0;
745 while ($i < $num) {
746 $obj = $this->db->fetch_object($resql);
747 if ($obj) {
748 $listaliases['senderprofile_'.$obj->rowid] = $obj->label.' <'.$obj->email.'>';
749 }
750 $i++;
751 }
752 } else {
753 dol_print_error($this->db);
754 }
755
756 foreach ($listaliases as $typealias => $listalias) {
757 $posalias = 0;
758 $listaliasarray = explode(',', $listalias);
759 foreach ($listaliasarray as $listaliasval) {
760 $posalias++;
761 $listaliasval = trim($listaliasval);
762 if ($listaliasval) {
763 $listaliasval = preg_replace('/</', '&lt;', $listaliasval);
764 $listaliasval = preg_replace('/>/', '&gt;', $listaliasval);
765 if (!preg_match('/&lt;/', $listaliasval)) {
766 $listaliasval = '&lt;'.$listaliasval.'&gt;';
767 }
768 $liste[$typealias.'_'.$posalias] = array('label' => $listaliasval, 'data-html' => $listaliasval);
769 }
770 }
771 }
772
773 // Using ajaxcombo here make the '<email>' no more visible on list because <emailofuser> is not a valid html tag,
774 // so we transform before each record into $liste to be printable with ajaxcombo by replacing <> into ()
775 // $liste['senderprofile_0_0'] = array('label'=>'rrr', 'data-html'=>'rrr &lt;aaaa&gt;');
776 foreach ($liste as $key => $val) {
777 if (!empty($liste[$key]['data-html'])) {
778 $liste[$key]['data-html'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $liste[$key]['data-html']);
779 $liste[$key]['data-html'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $liste[$key]['data-html']);
780 }
781 }
782 $out .= ' '.$form->selectarray('fromtype', $liste, empty($arraydefaultmessage->email_from) ? $this->fromtype : 'from_template_'.GETPOST('modelmailselected'), 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 1, '', $disablebademails);
783 }
784
785 $out .= "</td></tr>\n";
786 } else {
787 $out .= '<tr><td class="fieldrequired width200">'.$langs->trans("MailFrom")."</td><td>";
788 $out .= $langs->trans("Name").':<input type="text" id="fromname" name="fromname" class="maxwidth200onsmartphone" value="'.$this->fromname.'" />';
789 $out .= '&nbsp; &nbsp; ';
790 $out .= $langs->trans("EMail").':&lt;<input type="text" id="frommail" name="frommail" class="maxwidth200onsmartphone" value="'.$this->frommail.'" />&gt;';
791 $out .= "</td></tr>\n";
792 }
793 }
794
795 // To
796 if (!empty($this->withto) || is_array($this->withto)) {
797 $out .= $this->getHtmlForTo();
798 }
799
800 // To User
801 if (!empty($this->withtouser) && is_array($this->withtouser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
802 $out .= '<tr><td>';
803 $out .= $langs->trans("MailToUsers");
804 $out .= '</td><td>';
805
806 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
807 $tmparray = $this->withtouser;
808 foreach ($tmparray as $key => $val) {
809 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
810 }
811 $withtoselected = GETPOST("receiveruser", 'array'); // Array of selected value
812 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
813 $withtoselected = array_keys($tmparray);
814 }
815 $out .= $form->multiselectarray("receiveruser", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, "");
816 $out .= "</td></tr>\n";
817 }
818
819 // With option for one email per recipient
820 if (!empty($this->withoptiononeemailperrecipient)) {
821 if (abs($this->withoptiononeemailperrecipient) == 1) {
822 $out .= '<tr><td class="minwidth200">';
823 $out .= $langs->trans("GroupEmails");
824 $out .= '</td><td>';
825 $out .= ' <input type="checkbox" id="oneemailperrecipient" value="1" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> ';
826 $out .= '<label for="oneemailperrecipient">';
827 $out .= $form->textwithpicto($langs->trans("OneEmailPerRecipient"), $langs->trans("WarningIfYouCheckOneRecipientPerEmail"), 1, 'help');
828 $out .= '</label>';
829 //$out .= '<span class="hideonsmartphone opacitymedium">';
830 //$out .= ' - ';
831 //$out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
832 //$out .= '</span>';
833 if (getDolGlobalString('MASS_ACTION_EMAIL_ON_DIFFERENT_THIRPARTIES_ADD_CUSTOM_EMAIL')) {
834 if (!empty($this->withto) && !is_array($this->withto)) {
835 $out .= ' '.$langs->trans("or").' <input type="email" name="emailto" value="">';
836 }
837 }
838 $out .= '</td></tr>';
839 } else {
840 $out .= '<tr><td><input type="hidden" name="oneemailperrecipient" value="1"></td><td></td></tr>';
841 }
842 }
843
844 // CC
845 if (!empty($this->withtocc) || is_array($this->withtocc)) {
846 $out .= $this->getHtmlForCc();
847 }
848
849 // To User cc
850 if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
851 $out .= '<tr><td>';
852 $out .= $langs->trans("MailToCCUsers");
853 $out .= '</td><td>';
854
855 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
856 $tmparray = $this->withtoccuser;
857 foreach ($tmparray as $key => $val) {
858 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
859 }
860 $withtoselected = GETPOST("receiverccuser", 'array'); // Array of selected value
861 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
862 $withtoselected = array_keys($tmparray);
863 }
864 $out .= $form->multiselectarray("receiverccuser", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, "");
865 $out .= "</td></tr>\n";
866 }
867
868 // CCC
869 if (!empty($this->withtoccc) || is_array($this->withtoccc)) {
870 $out .= $this->getHtmlForWithCcc();
871 }
872
873 // Replyto
874 if (!empty($this->withreplyto)) {
875 if ($this->withreplytoreadonly) {
876 $out .= '<input type="hidden" id="replyname" name="replyname" value="'.$this->replytoname.'" />';
877 $out .= '<input type="hidden" id="replymail" name="replymail" value="'.$this->replytomail.'" />';
878 $out .= "<tr><td>".$langs->trans("MailReply")."</td><td>".$this->replytoname.($this->replytomail ? (" &lt;".$this->replytomail."&gt;") : "");
879 $out .= "</td></tr>\n";
880 }
881 }
882
883 // Errorsto
884 if (!empty($this->witherrorsto)) {
885 $out .= $this->getHtmlForWithErrorsTo();
886 }
887
888 // Ask delivery receipt
889 if (!empty($this->withdeliveryreceipt) && getDolGlobalInt('MAIN_EMAIL_SUPPORT_ACK')) {
890 $out .= $this->getHtmlForDeliveryreceipt();
891 }
892
893 // Topic
894 if (!empty($this->withtopic)) {
895 $out .= $this->getHtmlForTopic($arraydefaultmessage, $helpforsubstitution);
896 }
897
898 // Attached files
899 if (!empty($this->withfile)) {
900 $out .= '<tr>';
901 $out .= '<td class="tdtop">'.$langs->trans("MailFile").'</td>';
902
903 $out .= '<td>';
904
905 if ($this->withmaindocfile) {
906 // withmaindocfile is set to 1 or -1 to show the checkbox (-1 = checked or 1 = not checked)
907 if (GETPOSTISSET('sendmail')) {
908 $this->withmaindocfile = (GETPOST('addmaindocfile', 'alpha') ? -1 : 1);
909 } elseif (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
910 // If a template was selected, we use setup of template to define if join file checkbox is selected or not.
911 $this->withmaindocfile = ($arraydefaultmessage->joinfiles ? -1 : 1);
912 }
913 }
914
915 if (!empty($this->withmaindocfile)) {
916 if ($this->withmaindocfile == 1) {
917 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" />';
918 } elseif ($this->withmaindocfile == -1) {
919 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" checked="checked" />';
920 }
921 if (getDolGlobalString('MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND')) {
922 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDocOrLastGenerated").'.</label><br>';
923 } else {
924 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDoc").'.</label><br>';
925 }
926 }
927
928 if (is_numeric($this->withfile)) {
929 // TODO Trick to have param removedfile containing nb of file to delete. But this does not works without javascript
930 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
931 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
932 $out .= 'jQuery(document).ready(function () {';
933 $out .= ' jQuery(".removedfile").click(function() {';
934 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
935 $out .= ' });';
936 $out .= '})';
937 $out .= '</script>'."\n";
938 if (count($listofpaths)) {
939 foreach ($listofpaths as $key => $val) {
940 $relativepathtofile = substr($val, (strlen(DOL_DATA_ROOT) - strlen($val)));
941
942 $entity = (isset($this->param['object_entity']) ? $this->param['object_entity'] : $conf->entity);
943 if ($entity > 1) {
944 $relativepathtofile = str_replace('/'.$entity.'/', '/', $relativepathtofile);
945 }
946 // Try to extract data from full path
947 $formfile_params = array();
948 preg_match('#^(/)(\w+)(/)(.+)$#', $relativepathtofile, $formfile_params);
949
950 $out .= '<div id="attachfile_'.$key.'">';
951 // Preview of attachment
952 $out .= img_mime($listofnames[$key]).$listofnames[$key];
953
954 $out .= ' '.$formfile->showPreview(array(), $formfile_params[2], $formfile_params[4], 0, ($entity == 1 ? '' : 'entity='.((int) $entity)));
955
956 if (!$this->withfilereadonly) {
957 $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.'" />';
958 //$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>';
959 }
960 $out .= '<br></div>';
961 }
962 } /*elseif (empty($this->withmaindocfile)) {
963 //$out .= '<span class="opacitymedium">'.$langs->trans("NoAttachedFiles").'</span><br>';
964 }*/
965 if ($this->withfile == 2) {
966 $maxfilesizearray = getMaxFileSizeArray();
967 $maxmin = $maxfilesizearray['maxmin'];
968 if ($maxmin > 0) {
969 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
970 }
971 // Can add other files
972 if (!getDolGlobalString('FROM_MAIL_DONT_USE_INPUT_FILE_MULTIPLE')) {
973 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile[]" value="'.$langs->trans("Upload").'" multiple />';
974 } else {
975 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
976 }
977 $out .= ' ';
978 $out .= '<input type="submit" class="button smallpaddingimp" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
979 }
980 } else {
981 $out .= $this->withfile;
982 }
983
984 $out .= "</td></tr>\n";
985 }
986
987 // Message (+ Links to choose layout or ai prompt)
988 if (!empty($this->withbody)) {
989 $defaultmessage = GETPOST('message', 'restricthtml');
990 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
991 if ($arraydefaultmessage && $arraydefaultmessage->content) {
992 $defaultmessage = $arraydefaultmessage->content;
993 } elseif (!is_numeric($this->withbody)) {
994 $defaultmessage = $this->withbody;
995 }
996 }
997
998 // Complete substitution array with the url to make online payment
999 $paymenturl = '';
1000 // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
1001 require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
1002 $validpaymentmethod = getValidOnlinePaymentMethods('');
1003
1004 if (empty($this->substit['__REF__'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
1005 $paymenturl = '';
1006 } else {
1007 $langs->loadLangs(array('paypal', 'other'));
1008 $typeforonlinepayment = 'free';
1009 if ($this->param["models"] == 'order' || $this->param["models"] == 'order_send') {
1010 $typeforonlinepayment = 'order'; // TODO use detection on something else than template
1011 }
1012 if ($this->param["models"] == 'invoice' || $this->param["models"] == 'facture_send') {
1013 $typeforonlinepayment = 'invoice'; // TODO use detection on something else than template
1014 }
1015 if ($this->param["models"] == 'member') {
1016 $typeforonlinepayment = 'member'; // TODO use detection on something else than template
1017 }
1018 $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']);
1019 $paymenturl = $url;
1020 }
1021
1022 if (count($validpaymentmethod) > 0 && $paymenturl) {
1023 $langs->load('other');
1024 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = str_replace('\n', "\n", $langs->transnoentities("PredefinedMailContentLink", $paymenturl));
1025 $this->substit['__ONLINE_PAYMENT_URL__'] = $paymenturl;
1026 } elseif (count($validpaymentmethod) > 0) {
1027 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = '__ONLINE_PAYMENT_TEXT_AND_URL__';
1028 $this->substit['__ONLINE_PAYMENT_URL__'] = '__ONLINE_PAYMENT_URL__';
1029 } else {
1030 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = '';
1031 $this->substit['__ONLINE_PAYMENT_URL__'] = '';
1032 }
1033
1034 $this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'] = '';
1035
1036 // Generate the string with the template for lines repeated and filled for each line
1037 $lines = '';
1038 $defaultlines = $arraydefaultmessage->content_lines;
1039 if (isset($defaultlines)) {
1040 foreach ($this->substit_lines as $lineid => $substit_line) {
1041 $lines .= make_substitutions($defaultlines, $substit_line)."\n";
1042 }
1043 }
1044 $this->substit['__LINES__'] = $lines;
1045
1046 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1047
1048 // Deal with format differences between message and some substitution variables (text / HTML)
1049 $atleastonecomponentishtml = 0;
1050 if (strpos($defaultmessage, '__USER_SIGNATURE__') !== false && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1051 $atleastonecomponentishtml++;
1052 }
1053 if (strpos($defaultmessage, '__SENDEREMAIL_SIGNATURE__') !== false && dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
1054 $atleastonecomponentishtml++;
1055 }
1056 if (strpos($defaultmessage, '__ONLINE_PAYMENT_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
1057 $atleastonecomponentishtml++;
1058 }
1059 if (strpos($defaultmessage, '__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'])) {
1060 $atleastonecomponentishtml++;
1061 }
1062 if (dol_textishtml($defaultmessage)) {
1063 $atleastonecomponentishtml++;
1064 }
1065 if ($atleastonecomponentishtml) {
1066 if (!dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1067 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1068 }
1069 if (!dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
1070 $this->substit['__SENDEREMAIL_SIGNATURE__'] = dol_nl2br($this->substit['__SENDEREMAIL_SIGNATURE__']);
1071 }
1072 if (!dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
1073 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = dol_nl2br($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']);
1074 }
1075 if (!dol_textishtml($defaultmessage)) {
1076 $defaultmessage = dol_nl2br($defaultmessage);
1077 }
1078 }
1079
1080 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1081 $defaultmessage = GETPOST("message", "restricthtml");
1082 } else {
1083 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1084 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1085 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1086 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1087 }
1088
1089 $out .= '<tr>';
1090 $out .= '<td class="tdtop">';
1091 $out .= $form->textwithpicto($langs->trans('MailText'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
1092 $out .= '</td>';
1093 $out .= '<td class="tdtop">';
1094
1095 $formmail = $this;
1096 $showlinktolayout = ($formmail->withfckeditor && getDolGlobalInt('MAIN_EMAIL_USE_LAYOUT')) ? $formmail->withlayout : '';
1097 $showlinktolayoutlabel = $langs->trans("FillMessageWithALayout");
1098 $showlinktoai = ($formmail->withaiprompt && isModEnabled('ai')) ? 'textgenerationemail' : '';
1099 $showlinktoailabel = $langs->trans("FillMessageWithAIContent");
1100 $formatforouput = '';
1101 $htmlname = 'message';
1102
1103 // Fill $out
1104 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
1105
1106 $out .= '</td>';
1107 $out .= '</tr>';
1108
1109 $out .= '<tr>';
1110 $out .= '<td colspan="2">';
1111 if ($this->withbodyreadonly) {
1112 $out .= nl2br($defaultmessage);
1113 $out .= '<input type="hidden" id="message" name="message" disabled value="'.$defaultmessage.'" />';
1114 } else {
1115 if (!isset($this->ckeditortoolbar)) {
1116 $this->ckeditortoolbar = 'dolibarr_mailings';
1117 }
1118
1119 // Editor wysiwyg
1120 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1121 if ($this->withfckeditor == -1) {
1122 if (getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) {
1123 $this->withfckeditor = 1;
1124 } else {
1125 $this->withfckeditor = 0;
1126 }
1127 }
1128
1129 $doleditor = new DolEditor('message', $defaultmessage, '', 280, $this->ckeditortoolbar, 'In', true, true, $this->withfckeditor, 8, '95%');
1130 $out .= $doleditor->Create(1);
1131 }
1132 $out .= "</td></tr>\n";
1133 }
1134
1135 $out .= '</table>'."\n";
1136
1137 if ($this->withform == 1 || $this->withform == -1) {
1138 $out .= '<div class="center">';
1139 $out .= '<input type="submit" class="button button-add" id="sendmail" name="sendmail" value="'.$langs->trans("SendMail").'"';
1140 // Add a javascript test to avoid to forget to submit file before sending email
1141 if ($this->withfile == 2 && $conf->use_javascript_ajax) {
1142 $out .= ' onClick="if (document.mailform.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1143 }
1144 $out .= ' />';
1145 if ($this->withcancel) {
1146 $out .= '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'" />';
1147 }
1148 $out .= '</div>'."\n";
1149 }
1150
1151 if ($this->withform == 1) {
1152 $out .= '</form>'."\n";
1153 }
1154
1155 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1156 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1157 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1158 $out .= 'jQuery(document).ready(function () {';
1159 $out .= ' $(document).on("keypress", \'#mailform\', function (e) { /* Note this is called at every key pressed ! */
1160 var code = e.keyCode || e.which;
1161 if (code == 13) {
1162 console.log("Enter was intercepted and blocked");
1163 e.preventDefault();
1164 return false;
1165 }
1166 });';
1167 $out .= ' })';
1168 $out .= '</script>';
1169 }
1170
1171 $out .= "<!-- End form mail -->\n";
1172
1173 return $out;
1174 }
1175 }
1176
1182 public function getHtmlForTo()
1183 {
1184 global $langs, $form;
1185 $out = '<tr><td class="fieldrequired">';
1186 if ($this->withtofree) {
1187 $out .= $form->textwithpicto($langs->trans("MailTo"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1188 } else {
1189 $out .= $langs->trans("MailTo");
1190 }
1191 $out .= '</td><td>';
1192 if ($this->withtoreadonly) {
1193 if (!empty($this->toname) && !empty($this->tomail)) {
1194 $out .= '<input type="hidden" id="toname" name="toname" value="'.$this->toname.'" />';
1195 $out .= '<input type="hidden" id="tomail" name="tomail" value="'.$this->tomail.'" />';
1196 if ($this->totype == 'thirdparty') {
1197 $soc = new Societe($this->db);
1198 $soc->fetch($this->toid);
1199 $out .= $soc->getNomUrl(1);
1200 } elseif ($this->totype == 'contact') {
1201 $contact = new Contact($this->db);
1202 $contact->fetch($this->toid);
1203 $out .= $contact->getNomUrl(1);
1204 } else {
1205 $out .= $this->toname;
1206 }
1207 $out .= ' &lt;'.$this->tomail.'&gt;';
1208 if ($this->withtofree) {
1209 $out .= '<br>'.$langs->trans("and").' <input class="minwidth200" id="sendto" name="sendto" value="'.(!is_array($this->withto) && !is_numeric($this->withto) ? (GETPOSTISSET("sendto") ? GETPOST("sendto") : $this->withto) : "").'" />';
1210 }
1211 } else {
1212 // Note withto may be a text like 'AllRecipientSelected'
1213 $out .= (!is_array($this->withto) && !is_numeric($this->withto)) ? $this->withto : "";
1214 }
1215 } else {
1216 // The free input of email
1217 if (!empty($this->withtofree)) {
1218 $out .= '<input class="minwidth200" id="sendto" name="sendto" value="'.(($this->withtofree && !is_numeric($this->withtofree)) ? $this->withtofree : (!is_array($this->withto) && !is_numeric($this->withto) ? (GETPOSTISSET("sendto") ? GETPOST("sendto") : $this->withto) : "")).'" />';
1219 }
1220 // The select combo
1221 if (!empty($this->withto) && is_array($this->withto)) {
1222 if (!empty($this->withtofree)) {
1223 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1224 }
1225
1226 $tmparray = $this->withto;
1227 foreach ($tmparray as $key => $val) {
1228 if (is_array($val)) {
1229 $label = $val['label'];
1230 } else {
1231 $label = $val;
1232 }
1233
1234 $tmparray[$key] = array();
1235 $tmparray[$key]['id'] = $key;
1236
1237 $tmparray[$key]['label'] = $label;
1238 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1239 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1240 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1241
1242 $tmparray[$key]['labelhtml'] = $label;
1243 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1244 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1245 }
1246
1247 $withtoselected = GETPOST("receiver", 'array'); // Array of selected value
1248 if (!getDolGlobalInt('MAIN_MAIL_NO_WITH_TO_SELECTED')) {
1249 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
1250 $withtoselected = array_keys($tmparray);
1251 }
1252 }
1253
1254 $out .= $form->multiselectarray("receiver", $tmparray, $withtoselected, 0, 0, 'inline-block minwidth500', 0, 0);
1255 }
1256 }
1257 $out .= "</td></tr>\n";
1258 return $out;
1259 }
1260
1266 public function getHtmlForCc()
1267 {
1268 global $langs, $form;
1269 $out = '<tr><td>';
1270 $out .= $form->textwithpicto($langs->trans("MailCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1271 $out .= '</td><td>';
1272 if ($this->withtoccreadonly) {
1273 $out .= (!is_array($this->withtocc) && !is_numeric($this->withtocc)) ? $this->withtocc : "";
1274 } else {
1275 $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 : '')).'" />';
1276 if (!empty($this->withtocc) && is_array($this->withtocc)) {
1277 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1278
1279 $tmparray = $this->withtocc;
1280 foreach ($tmparray as $key => $val) {
1281 if (is_array($val)) {
1282 $label = $val['label'];
1283 } else {
1284 $label = $val;
1285 }
1286
1287 $tmparray[$key] = array();
1288 $tmparray[$key]['id'] = $key;
1289
1290 $tmparray[$key]['label'] = $label;
1291 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1292 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1293 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1294
1295 $tmparray[$key]['labelhtml'] = $label;
1296 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1297 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1298 }
1299
1300 $withtoccselected = GETPOST("receivercc", 'array'); // Array of selected value
1301
1302 $out .= $form->multiselectarray("receivercc", $tmparray, $withtoccselected, 0, 0, 'inline-block minwidth500', 0, 0);
1303 }
1304 }
1305 $out .= "</td></tr>\n";
1306 return $out;
1307 }
1308
1315 public function getHtmlForWithCcc()
1316 {
1317 global $langs, $form;
1318
1319 $out = '<tr><td>';
1320 $out .= $form->textwithpicto($langs->trans("MailCCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1321 $out .= '</td><td>';
1322 if (!empty($this->withtocccreadonly)) {
1323 $out .= (!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : "";
1324 } else {
1325 $out .= '<input class="minwidth200" id="sendtoccc" name="sendtoccc" value="'.(GETPOSTISSET("sendtoccc") ? GETPOST("sendtoccc", "alpha") : ((!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />';
1326 if (!empty($this->withtoccc) && is_array($this->withtoccc)) {
1327 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1328
1329 $tmparray = $this->withtoccc;
1330 foreach ($tmparray as $key => $val) {
1331 if (is_array($val)) {
1332 $label = $val['label'];
1333 } else {
1334 $label = $val;
1335 }
1336 $tmparray[$key] = array();
1337 $tmparray[$key]['id'] = $key;
1338
1339 $tmparray[$key]['label'] = $label;
1340 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1341 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1342 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1343
1344 $tmparray[$key]['labelhtml'] = $label;
1345 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1346 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1347 }
1348
1349 $withtocccselected = GETPOST("receiverccc", 'array'); // Array of selected value
1350
1351 $out .= $form->multiselectarray("receiverccc", $tmparray, $withtocccselected, 0, 0, 'inline-block minwidth500', 0, 0);
1352 }
1353 }
1354
1355 $showinfobcc = '';
1356 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1357 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO');
1358 }
1359 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1360 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO');
1361 }
1362 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1363 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO');
1364 }
1365 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1366 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO');
1367 }
1368 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1369 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO');
1370 }
1371 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'invoice_supplier_send') {
1372 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO');
1373 }
1374 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.
1375 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROJECT_TO');
1376 }
1377 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO') && !empty($this->param['models']) && $this->param['models'] == 'shipping_send') {
1378 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO');
1379 }
1380 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO') && !empty($this->param['models']) && $this->param['models'] == 'reception_send') {
1381 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO');
1382 }
1383 if ($showinfobcc) {
1384 $out .= ' + '.$showinfobcc;
1385 }
1386 $out .= "</td></tr>\n";
1387 return $out;
1388 }
1389
1395 public function getHtmlForWithErrorsTo()
1396 {
1397 global $langs;
1398
1399 //if (! $this->errorstomail) $this->errorstomail=$this->frommail;
1400 $errorstomail = getDolGlobalString('MAIN_MAIL_ERRORS_TO', (!empty($this->errorstomail) ? $this->errorstomail : ''));
1401 if ($this->witherrorstoreadonly) {
1402 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1403 $out .= '<input type="hidden" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1404 $out .= $errorstomail;
1405 $out .= "</td></tr>\n";
1406 } else {
1407 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1408 $out .= '<input class="minwidth200" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1409 $out .= "</td></tr>\n";
1410 }
1411 return $out;
1412 }
1413
1419 public function getHtmlForDeliveryreceipt()
1420 {
1421 global $langs;
1422
1423 $out = '<tr><td><label for="deliveryreceipt">'.$langs->trans("DeliveryReceipt").'</label></td><td>';
1424
1425 if (!empty($this->withdeliveryreceiptreadonly)) {
1426 $out .= yn($this->withdeliveryreceipt);
1427 } else {
1428 $defaultvaluefordeliveryreceipt = 0;
1429 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_PROPAL') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1430 $defaultvaluefordeliveryreceipt = 1;
1431 }
1432 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_PROPOSAL') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1433 $defaultvaluefordeliveryreceipt = 1;
1434 }
1435 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1436 $defaultvaluefordeliveryreceipt = 1;
1437 }
1438 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_INVOICE') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1439 $defaultvaluefordeliveryreceipt = 1;
1440 }
1441 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1442 $defaultvaluefordeliveryreceipt = 1;
1443 }
1444 //$out .= $form->selectyesno('deliveryreceipt', (GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt), 1);
1445 $out .= '<input type="checkbox" id="deliveryreceipt" name="deliveryreceipt" value="1"'.((GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt) ? ' checked="checked"' : '').'>';
1446 }
1447 $out .= "</td></tr>\n";
1448 return $out;
1449 }
1450
1458 public function getHtmlForTopic($arraydefaultmessage, $helpforsubstitution)
1459 {
1460 global $langs, $form;
1461
1462 $defaulttopic = GETPOST('subject', 'restricthtml');
1463
1464 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
1465 if ($arraydefaultmessage && $arraydefaultmessage->topic) {
1466 $defaulttopic = $arraydefaultmessage->topic;
1467 } elseif (!is_numeric($this->withtopic)) {
1468 $defaulttopic = $this->withtopic;
1469 }
1470 }
1471
1472 $defaulttopic = make_substitutions($defaulttopic, $this->substit);
1473
1474 $out = '<tr>';
1475 $out .= '<td class="fieldrequired">';
1476 $out .= $form->textwithpicto($langs->trans('MailTopic'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
1477 $out .= '</td>';
1478 $out .= '<td>';
1479 if ($this->withtopicreadonly) {
1480 $out .= $defaulttopic;
1481 $out .= '<input type="hidden" class="quatrevingtpercent" id="subject" name="subject" value="'.$defaulttopic.'" />';
1482 } else {
1483 $out .= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'.((GETPOSTISSET("subject") && !GETPOST('modelselected')) ? GETPOST("subject") : ($defaulttopic ? $defaulttopic : '')).'" />';
1484 }
1485 $out .= "</td></tr>\n";
1486 return $out;
1487 }
1488
1497 public function getSectionForAIPrompt($function = 'textgeneration', $format = '', $htmlContent = 'message')
1498 {
1499 global $langs;
1500
1501 $langs->load("other");
1502
1503 $htmlContent = preg_replace('/[^a-z0-9_]/', '', $htmlContent);
1504
1505 $out = '<div id="ai_input'.$htmlContent.'" class="hidden paddingtop paddingbottom">';
1506 $out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions'.$htmlContent.'" name="instruction" placeholder="'.$langs->trans("EnterYourAIPromptHere").'..." />';
1507 $out .= '<input id="generate_button'.$htmlContent.'" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
1508 $out .= '<div id="ai_status_message'.$htmlContent.'" class="fieldrequired hideobject marginrightonly margintoponly">';
1509 $out .= '<i class="fa fa-spinner fa-spin fa-2x fa-fw valignmiddle marginrightonly"></i>'.$langs->trans("AIProcessingPleaseWait", getDolGlobalString('AI_API_SERVICE', 'chatgpt'));
1510 $out .= '</div>';
1511
1512 if ($function == 'imagegeneration') {
1513 $out .= '<div id="ai_image_result" class="margintoponly"></div>'; // Div for displaying the generated image
1514 }
1515
1516 $out .= "</div>\n";
1517
1518 $out .= "<script type='text/javascript'>
1519 $(document).ready(function() {
1520 // for keydown
1521 $('#ai_instructions".$htmlContent."').keydown(function(event) {
1522 if (event.keyCode === 13) {
1523 event.preventDefault();
1524 $('#generate_button".$htmlContent."').click();
1525 }
1526 });
1527
1528 $('#generate_button".$htmlContent."').click(function() {
1529 console.log('We click on generate_button".$htmlContent." ai button');
1530
1531 var instructions = $('#ai_instructions".$htmlContent."').val();
1532 var timeoutfinished = 0;
1533 var apicallfinished = 0;
1534
1535 $('#ai_status_message".$htmlContent."').show();
1536 $('.icon-container .loader').show();
1537 setTimeout(function() {
1538 timeoutfinished = 1;
1539 if (apicallfinished) {
1540 $('#ai_status_message".$htmlContent."').hide();
1541 }
1542 }, 2000);
1543
1544 if ('".$function."' === 'imagegeneration') {
1545 // Handle image generation request
1546 $.ajax({
1547 url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".currentToken()."',
1548 type: 'POST',
1549 contentType: 'application/json',
1550 data: JSON.stringify({
1551 'format': '".dol_escape_js($format)."', /* the format for output */
1552 'function': '".dol_escape_js($function)."', /* the AI feature to call */
1553 'instructions': instructions, /* the prompt string */
1554 }),
1555 success: function(response) {
1556 console.log('Received image URL: '+response);
1557 // Assuming response is the URL of the generated image
1558 var imageUrl = response;
1559 $('#ai_image_result').html('<img src=\"' + imageUrl + '\" alt=\"Generated Image\" />');
1560
1561 // Clear the input field
1562 $('#ai_instructions').val('');
1563
1564 apicallfinished = 1;
1565 if (timeoutfinished) {
1566 $('#ai_status_message').hide();
1567 }
1568 },
1569 error: function(xhr, status, error) {
1570 alert(error);
1571 console.error('error ajax', status, error);
1572 $('#ai_status_message').hide();
1573 }
1574 });
1575 } else {
1576
1577 // set editor in readonly
1578 if (CKEDITOR.instances.".$htmlContent.") {
1579 CKEDITOR.instances.".$htmlContent.".setReadOnly(1);
1580 }
1581
1582 $.ajax({
1583 url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".currentToken()."',
1584 type: 'POST',
1585 contentType: 'application/json',
1586 data: JSON.stringify({
1587 'format': '".dol_escape_js($format)."', /* the format for output */
1588 'function': '".dol_escape_js($function)."', /* the AI feature to call */
1589 'instructions': instructions, /* the prompt string */
1590 }),
1591 success: function(response) {
1592 console.log('Add response into field \'#".$htmlContent."\': '+response);
1593
1594 jQuery('#".$htmlContent."').val(response); // If #htmlcontent is a input name or textarea
1595 jQuery('#".$htmlContent."').html(response); // If #htmlContent is a div
1596 //jQuery('#".$htmlContent."preview').val(response);
1597
1598 if (CKEDITOR.instances) {
1599 var editorInstance = CKEDITOR.instances.".$htmlContent.";
1600 if (editorInstance) {
1601 editorInstance.setReadOnly(0);
1602 editorInstance.setData(response);
1603 }
1604 //var editorInstancepreview = CKEDITOR.instances.".$htmlContent."preview;
1605 //if (editorInstancepreview) {
1606 // editorInstancepreview.setData(response);
1607 //}
1608 }
1609
1610 // remove readonly
1611 $('#ai_instructions".$htmlContent."').val('');
1612
1613 apicallfinished = 1;
1614 if (timeoutfinished) {
1615 $('#ai_status_message".$htmlContent."').hide();
1616 }
1617 },
1618 error: function(xhr, status, error) {
1619 alert(error);
1620 console.error('error ajax', status, error);
1621 $('#ai_status_message".$htmlContent."').hide();
1622 }
1623
1624 });
1625 });
1626 });
1627 </script>
1628 ";
1629 return $out;
1630 }
1631
1639 public function getModelEmailTemplate($htmlContent = 'message', $showlinktolayout = 'email')
1640 {
1641 global $websitepage, $langs;
1642
1643 require_once DOL_DOCUMENT_ROOT.'/core/lib/emaillayout.lib.php';
1644 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1645 require_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
1646
1647 // Fetch blogs
1648 $websitepage = new WebsitePage($this->db);
1649 $arrayofblogs = $websitepage->fetchAll('', 'DESC', 'date_creation', 0, 0, array('type_container' => 'blogpost'));
1650
1651 $out = '<div id="template-selector" class="email-layout-container hidden" style="display:none;">';
1652
1653 // Define list of email layouts to use
1654 $layouts = array(
1655 'empty' => 'empty',
1656 );
1657 // Search available layouts on disk
1658 $arrayoflayoutemplates = dol_dir_list(DOL_DOCUMENT_ROOT.'/install/doctemplates/maillayout/', 'files', 0, '\.html$');
1659 foreach ($arrayoflayoutemplates as $layouttemplatefile) {
1660 $layoutname = preg_replace('/\.html$/i', '', $layouttemplatefile['name']);
1661
1662 // Exclude some layouts for some use cases
1663 if ($layoutname == 'news' && !in_array($showlinktolayout, array('emailing', 'websitepage'))) {
1664 continue;
1665 }
1666 if ($layoutname == 'products' && !in_array($showlinktolayout, array('emailing', 'websitepage'))) {
1667 continue;
1668 }
1669
1670 $layouts[$layoutname] = ucfirst($layoutname);
1671 }
1672 //}
1673 // TODO Add a hook to allow to complete the list
1674
1675 foreach ($layouts as $layout => $templateFunction) {
1676 $contentHtml = getHtmlOfLayout($layout);
1677
1678 $out .= '<div class="template-option" data-template="'.$layout.'" data-content="'.htmlentities($contentHtml).'">';
1679 $out .= '<img class="maillayout" alt="'.$layout.'" src="'.DOL_URL_ROOT.'/theme/common/maillayout/'.$layout.'.png" />';
1680 $out .= '<span class="template-option-text">'.$langs->trans($templateFunction).'</span>';
1681 $out .= '</div>';
1682 }
1683 $out .= '</div>';
1684
1685 // Prepare the array for multiselect
1686 $blogArray = array();
1687 if (!empty($arrayofblogs)) {
1688 foreach ($arrayofblogs as $blog) {
1689 $blogArray[$blog->id] = substr(htmlentities($blog->title), 0, 30);
1690 }
1691 }
1692
1693 // Use the multiselect array function to create the dropdown
1694 $out .= '<div id="post-dropdown-container" class="email-layout-container hidden" style="display:none;">';
1695 $out .= '<label for="blogpost-select">Select Posts: </label>';
1696 $out .= self::multiselectarray('blogpost-select', $blogArray);
1697 $out .= '</div>';
1698
1699 $out .= '<script type="text/javascript">
1700 $(document).ready(function() {
1701 $(".template-option").click(function() {
1702 var template = $(this).data("template");
1703 var subject = jQuery("#subject").val();
1704 var fromtype = jQuery("#fromtype").val();
1705 var sendto = jQuery("#sendto").val();
1706 var sendtocc = jQuery("#sendtocc").val();
1707 var sendtoccc = jQuery("#sendtoccc").val();
1708
1709 console.log("We choose a layout for email template=" + template + ", subject="+subject);
1710
1711 console.log("We choose a layout for email template " + template);
1712
1713 $(".template-option").removeClass("selected");
1714 $(this).addClass("selected");
1715
1716 var subject = $("#sujet").val();
1717
1718 var contentHtml = $(this).data("content");
1719 contentHtml = contentHtml.replace(/__SUBJECT__/g, subject);
1720
1721 if (template === "news") {
1722 $("#post-dropdown-container").show();
1723 console.log("Displaying dropdown for news template");
1724 } else {
1725 $("#post-dropdown-container").hide();
1726
1727 var csrfToken = "' .newToken().'";
1728 $.ajax({
1729 type: "POST",
1730 url: "'.DOL_URL_ROOT.'/core/ajax/mailtemplate.php",
1731 data: {
1732 template: template,
1733 subject: subject,
1734 fromtype: fromtype,
1735 sendto: sendto,
1736 sendtocc: sendtocc,
1737 sendtoccc: sendtoccc,
1738 content: contentHtml,
1739 selectedPosts: "[]",
1740 token: csrfToken
1741 },
1742 success: function(response) {
1743 jQuery("#'.$htmlContent.'").val(response);
1744 var editorInstance = CKEDITOR.instances["'.$htmlContent.'"];
1745 if (editorInstance) {
1746 editorInstance.setData(response);
1747 }
1748 },
1749 error: function(xhr, status, error) {
1750 console.error("An error occurred: " + xhr.responseText);
1751 }
1752 });
1753 }
1754 });
1755
1756 $("#blogpost-select").change(function() {
1757 var selectedIds = $(this).val();
1758 var contentHtml = $(".template-option.selected").data("content");
1759
1760 updateSelectedPostsContent(contentHtml, selectedIds);
1761 });
1762
1763 function updateSelectedPostsContent(contentHtml, selectedIds) {
1764 var csrfToken = "' .newToken().'";
1765 $.ajax({
1766 type: "POST",
1767 url: "/core/ajax/getnews.php",
1768 data: {
1769 selectedIds: JSON.stringify(selectedIds),
1770 token : csrfToken
1771 },
1772 success: function(response) {
1773 var selectedPosts = JSON.parse(response);
1774 var subject = $("#sujet").val();
1775
1776 contentHtml = contentHtml.replace(/__SUBJECT__/g, subject);
1777
1778 $.ajax({
1779 type: "POST",
1780 url: "/core/ajax/mailtemplate.php",
1781 data: {
1782 content: contentHtml,
1783 selectedPosts: selectedIds.join(","),
1784 token: csrfToken
1785 },
1786 success: function(response) {
1787 jQuery("#'.$htmlContent.'").val(response);
1788 var editorInstance = CKEDITOR.instances["'.$htmlContent.'"];
1789 if (editorInstance) {
1790 editorInstance.setData(response);
1791 }
1792 },
1793 error: function(xhr, status, error) {
1794 console.error("An error occurred: " + xhr.responseText);
1795 }
1796 });
1797 },
1798 error: function(xhr, status, error) {
1799 console.error("An error occurred: " + xhr.responseText);
1800 }
1801 });
1802 }
1803 });
1804 </script>';
1805
1806 return $out;
1807 }
1808
1826 public function getEMailTemplate($dbs, $type_template, $user, $outputlangs, $id = 0, $active = 1, $label = '', $defaultfortype = -1)
1827 {
1828 global $conf;
1829
1830 if ($id == -2 && empty($label)) {
1831 $this->error = 'LabelIsMandatoryWhenIdIs-2or-3';
1832 return -1;
1833 }
1834
1835 $ret = new ModelMail($dbs);
1836
1837 $languagetosearch = (is_object($outputlangs) ? $outputlangs->defaultlang : '');
1838 // Define $languagetosearchmain to fall back on main language (for example to get 'es_ES' for 'es_MX')
1839 $tmparray = explode('_', $languagetosearch);
1840 $languagetosearchmain = $tmparray[0].'_'.strtoupper($tmparray[0]);
1841 if ($languagetosearchmain == $languagetosearch) {
1842 $languagetosearchmain = '';
1843 }
1844
1845 $sql = "SELECT rowid, entity, module, label, type_template, topic, email_from, joinfiles, content, content_lines, lang, email_from, email_to, email_tocc, email_tobcc";
1846 $sql .= " FROM ".$dbs->prefix().'c_email_templates';
1847 $sql .= " WHERE (type_template = '".$dbs->escape($type_template)."' OR type_template = 'all')";
1848 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1849 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // Get all public or private owned
1850 if ($active >= 0) {
1851 $sql .= " AND active = ".((int) $active);
1852 }
1853 if ($defaultfortype >= 0) {
1854 $sql .= " AND defaultfortype = ".((int) $defaultfortype);
1855 }
1856 if ($label) {
1857 $sql .= " AND label = '".$dbs->escape($label)."'";
1858 }
1859 if (!($id > 0) && $languagetosearch) {
1860 $sql .= " AND (lang = '".$dbs->escape($languagetosearch)."'".($languagetosearchmain ? " OR lang = '".$dbs->escape($languagetosearchmain)."'" : "")." OR lang IS NULL OR lang = '')";
1861 }
1862 if ($id > 0) {
1863 $sql .= " AND rowid = ".(int) $id;
1864 }
1865 if ($id == -1) {
1866 $sql .= " AND position = 0";
1867 }
1868 $sql .= " AND entity IN(".getEntity('c_email_templates', 1).")";
1869 if ($languagetosearch) {
1870 $sql .= $dbs->order("position,lang,label", "ASC,DESC,ASC"); // We want line with lang set first, then with lang null or ''
1871 } else {
1872 $sql .= $dbs->order("position,lang,label", "ASC,ASC,ASC"); // If no language provided, we give priority to lang not defined
1873 }
1874 //$sql .= $dbs->plimit(1);
1875 //print $sql;
1876
1877 $resql = $dbs->query($sql);
1878 if (!$resql) {
1879 dol_print_error($dbs);
1880 return -1;
1881 }
1882
1883 // Get first found
1884 while (1) {
1885 $obj = $dbs->fetch_object($resql);
1886
1887 if ($obj) {
1888 // If template is for a module, check module is enabled; if not, take next template
1889 if ($obj->module) {
1890 $tempmodulekey = $obj->module;
1891 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
1892 continue;
1893 }
1894 }
1895
1896 // If a record was found
1897 $ret->id = $obj->rowid;
1898 $ret->module = $obj->module;
1899 $ret->label = $obj->label;
1900 $ret->lang = $obj->lang;
1901 $ret->topic = $obj->topic;
1902 $ret->content = $obj->content;
1903 $ret->content_lines = $obj->content_lines;
1904 $ret->joinfiles = $obj->joinfiles;
1905 $ret->email_from = $obj->email_from;
1906
1907 break;
1908 } else {
1909 // If no record found
1910 if ($id == -2) {
1911 // Not found with the provided label
1912 return -1;
1913 } else {
1914 // If there is no template at all
1915 $defaultmessage = '';
1916
1917 if ($type_template == 'body') {
1918 // Special case to use this->withbody as content
1919 $defaultmessage = $this->withbody;
1920 } elseif ($type_template == 'facture_send') {
1921 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoice");
1922 } elseif ($type_template == 'facture_relance') {
1923 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoiceReminder");
1924 } elseif ($type_template == 'propal_send') {
1925 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendProposal");
1926 } elseif ($type_template == 'supplier_proposal_send') {
1927 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierProposal");
1928 } elseif ($type_template == 'order_send') {
1929 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendOrder");
1930 } elseif ($type_template == 'order_supplier_send') {
1931 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierOrder");
1932 } elseif ($type_template == 'invoice_supplier_send') {
1933 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierInvoice");
1934 } elseif ($type_template == 'shipping_send') {
1935 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendShipping");
1936 } elseif ($type_template == 'fichinter_send') {
1937 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendFichInter");
1938 } elseif ($type_template == 'actioncomm_send') {
1939 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendActionComm");
1940 } elseif (!empty($type_template)) {
1941 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentGeneric");
1942 }
1943
1944 $ret->label = 'default';
1945 $ret->lang = $outputlangs->defaultlang;
1946 $ret->topic = '';
1947 $ret->joinfiles = 1;
1948 $ret->content = $defaultmessage;
1949 $ret->content_lines = '';
1950
1951 break;
1952 }
1953 }
1954 }
1955
1956 $dbs->free($resql);
1957
1958 return $ret;
1959 }
1960
1970 public function isEMailTemplate($type_template, $user, $outputlangs)
1971 {
1972 $sql = "SELECT label, topic, content, lang";
1973 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
1974 $sql .= " WHERE type_template='".$this->db->escape($type_template)."'";
1975 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1976 $sql .= " AND (fk_user is NULL or fk_user = 0 or fk_user = ".((int) $user->id).")";
1977 if (is_object($outputlangs)) {
1978 $sql .= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')";
1979 }
1980 $sql .= $this->db->order("lang,label", "ASC");
1981 //print $sql;
1982
1983 $resql = $this->db->query($sql);
1984 if ($resql) {
1985 $num = $this->db->num_rows($resql);
1986 $this->db->free($resql);
1987 return $num;
1988 } else {
1989 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
1990 return -1;
1991 }
1992 }
1993
2004 public function fetchAllEMailTemplate($type_template, $user, $outputlangs, $active = 1)
2005 {
2006 global $db, $conf;
2007
2008 $sql = "SELECT rowid, module, label, topic, content, content_lines, lang, fk_user, private, position";
2009 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
2010 $sql .= " WHERE type_template IN ('".$this->db->escape($type_template)."', 'all')";
2011 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
2012 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // See all public templates or templates I own.
2013 if ($active >= 0) {
2014 $sql .= " AND active = ".((int) $active);
2015 }
2016 //if (is_object($outputlangs)) $sql.= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')"; // Return all languages
2017 $sql .= $this->db->order("position,lang,label", "ASC");
2018 //print $sql;
2019
2020 $resql = $this->db->query($sql);
2021 if ($resql) {
2022 $num = $this->db->num_rows($resql);
2023 $this->lines_model = array();
2024 while ($obj = $this->db->fetch_object($resql)) {
2025 // If template is for a module, check module is enabled.
2026 if ($obj->module) {
2027 $tempmodulekey = $obj->module;
2028 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
2029 continue;
2030 }
2031 }
2032
2033 $line = new ModelMail($db);
2034 $line->id = $obj->rowid;
2035 $line->label = $obj->label;
2036 $line->lang = $obj->lang;
2037 $line->fk_user = $obj->fk_user;
2038 $line->private = $obj->private;
2039 $line->position = $obj->position;
2040 $line->topic = $obj->topic;
2041 $line->content = $obj->content;
2042 $line->content_lines = $obj->content_lines;
2043
2044 $this->lines_model[] = $line;
2045 }
2046 $this->db->free($resql);
2047 return $num;
2048 } else {
2049 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
2050 return -1;
2051 }
2052 }
2053
2054
2055
2064 public function setSubstitFromObject($object, $outputlangs)
2065 {
2066 global $extrafields;
2067
2068 $parameters = array();
2069 $tmparray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
2070 complete_substitutions_array($tmparray, $outputlangs, null, $parameters);
2071
2072 $this->substit = $tmparray;
2073
2074 // Fill substit_lines with each object lines content
2075 if (is_array($object->lines)) {
2076 foreach ($object->lines as $line) {
2077 $substit_line = array(
2078 '__PRODUCT_REF__' => isset($line->product_ref) ? $line->product_ref : '',
2079 '__PRODUCT_LABEL__' => isset($line->product_label) ? $line->product_label : '',
2080 '__PRODUCT_DESCRIPTION__' => isset($line->product_desc) ? $line->product_desc : '',
2081 '__LABEL__' => isset($line->label) ? $line->label : '',
2082 '__DESCRIPTION__' => isset($line->desc) ? $line->desc : '',
2083 '__DATE_START_YMD__' => dol_print_date($line->date_start, 'day', false, $outputlangs),
2084 '__DATE_END_YMD__' => dol_print_date($line->date_end, 'day', false, $outputlangs),
2085 '__QUANTITY__' => $line->qty,
2086 '__SUBPRICE__' => price($line->subprice),
2087 '__AMOUNT__' => price($line->total_ttc),
2088 '__AMOUNT_EXCL_TAX__' => price($line->total_ht)
2089 );
2090
2091 // Create dynamic tags for __PRODUCT_EXTRAFIELD_FIELD__
2092 if (!empty($line->fk_product)) {
2093 if (!is_object($extrafields)) {
2094 $extrafields = new ExtraFields($this->db);
2095 }
2096 $product = new Product($this->db);
2097 $product->fetch($line->fk_product, '', '', 1);
2098 $product->fetch_optionals();
2099
2100 $extrafields->fetch_name_optionals_label($product->table_element, true);
2101
2102 if (!empty($extrafields->attributes[$product->table_element]['label']) && is_array($extrafields->attributes[$product->table_element]['label']) && count($extrafields->attributes[$product->table_element]['label']) > 0) {
2103 foreach ($extrafields->attributes[$product->table_element]['label'] as $key => $label) {
2104 $substit_line['__PRODUCT_EXTRAFIELD_'.strtoupper($key).'__'] = isset($product->array_options['options_'.$key]) ? $product->array_options['options_'.$key] : '';
2105 }
2106 }
2107 }
2108
2109 $this->substit_lines[$line->id] = $substit_line; // @phan-suppress-current-line PhanTypeMismatchProperty
2110 }
2111 }
2112 }
2113
2122 public static function getAvailableSubstitKey($mode = 'formemail', $object = null)
2123 {
2124 global $langs;
2125
2126 $tmparray = array();
2127 if ($mode == 'formemail' || $mode == 'formemailwithlines' || $mode == 'formemailforlines') {
2128 $parameters = array('mode' => $mode);
2129 $tmparray = getCommonSubstitutionArray($langs, 2, null, $object); // Note: On email templated edition, this is null because it is related to all type of objects
2130 complete_substitutions_array($tmparray, $langs, null, $parameters);
2131
2132 if ($mode == 'formwithlines') {
2133 $tmparray['__LINES__'] = '__LINES__'; // Will be set by the get_form function
2134 }
2135 if ($mode == 'formforlines') {
2136 $tmparray['__QUANTITY__'] = '__QUANTITY__'; // Will be set by the get_form function
2137 }
2138 }
2139
2140 if ($mode == 'emailing') {
2141 $parameters = array('mode' => $mode);
2142 $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
2143 complete_substitutions_array($tmparray, $langs, null, $parameters);
2144
2145 // For mass emailing, we have different keys specific to the data into tagerts list
2146 $tmparray['__ID__'] = 'IdRecord';
2147 $tmparray['__THIRDPARTY_CUSTOMER_CODE__'] = 'CustomerCode';
2148 $tmparray['__EMAIL__'] = 'EMailRecipient';
2149 $tmparray['__LASTNAME__'] = 'Lastname';
2150 $tmparray['__FIRSTNAME__'] = 'Firstname';
2151 $tmparray['__MAILTOEMAIL__'] = 'TagMailtoEmail';
2152 $tmparray['__OTHER1__'] = 'Other1';
2153 $tmparray['__OTHER2__'] = 'Other2';
2154 $tmparray['__OTHER3__'] = 'Other3';
2155 $tmparray['__OTHER4__'] = 'Other4';
2156 $tmparray['__OTHER5__'] = 'Other5';
2157 $tmparray['__CHECK_READ__'] = $langs->trans('TagCheckMail');
2158 $tmparray['__UNSUBSCRIBE__'] = $langs->trans('TagUnsubscribe');
2159 $tmparray['__UNSUBSCRIBE_URL__'] = $langs->trans('TagUnsubscribe').' (URL)';
2160
2161 $onlinepaymentenabled = 0;
2162 if (isModEnabled('paypal')) {
2163 $onlinepaymentenabled++;
2164 }
2165 if (isModEnabled('paybox')) {
2166 $onlinepaymentenabled++;
2167 }
2168 if (isModEnabled('stripe')) {
2169 $onlinepaymentenabled++;
2170 }
2171 if ($onlinepaymentenabled && getDolGlobalString('PAYMENT_SECURITY_TOKEN')) {
2172 $tmparray['__SECUREKEYPAYMENT__'] = getDolGlobalString('PAYMENT_SECURITY_TOKEN');
2173 if (getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
2174 if (isModEnabled('member')) {
2175 $tmparray['__SECUREKEYPAYMENT_MEMBER__'] = 'SecureKeyPAYMENTUniquePerMember';
2176 }
2177 if (isModEnabled('don')) {
2178 $tmparray['__SECUREKEYPAYMENT_DONATION__'] = 'SecureKeyPAYMENTUniquePerDonation';
2179 }
2180 if (isModEnabled('invoice')) {
2181 $tmparray['__SECUREKEYPAYMENT_INVOICE__'] = 'SecureKeyPAYMENTUniquePerInvoice';
2182 }
2183 if (isModEnabled('order')) {
2184 $tmparray['__SECUREKEYPAYMENT_ORDER__'] = 'SecureKeyPAYMENTUniquePerOrder';
2185 }
2186 if (isModEnabled('contract')) {
2187 $tmparray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'SecureKeyPAYMENTUniquePerContractLine';
2188 }
2189
2190 //Online payment link
2191 if (isModEnabled('member')) {
2192 $tmparray['__ONLINEPAYMENTLINK_MEMBER__'] = 'OnlinePaymentLinkUniquePerMember';
2193 }
2194 if (isModEnabled('don')) {
2195 $tmparray['__ONLINEPAYMENTLINK_DONATION__'] = 'OnlinePaymentLinkUniquePerDonation';
2196 }
2197 if (isModEnabled('invoice')) {
2198 $tmparray['__ONLINEPAYMENTLINK_INVOICE__'] = 'OnlinePaymentLinkUniquePerInvoice';
2199 }
2200 if (isModEnabled('order')) {
2201 $tmparray['__ONLINEPAYMENTLINK_ORDER__'] = 'OnlinePaymentLinkUniquePerOrder';
2202 }
2203 if (isModEnabled('contract')) {
2204 $tmparray['__ONLINEPAYMENTLINK_CONTRACTLINE__'] = 'OnlinePaymentLinkUniquePerContractLine';
2205 }
2206 }
2207 } else {
2208 /* No need to show into tooltip help, option is not enabled
2209 $vars['__SECUREKEYPAYMENT__']='';
2210 $vars['__SECUREKEYPAYMENT_MEMBER__']='';
2211 $vars['__SECUREKEYPAYMENT_INVOICE__']='';
2212 $vars['__SECUREKEYPAYMENT_ORDER__']='';
2213 $vars['__SECUREKEYPAYMENT_CONTRACTLINE__']='';
2214 */
2215 }
2216 if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
2217 $tmparray['__PUBLICLINK_NEWMEMBERFORM__'] = 'BlankSubscriptionForm';
2218 }
2219 }
2220
2221 foreach ($tmparray as $key => $val) {
2222 if (empty($val)) {
2223 $tmparray[$key] = $key;
2224 }
2225 }
2226
2227 return $tmparray;
2228 }
2229}
2230
2231
2232require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
2233
2239class ModelMail extends CommonObject
2240{
2244 public $element = 'email_template';
2245
2249 public $table_element = 'c_email_templates';
2250
2251
2252 // BEGIN MODULEBUILDER PROPERTIES
2256 public $fields = array(
2257 "rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => "1", 'position' => 10, 'notnull' => 1, "visible" => "-1",),
2258 "module" => array("type" => "varchar(32)", "label" => "Module", "enabled" => "1", 'position' => 20, 'notnull' => 0, "visible" => "-1",),
2259 "type_template" => array("type" => "varchar(32)", "label" => "Typetemplate", "enabled" => "1", 'position' => 25, 'notnull' => 0, "visible" => "-1",),
2260 "lang" => array("type" => "varchar(6)", "label" => "Lang", "enabled" => "1", 'position' => 30, 'notnull' => 0, "visible" => "-1",),
2261 "private" => array("type" => "smallint(6)", "label" => "Private", "enabled" => "1", 'position' => 35, 'notnull' => 1, "visible" => "-1",),
2262 "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",),
2263 "datec" => array("type" => "datetime", "label" => "DateCreation", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "-1",),
2264 "tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => "1", 'position' => 50, 'notnull' => 1, "visible" => "-1",),
2265 "label" => array("type" => "varchar(255)", "label" => "Label", "enabled" => "1", 'position' => 55, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1", "css" => "minwidth300", "cssview" => "wordbreak", "csslist" => "tdoverflowmax150",),
2266 "position" => array("type" => "smallint(6)", "label" => "Position", "enabled" => "1", 'position' => 60, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2267 "active" => array("type" => "integer", "label" => "Active", "enabled" => "1", 'position' => 65, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
2268 "topic" => array("type" => "text", "label" => "Topic", "enabled" => "1", 'position' => 70, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2269 "content" => array("type" => "mediumtext", "label" => "Content", "enabled" => "1", 'position' => 75, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2270 "content_lines" => array("type" => "text", "label" => "Contentlines", "enabled" => "getDolGlobalString('MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES')", 'position' => 80, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2271 "enabled" => array("type" => "varchar(255)", "label" => "Enabled", "enabled" => "1", 'position' => 85, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2272 "joinfiles" => array("type" => "varchar(255)", "label" => "Joinfiles", "enabled" => "1", 'position' => 90, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2273 "email_from" => array("type" => "varchar(255)", "label" => "Emailfrom", "enabled" => "1", 'position' => 95, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2274 "email_to" => array("type" => "varchar(255)", "label" => "Emailto", "enabled" => "1", 'position' => 100, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2275 "email_tocc" => array("type" => "varchar(255)", "label" => "Emailtocc", "enabled" => "1", 'position' => 105, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2276 "email_tobcc" => array("type" => "varchar(255)", "label" => "Emailtobcc", "enabled" => "1", 'position' => 110, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2277 "defaultfortype" => array("type" => "smallint(6)", "label" => "Defaultfortype", "enabled" => "1", 'position' => 115, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2278 );
2282 public $rowid;
2286 public $type_template;
2290 public $datec;
2294 public $tms;
2298 public $active;
2302 public $enabled;
2306 public $defaultfortype;
2307
2311 public $id;
2312
2316 public $label;
2317
2321 public $fk_user;
2322
2326 public $private;
2327
2331 public $topic;
2332
2336 public $content;
2340 public $content_lines;
2341
2345 public $lang;
2349 public $joinfiles;
2350
2354 public $email_from;
2358 public $email_to;
2362 public $email_tocc;
2366 public $email_tobcc;
2367
2371 public $module;
2372
2376 public $position;
2377 // END MODULEBUILDER PROPERTIES
2378
2379
2380
2386 public function __construct(DoliDB $db)
2387 {
2388 global $langs;
2389
2390 $this->db = $db;
2391 $this->ismultientitymanaged = 0;
2392 $this->isextrafieldmanaged = 1;
2393
2394 // @phan-suppress-next-line PhanTypeMismatchProperty
2395 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
2396 $this->fields['rowid']['visible'] = 0;
2397 }
2398 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
2399 $this->fields['entity']['enabled'] = 0;
2400 }
2401
2402 // Example to show how to set values of fields definition dynamically
2403 /*if ($user->hasRight('test', 'mailtemplate', 'read')) {
2404 $this->fields['myfield']['visible'] = 1;
2405 $this->fields['myfield']['noteditable'] = 0;
2406 }*/
2407
2408 // Unset fields that are disabled
2409 foreach ($this->fields as $key => $val) {
2410 if (isset($val['enabled']) && empty($val['enabled'])) {
2411 unset($this->fields[$key]);
2412 }
2413 }
2414
2415 // Translate some data of arrayofkeyval
2416 if (is_object($langs)) {
2417 foreach ($this->fields as $key => $val) {
2418 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
2419 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
2420 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
2421 }
2422 }
2423 }
2424 }
2425 }
2426
2427
2437 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
2438 {
2439 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
2440 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
2441 $this->fetchLines($noextrafields);
2442 }
2443 return $result;
2444 }
2445}
print $object position
Definition edit.php:204
Class to manage a WYSIWYG editor.
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 $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
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)
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.
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:153
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:149
getMaxFileSizeArray()
Return the max allowed for file upload.