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