dolibarr 21.0.0-alpha
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
120 public $withsubstit; // Show substitution array
121 public $withfrom;
122
126 public $withto; // Show recipient emails
127 public $withreplyto;
128
134 public $withtofree;
135 public $withtocc;
136 public $withtoccc;
137 public $withtopic;
138 public $witherrorsto;
139
143 public $withfile;
144
148 public $withlayout;
149
153 public $withaiprompt;
154
158 public $withmaindocfile;
159 public $withbody;
160
161 public $withfromreadonly;
162 public $withreplytoreadonly;
163 public $withtoreadonly;
164 public $withtoccreadonly;
165 public $witherrorstoreadonly;
166 public $withtocccreadonly;
167 public $withtopicreadonly;
168 public $withbodyreadonly;
169 public $withfilereadonly;
170 public $withdeliveryreceipt;
171 public $withcancel;
172 public $withdeliveryreceiptreadonly;
173 public $withfckeditor;
174
178 public $ckeditortoolbar;
179
180 public $substit = array();
181 public $substit_lines = array();
185 public $param = array();
186
187 public $withtouser = array();
188 public $withtoccuser = array();
189
190 public $lines_model;
191
192 // -1 suggest the checkbox 'one email per recipient' not checked, 0 = no suggestion, 1 = suggest and checked
193 public $withoptiononeemailperrecipient;
194
195
201 public function __construct($db)
202 {
203 $this->db = $db;
204
205 $this->withform = 1;
206
207 $this->withfrom = 1;
208 $this->withto = 1;
209 $this->withtofree = 1;
210 $this->withtocc = 1;
211 $this->withtoccc = 0;
212 $this->witherrorsto = 0;
213 $this->withtopic = 1;
214 $this->withfile = 0; // 1=Add section "Attached files". 2=Can add files.
215 $this->withmaindocfile = 0; // 1=Add a checkbox "Attach also main document" for mass actions (checked by default), -1=Add checkbox (not checked by default)
216 $this->withbody = 1;
217
218 $this->withfromreadonly = 1;
219 $this->withreplytoreadonly = 1;
220 $this->withtoreadonly = 0;
221 $this->withtoccreadonly = 0;
222 $this->withtocccreadonly = 0;
223 $this->witherrorstoreadonly = 0;
224 $this->withtopicreadonly = 0;
225 $this->withfilereadonly = 0;
226 $this->withbodyreadonly = 0;
227 $this->withdeliveryreceiptreadonly = 0;
228 $this->withfckeditor = -1; // -1 = Auto
229 }
230
231 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
237 public function clear_attached_files()
238 {
239 // phpcs:enable
240 global $conf, $user;
241 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
242
243 // Set tmp user directory
244 $vardir = $conf->user->dir_output."/".$user->id;
245 $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
246 if (is_dir($upload_dir)) {
247 dol_delete_dir_recursive($upload_dir);
248 }
249
250 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
251 unset($_SESSION["listofpaths".$keytoavoidconflict]);
252 unset($_SESSION["listofnames".$keytoavoidconflict]);
253 unset($_SESSION["listofmimes".$keytoavoidconflict]);
254 }
255
256 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
265 public function add_attached_files($path, $file = '', $type = '')
266 {
267 // phpcs:enable
268 $listofpaths = array();
269 $listofnames = array();
270 $listofmimes = array();
271
272 if (empty($file)) {
273 $file = basename($path);
274 }
275 if (empty($type)) {
276 $type = dol_mimetype($file);
277 }
278
279 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
280 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
281 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
282 }
283 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
284 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
285 }
286 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
287 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
288 }
289 if (!in_array($file, $listofnames)) {
290 $listofpaths[] = $path;
291 $listofnames[] = $file;
292 $listofmimes[] = $type;
293 $_SESSION["listofpaths".$keytoavoidconflict] = implode(';', $listofpaths);
294 $_SESSION["listofnames".$keytoavoidconflict] = implode(';', $listofnames);
295 $_SESSION["listofmimes".$keytoavoidconflict] = implode(';', $listofmimes);
296 }
297 }
298
299 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
306 public function remove_attached_files($keytodelete)
307 {
308 // phpcs:enable
309 $listofpaths = array();
310 $listofnames = array();
311 $listofmimes = array();
312
313 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
314 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
315 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
316 }
317 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
318 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
319 }
320 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
321 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
322 }
323 if ($keytodelete >= 0) {
324 unset($listofpaths[$keytodelete]);
325 unset($listofnames[$keytodelete]);
326 unset($listofmimes[$keytodelete]);
327 $_SESSION["listofpaths".$keytoavoidconflict] = implode(';', $listofpaths);
328 $_SESSION["listofnames".$keytoavoidconflict] = implode(';', $listofnames);
329 $_SESSION["listofmimes".$keytoavoidconflict] = implode(';', $listofmimes);
330 //var_dump($_SESSION['listofpaths']);
331 }
332 }
333
334 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
340 public function get_attached_files()
341 {
342 // phpcs:enable
343 $listofpaths = array();
344 $listofnames = array();
345 $listofmimes = array();
346
347 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
348 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
349 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
350 }
351 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
352 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
353 }
354 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
355 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
356 }
357 return array('paths' => $listofpaths, 'names' => $listofnames, 'mimes' => $listofmimes);
358 }
359
360 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
371 public function show_form($addfileaction = 'addfile', $removefileaction = 'removefile')
372 {
373 // phpcs:enable
374 print $this->get_form($addfileaction, $removefileaction);
375 }
376
377 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
388 public function get_form($addfileaction = 'addfile', $removefileaction = 'removefile')
389 {
390 // phpcs:enable
391 global $conf, $langs, $user, $hookmanager, $form;
392
393 // Required to show preview wof mail attachments
394 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
395 $formfile = new FormFile($this->db);
396
397 if (!is_object($form)) {
398 $form = new Form($this->db);
399 }
400
401 // Load translation files required by the page
402 $langs->loadLangs(array('other', 'mails', 'members'));
403
404 // Clear temp files. Must be done before call of triggers, at beginning (mode = init), or when we select a new template
405 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
406 $this->clear_attached_files();
407 }
408
409 // Call hook getFormMail
410 $hookmanager->initHooks(array('formmail'));
411
412 $parameters = array(
413 'addfileaction' => $addfileaction,
414 'removefileaction' => $removefileaction,
415 'trackid' => $this->trackid
416 );
417 $reshook = $hookmanager->executeHooks('getFormMail', $parameters, $this);
418
419 if (!empty($reshook)) {
420 return $hookmanager->resPrint;
421 } else {
422 $out = '';
423
424 $disablebademails = 1;
425
426 // Define output language
427 $outputlangs = $langs;
428 $newlang = '';
429 if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($this->param['langsmodels'])) {
430 $newlang = $this->param['langsmodels'];
431 }
432 if (!empty($newlang)) {
433 $outputlangs = new Translate("", $conf);
434 $outputlangs->setDefaultLang($newlang);
435 $outputlangs->load('other');
436 }
437
438 // Get message template for $this->param["models"] into c_email_templates
439 $arraydefaultmessage = -1;
440 if ($this->param['models'] != 'none') {
441 $model_id = 0;
442 if (array_key_exists('models_id', $this->param)) {
443 $model_id = $this->param["models_id"];
444 }
445
446 $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
447 }
448
449 // Define list of attached files
450 $listofpaths = array();
451 $listofnames = array();
452 $listofmimes = array();
453 $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
454
455 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
456 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
457 foreach ($this->param['fileinit'] as $path) {
458 if (!empty($path)) {
459 $this->add_attached_files($path);
460 }
461 }
462 }
463 }
464
465 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
466 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
467 }
468 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
469 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
470 }
471 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
472 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
473 }
474
475
476 $out .= "\n".'<!-- Begin form mail type='.$this->param["models"].' --><div id="mailformdiv"></div>'."\n";
477 if ($this->withform == 1) {
478 $out .= '<form method="POST" name="mailform" id="mailform" enctype="multipart/form-data" action="'.$this->param["returnurl"].'#formmail">'."\n";
479
480 $out .= '<a id="formmail" name="formmail"></a>';
481 $out .= '<input style="display:none" type="submit" id="sendmailhidden" name="sendmail">';
482 $out .= '<input type="hidden" name="token" value="'.newToken().'" />';
483 $out .= '<input type="hidden" name="trackid" value="'.$this->trackid.'" />';
484 $out .= '<input type="hidden" name="inreplyto" value="'.$this->inreplyto.'" />';
485 }
486 if (!empty($this->withfrom)) {
487 if (!empty($this->withfromreadonly)) {
488 $out .= '<input type="hidden" id="fromname" name="fromname" value="'.$this->fromname.'" />';
489 $out .= '<input type="hidden" id="frommail" name="frommail" value="'.$this->frommail.'" />';
490 }
491 }
492 foreach ($this->param as $key => $value) {
493 if (is_array($value)) {
494 $out .= "<!-- param key=".$key." is array, we do not output input field for it -->\n";
495 } else {
496 $out .= '<input type="hidden" id="'.$key.'" name="'.$key.'" value="'.$value.'" />'."\n";
497 }
498 }
499
500 $modelmail_array = array();
501 if ($this->param['models'] != 'none') {
502 $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs); // Fill $this->lines_model
503 if ($result < 0) {
504 setEventMessages($this->error, $this->errors, 'errors');
505 }
506
507 foreach ($this->lines_model as $line) {
508 $reg = array();
509 if (preg_match('/\‍((.*)\‍)/', $line->label, $reg)) {
510 $labeltouse = $langs->trans($reg[1]); // langs->trans when label is __(xxx)__
511 } else {
512 $labeltouse = $line->label;
513 }
514
515 // We escape the $labeltouse to store it into $modelmail_array.
516 $modelmail_array[$line->id] = dol_escape_htmltag($labeltouse);
517 if ($line->lang) {
518 $modelmail_array[$line->id] .= ' '.picto_from_langcode($line->lang);
519 }
520 if ($line->private) {
521 $modelmail_array[$line->id] .= ' - <span class="opacitymedium">'.dol_escape_htmltag($langs->trans("Private")).'</span>';
522 }
523 }
524 }
525
526 // Zone to select email template
527 if (count($modelmail_array) > 0) {
528 $model_mail_selected_id = GETPOSTISSET('modelmailselected') ? GETPOSTINT('modelmailselected') : ($arraydefaultmessage->id > 0 ? $arraydefaultmessage->id : 0);
529
530 // If list of template is filled
531 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
532
533 $out .= '<span class="opacitymedium">'.$langs->trans('SelectMailModel').':</span> ';
534
535 $out .= $this->selectarray('modelmailselected', $modelmail_array, $model_mail_selected_id, 1, 0, 0, '', 0, 0, 0, '', 'minwidth100', 1, '', 0, 1);
536 if ($user->admin) {
537 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
538 }
539
540 $out .= ' &nbsp; ';
541 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
542 $out .= ' &nbsp; ';
543 $out .= '</div>';
544 } elseif (!empty($this->param['models']) && in_array($this->param['models'], array(
545 'propal_send', 'order_send', 'facture_send',
546 'shipping_send', 'fichinter_send', 'supplier_proposal_send', 'order_supplier_send',
547 'invoice_supplier_send', 'thirdparty', 'contract', 'user', 'recruitmentcandidature_send', 'all'
548 ))) {
549 // If list of template is empty
550 $out .= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
551 $out .= '<span class="opacitymedium">'.$langs->trans('SelectMailModel').':</span> ';
552 $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.
553 if ($user->admin) {
554 $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')), 1);
555 }
556 $out .= ' &nbsp; ';
557 $out .= '<input type="submit" class="button reposition smallpaddingimp" value="'.$langs->trans('Apply').'" name="modelselected" disabled="disabled" id="modelselected">';
558 $out .= ' &nbsp; ';
559 $out .= '</div>';
560 } else {
561 $out .= '<!-- No template available for $this->param["models"] = '.$this->param['models'].' -->';
562 }
563
564
565 $out .= '<table class="tableforemailform boxtablenotop centpercent">'."\n";
566
567 // Substitution array/string
568 $helpforsubstitution = '';
569 if (is_array($this->substit) && count($this->substit)) {
570 $helpforsubstitution .= $langs->trans('AvailableVariables').' :<br><br><span class="small">'."\n";
571 }
572 foreach ($this->substit as $key => $val) {
573 // Do not show deprecated variables into the tooltip help of substitution variables
574 if (in_array($key, array('__NEWREF__', '__REFCLIENT__', '__REFSUPPLIER__', '__SUPPLIER_ORDER_DATE_DELIVERY__', '__SUPPLIER_ORDER_DELAY_DELIVERY__'))) {
575 continue;
576 }
577 $helpforsubstitution .= $key.' -> '.$langs->trans(dol_string_nohtmltag(dolGetFirstLineOfText($val))).'<br>';
578 }
579 if (is_array($this->substit) && count($this->substit)) {
580 $helpforsubstitution .= '</span>';
581 }
582
583 /*
584 if (!empty($this->withsubstit)) { // Unset or set ->withsubstit=0 to disable this.
585 $out .= '<tr><td colspan="2" class="right">';
586 if (is_numeric($this->withsubstit)) {
587 $out .= $form->textwithpicto($langs->trans("EMailTestSubstitutionReplacedByGenericValues"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // Old usage
588 } else {
589 $out .= $form->textwithpicto($langs->trans('AvailableVariables'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // New usage
590 }
591 $out .= "</td></tr>\n";
592 }*/
593
594 // From
595 if (!empty($this->withfrom)) {
596 if (!empty($this->withfromreadonly)) {
597 $out .= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
598
599 // $this->fromtype is the default value to use to select sender
600 if (!($this->fromtype === 'user' && $this->fromid > 0)
601 && !($this->fromtype === 'company')
602 && !($this->fromtype === 'robot')
603 && !preg_match('/user_aliases/', $this->fromtype)
604 && !preg_match('/global_aliases/', $this->fromtype)
605 && !preg_match('/senderprofile/', $this->fromtype)
606 ) {
607 // Use this->fromname and this->frommail or error if not defined
608 $out .= $this->fromname;
609 if ($this->frommail) {
610 $out .= ' &lt;'.$this->frommail.'&gt;';
611 } else {
612 if ($this->fromtype) {
613 $langs->load('errors');
614 $out .= '<span class="warning"> &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt; </span>';
615 }
616 }
617 } else {
618 $liste = array();
619
620 // Add user email
621 if (empty($user->email)) {
622 $langs->load('errors');
623 $s = $user->getFullName($langs).' &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt;';
624 } else {
625 $s = $user->getFullName($langs).' &lt;'.$user->email.'&gt;';
626 }
627 $liste['user'] = array('label' => $s, 'data-html' => $s);
628
629 // Add also company main email
630 if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
631 $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;';
632 $liste['company'] = array('label' => $s, 'data-html' => $s);
633 }
634
635 // Add also email aliases if there is some
636 $listaliases = array(
637 'user_aliases' => (empty($user->email_aliases) ? '' : $user->email_aliases),
638 'global_aliases' => getDolGlobalString('MAIN_INFO_SOCIETE_MAIL_ALIASES'),
639 );
640
641 if (!empty($arraydefaultmessage->email_from)) {
642 $templatemailfrom = ' &lt;'.$arraydefaultmessage->email_from.'&gt;';
643 $liste['from_template_'.GETPOST('modelmailselected')] = array('label' => $templatemailfrom, 'data-html' => $templatemailfrom);
644 }
645
646 // Also add robot email
647 if (!empty($this->fromalsorobot)) {
648 if (getDolGlobalString('MAIN_MAIL_EMAIL_FROM') && getDolGlobalString('MAIN_MAIL_EMAIL_FROM') != getDolGlobalString('MAIN_INFO_SOCIETE_MAIL')) {
649 $s = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
650 if ($this->frommail) {
651 $s .= ' &lt;' . getDolGlobalString('MAIN_MAIL_EMAIL_FROM').'&gt;';
652 }
653 $liste['main_from'] = array('label' => $s, 'data-html' => $s);
654 }
655 }
656
657 // Add also email aliases from the c_email_senderprofile table
658 $sql = "SELECT rowid, label, email FROM ".$this->db->prefix()."c_email_senderprofile";
659 $sql .= " WHERE active = 1 AND (private = 0 OR private = ".((int) $user->id).")";
660 $sql .= " ORDER BY position";
661 $resql = $this->db->query($sql);
662 if ($resql) {
663 $num = $this->db->num_rows($resql);
664 $i = 0;
665 while ($i < $num) {
666 $obj = $this->db->fetch_object($resql);
667 if ($obj) {
668 $listaliases['senderprofile_'.$obj->rowid] = $obj->label.' <'.$obj->email.'>';
669 }
670 $i++;
671 }
672 } else {
673 dol_print_error($this->db);
674 }
675
676 foreach ($listaliases as $typealias => $listalias) {
677 $posalias = 0;
678 $listaliasarray = explode(',', $listalias);
679 foreach ($listaliasarray as $listaliasval) {
680 $posalias++;
681 $listaliasval = trim($listaliasval);
682 if ($listaliasval) {
683 $listaliasval = preg_replace('/</', '&lt;', $listaliasval);
684 $listaliasval = preg_replace('/>/', '&gt;', $listaliasval);
685 if (!preg_match('/&lt;/', $listaliasval)) {
686 $listaliasval = '&lt;'.$listaliasval.'&gt;';
687 }
688 $liste[$typealias.'_'.$posalias] = array('label' => $listaliasval, 'data-html' => $listaliasval);
689 }
690 }
691 }
692
693 // Using ajaxcombo here make the '<email>' no more visible on list because <emailofuser> is not a valid html tag,
694 // so we transform before each record into $liste to be printable with ajaxcombo by replacing <> into ()
695 // $liste['senderprofile_0_0'] = array('label'=>'rrr', 'data-html'=>'rrr &lt;aaaa&gt;');
696 foreach ($liste as $key => $val) {
697 if (!empty($liste[$key]['data-html'])) {
698 $liste[$key]['data-html'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $liste[$key]['data-html']);
699 $liste[$key]['data-html'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $liste[$key]['data-html']);
700 }
701 }
702 $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);
703 }
704
705 $out .= "</td></tr>\n";
706 } else {
707 $out .= '<tr><td class="fieldrequired width200">'.$langs->trans("MailFrom")."</td><td>";
708 $out .= $langs->trans("Name").':<input type="text" id="fromname" name="fromname" class="maxwidth200onsmartphone" value="'.$this->fromname.'" />';
709 $out .= '&nbsp; &nbsp; ';
710 $out .= $langs->trans("EMail").':&lt;<input type="text" id="frommail" name="frommail" class="maxwidth200onsmartphone" value="'.$this->frommail.'" />&gt;';
711 $out .= "</td></tr>\n";
712 }
713 }
714
715 // To
716 if (!empty($this->withto) || is_array($this->withto)) {
717 $out .= $this->getHtmlForTo();
718 }
719
720 // To User
721 if (!empty($this->withtouser) && is_array($this->withtouser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
722 $out .= '<tr><td>';
723 $out .= $langs->trans("MailToUsers");
724 $out .= '</td><td>';
725
726 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
727 $tmparray = $this->withtouser;
728 foreach ($tmparray as $key => $val) {
729 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
730 }
731 $withtoselected = GETPOST("receiveruser", 'array'); // Array of selected value
732 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
733 $withtoselected = array_keys($tmparray);
734 }
735 $out .= $form->multiselectarray("receiveruser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
736 $out .= "</td></tr>\n";
737 }
738
739 // With option for one email per recipient
740 if (!empty($this->withoptiononeemailperrecipient)) {
741 if (abs($this->withoptiononeemailperrecipient) == 1) {
742 $out .= '<tr><td class="minwidth200">';
743 $out .= $langs->trans("GroupEmails");
744 $out .= '</td><td>';
745 $out .= ' <input type="checkbox" id="oneemailperrecipient" value="1" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0 ? ' checked="checked"' : '').'> ';
746 $out .= '<label for="oneemailperrecipient">';
747 $out .= $form->textwithpicto($langs->trans("OneEmailPerRecipient"), $langs->trans("WarningIfYouCheckOneRecipientPerEmail"), 1, 'help');
748 $out .= '</label>';
749 //$out .= '<span class="hideonsmartphone opacitymedium">';
750 //$out .= ' - ';
751 //$out .= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
752 //$out .= '</span>';
753 if (getDolGlobalString('MASS_ACTION_EMAIL_ON_DIFFERENT_THIRPARTIES_ADD_CUSTOM_EMAIL')) {
754 if (!empty($this->withto) && !is_array($this->withto)) {
755 $out .= ' '.$langs->trans("or").' <input type="email" name="emailto" value="">';
756 }
757 }
758 $out .= '</td></tr>';
759 } else {
760 $out .= '<tr><td><input type="hidden" name="oneemailperrecipient" value="1"></td><td></td></tr>';
761 }
762 }
763
764 // CC
765 if (!empty($this->withtocc) || is_array($this->withtocc)) {
766 $out .= $this->getHtmlForCc();
767 }
768
769 // To User cc
770 if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
771 $out .= '<tr><td>';
772 $out .= $langs->trans("MailToCCUsers");
773 $out .= '</td><td>';
774
775 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
776 $tmparray = $this->withtoccuser;
777 foreach ($tmparray as $key => $val) {
778 $tmparray[$key] = dol_htmlentities($tmparray[$key], 0, 'UTF-8', true);
779 }
780 $withtoselected = GETPOST("receiverccuser", 'array'); // Array of selected value
781 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
782 $withtoselected = array_keys($tmparray);
783 }
784 $out .= $form->multiselectarray("receiverccuser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
785 $out .= "</td></tr>\n";
786 }
787
788 // CCC
789 if (!empty($this->withtoccc) || is_array($this->withtoccc)) {
790 $out .= $this->getHtmlForWithCcc();
791 }
792
793 // Replyto
794 if (!empty($this->withreplyto)) {
795 if ($this->withreplytoreadonly) {
796 $out .= '<input type="hidden" id="replyname" name="replyname" value="'.$this->replytoname.'" />';
797 $out .= '<input type="hidden" id="replymail" name="replymail" value="'.$this->replytomail.'" />';
798 $out .= "<tr><td>".$langs->trans("MailReply")."</td><td>".$this->replytoname.($this->replytomail ? (" &lt;".$this->replytomail."&gt;") : "");
799 $out .= "</td></tr>\n";
800 }
801 }
802
803 // Errorsto
804 if (!empty($this->witherrorsto)) {
805 $out .= $this->getHtmlForWithErrorsTo();
806 }
807
808 // Ask delivery receipt
809 if (!empty($this->withdeliveryreceipt) && getDolGlobalInt('MAIN_EMAIL_SUPPORT_ACK')) {
810 $out .= $this->getHtmlForDeliveryreceipt();
811 }
812
813 // Topic
814 if (!empty($this->withtopic)) {
815 $out .= $this->getHtmlForTopic($arraydefaultmessage, $helpforsubstitution);
816 }
817
818 // Attached files
819 if (!empty($this->withfile)) {
820 $out .= '<tr>';
821 $out .= '<td class="tdtop">'.$langs->trans("MailFile").'</td>';
822
823 $out .= '<td>';
824
825 if ($this->withmaindocfile) {
826 // withmaindocfile is set to 1 or -1 to show the checkbox (-1 = checked or 1 = not checked)
827 if (GETPOSTISSET('sendmail')) {
828 $this->withmaindocfile = (GETPOST('addmaindocfile', 'alpha') ? -1 : 1);
829 } elseif (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
830 // If a template was selected, we use setup of template to define if join file checkbox is selected or not.
831 $this->withmaindocfile = ($arraydefaultmessage->joinfiles ? -1 : 1);
832 }
833 }
834
835 if (!empty($this->withmaindocfile)) {
836 if ($this->withmaindocfile == 1) {
837 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" />';
838 } elseif ($this->withmaindocfile == -1) {
839 $out .= '<input type="checkbox" id="addmaindocfile" name="addmaindocfile" value="1" checked="checked" />';
840 }
841 if (getDolGlobalString('MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND')) {
842 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDocOrLastGenerated").'.</label><br>';
843 } else {
844 $out .= ' <label for="addmaindocfile">'.$langs->trans("JoinMainDoc").'.</label><br>';
845 }
846 }
847
848 if (is_numeric($this->withfile)) {
849 // TODO Trick to have param removedfile containing nb of file to delete. But this does not works without javascript
850 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
851 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
852 $out .= 'jQuery(document).ready(function () {';
853 $out .= ' jQuery(".removedfile").click(function() {';
854 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
855 $out .= ' });';
856 $out .= '})';
857 $out .= '</script>'."\n";
858 if (count($listofpaths)) {
859 foreach ($listofpaths as $key => $val) {
860 $relativepathtofile = substr($val, (strlen(DOL_DATA_ROOT) - strlen($val)));
861
862 $entity = (isset($this->param['object_entity']) ? $this->param['object_entity'] : $conf->entity);
863 if ($entity > 1) {
864 $relativepathtofile = str_replace('/'.$entity.'/', '/', $relativepathtofile);
865 }
866 // Try to extract data from full path
867 $formfile_params = array();
868 preg_match('#^(/)(\w+)(/)(.+)$#', $relativepathtofile, $formfile_params);
869
870 $out .= '<div id="attachfile_'.$key.'">';
871 // Preview of attachment
872 $out .= img_mime($listofnames[$key]).$listofnames[$key];
873
874 $out .= ' '.$formfile->showPreview(array(), $formfile_params[2], $formfile_params[4], 0, ($entity == 1 ? '' : 'entity='.((int) $entity)));
875
876 if (!$this->withfilereadonly) {
877 $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.'" />';
878 //$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>';
879 }
880 $out .= '<br></div>';
881 }
882 } elseif (empty($this->withmaindocfile)) {
883 //$out .= '<span class="opacitymedium">'.$langs->trans("NoAttachedFiles").'</span><br>';
884 }
885 if ($this->withfile == 2) {
886 $maxfilesizearray = getMaxFileSizeArray();
887 $maxmin = $maxfilesizearray['maxmin'];
888 if ($maxmin > 0) {
889 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
890 }
891 // Can add other files
892 if (!getDolGlobalString('FROM_MAIL_DONT_USE_INPUT_FILE_MULTIPLE')) {
893 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile[]" value="'.$langs->trans("Upload").'" multiple />';
894 } else {
895 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
896 }
897 $out .= ' ';
898 $out .= '<input type="submit" class="button smallpaddingimp" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
899 }
900 } else {
901 $out .= $this->withfile;
902 }
903
904 $out .= "</td></tr>\n";
905 }
906
907 // Message (+ Links to choose layout or ai prompt)
908 if (!empty($this->withbody)) {
909 $defaultmessage = GETPOST('message', 'restricthtml');
910 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
911 if ($arraydefaultmessage && $arraydefaultmessage->content) {
912 $defaultmessage = $arraydefaultmessage->content;
913 } elseif (!is_numeric($this->withbody)) {
914 $defaultmessage = $this->withbody;
915 }
916 }
917
918 // Complete substitution array with the url to make online payment
919 $validpaymentmethod = array();
920 if (empty($this->substit['__REF__'])) {
921 $paymenturl = '';
922 } else {
923 // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
924 require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
925 $langs->loadLangs(array('paypal', 'other'));
926 $typeforonlinepayment = 'free';
927 if ($this->param["models"] == 'order' || $this->param["models"] == 'order_send') {
928 $typeforonlinepayment = 'order'; // TODO use detection on something else than template
929 }
930 if ($this->param["models"] == 'invoice' || $this->param["models"] == 'facture_send') {
931 $typeforonlinepayment = 'invoice'; // TODO use detection on something else than template
932 }
933 if ($this->param["models"] == 'member') {
934 $typeforonlinepayment = 'member'; // TODO use detection on something else than template
935 }
936 $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']);
937 $paymenturl = $url;
938
939 $validpaymentmethod = getValidOnlinePaymentMethods('');
940 }
941
942 if (count($validpaymentmethod) > 0 && $paymenturl) {
943 $langs->load('other');
944 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = str_replace('\n', "\n", $langs->transnoentities("PredefinedMailContentLink", $paymenturl));
945 $this->substit['__ONLINE_PAYMENT_URL__'] = $paymenturl;
946 } else {
947 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = '';
948 $this->substit['__ONLINE_PAYMENT_URL__'] = '';
949 }
950
951 $this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'] = '';
952
953 // Add lines substitution key from each line
954 $lines = '';
955 $defaultlines = $arraydefaultmessage->content_lines;
956 if (isset($defaultlines)) {
957 foreach ($this->substit_lines as $substit_line) {
958 $lines .= make_substitutions($defaultlines, $substit_line)."\n";
959 }
960 }
961 $this->substit['__LINES__'] = $lines;
962
963 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
964
965 // Deal with format differences between message and some substitution variables (text / HTML)
966 $atleastonecomponentishtml = 0;
967 if (strpos($defaultmessage, '__USER_SIGNATURE__') !== false && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
968 $atleastonecomponentishtml++;
969 }
970 if (strpos($defaultmessage, '__SENDEREMAIL_SIGNATURE__') !== false && dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
971 $atleastonecomponentishtml++;
972 }
973 if (strpos($defaultmessage, '__ONLINE_PAYMENT_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
974 $atleastonecomponentishtml++;
975 }
976 if (strpos($defaultmessage, '__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__') !== false && dol_textishtml($this->substit['__ONLINE_INTERVIEW_SCHEDULER_TEXT_AND_URL__'])) {
977 $atleastonecomponentishtml++;
978 }
979 if (dol_textishtml($defaultmessage)) {
980 $atleastonecomponentishtml++;
981 }
982 if ($atleastonecomponentishtml) {
983 if (!dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
984 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
985 }
986 if (!dol_textishtml($this->substit['__SENDEREMAIL_SIGNATURE__'])) {
987 $this->substit['__SENDEREMAIL_SIGNATURE__'] = dol_nl2br($this->substit['__SENDEREMAIL_SIGNATURE__']);
988 }
989 if (!dol_textishtml($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'])) {
990 $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__'] = dol_nl2br($this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']);
991 }
992 if (!dol_textishtml($defaultmessage)) {
993 $defaultmessage = dol_nl2br($defaultmessage);
994 }
995 }
996
997 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
998 $defaultmessage = GETPOST("message", "restricthtml");
999 } else {
1000 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1001 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1002 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1003 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1004 }
1005
1006 $out .= '<tr>';
1007 $out .= '<td class="tdtop">';
1008 $out .= $form->textwithpicto($langs->trans('MailText'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
1009 $out .= '</td>';
1010 $out .= '<td class="tdtop">';
1011
1012 $formmail = $this;
1013 $showlinktolayout = $formmail->withlayout && $formmail->withfckeditor && getDolGlobalInt('MAIN_EMAIL_USE_LAYOUT');
1014 $showlinktolayoutlabel = $langs->trans("FillMessageWithALayout");
1015 $showlinktoai = ($formmail->withaiprompt && isModEnabled('ai')) ? 'textgenerationemail' : '';
1016 $showlinktoailabel = $langs->trans("FillMessageWithAIContent");
1017 $formatforouput = '';
1018 $htmlname = 'message';
1019
1020 // Fill $out
1021 include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
1022
1023 $out .= '</td>';
1024 $out .= '</tr>';
1025
1026 $out .= '<tr>';
1027 $out .= '<td colspan="2">';
1028 if ($this->withbodyreadonly) {
1029 $out .= nl2br($defaultmessage);
1030 $out .= '<input type="hidden" id="message" name="message" disabled value="'.$defaultmessage.'" />';
1031 } else {
1032 if (!isset($this->ckeditortoolbar)) {
1033 $this->ckeditortoolbar = 'dolibarr_mailings';
1034 }
1035
1036 // Editor wysiwyg
1037 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1038 if ($this->withfckeditor == -1) {
1039 if (getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) {
1040 $this->withfckeditor = 1;
1041 } else {
1042 $this->withfckeditor = 0;
1043 }
1044 }
1045
1046 $doleditor = new DolEditor('message', $defaultmessage, '', 280, $this->ckeditortoolbar, 'In', true, true, $this->withfckeditor, 8, '95%');
1047 $out .= $doleditor->Create(1);
1048 }
1049 $out .= "</td></tr>\n";
1050 }
1051
1052 $out .= '</table>'."\n";
1053
1054 if ($this->withform == 1 || $this->withform == -1) {
1055 $out .= '<div class="center">';
1056 $out .= '<input type="submit" class="button button-add" id="sendmail" name="sendmail" value="'.$langs->trans("SendMail").'"';
1057 // Add a javascript test to avoid to forget to submit file before sending email
1058 if ($this->withfile == 2 && $conf->use_javascript_ajax) {
1059 $out .= ' onClick="if (document.mailform.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1060 }
1061 $out .= ' />';
1062 if ($this->withcancel) {
1063 $out .= '<input class="button button-cancel" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'" />';
1064 }
1065 $out .= '</div>'."\n";
1066 }
1067
1068 if ($this->withform == 1) {
1069 $out .= '</form>'."\n";
1070 }
1071
1072 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1073 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1074 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1075 $out .= 'jQuery(document).ready(function () {';
1076 $out .= ' $(document).on("keypress", \'#mailform\', function (e) { /* Note this is called at every key pressed ! */
1077 var code = e.keyCode || e.which;
1078 if (code == 13) {
1079 console.log("Enter was intercepted and blocked");
1080 e.preventDefault();
1081 return false;
1082 }
1083 });';
1084 $out .= ' })';
1085 $out .= '</script>';
1086 }
1087
1088 $out .= "<!-- End form mail -->\n";
1089
1090 return $out;
1091 }
1092 }
1093
1099 public function getHtmlForTo()
1100 {
1101 global $langs, $form;
1102 $out = '<tr><td class="fieldrequired">';
1103 if ($this->withtofree) {
1104 $out .= $form->textwithpicto($langs->trans("MailTo"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1105 } else {
1106 $out .= $langs->trans("MailTo");
1107 }
1108 $out .= '</td><td>';
1109 if ($this->withtoreadonly) {
1110 if (!empty($this->toname) && !empty($this->tomail)) {
1111 $out .= '<input type="hidden" id="toname" name="toname" value="'.$this->toname.'" />';
1112 $out .= '<input type="hidden" id="tomail" name="tomail" value="'.$this->tomail.'" />';
1113 if ($this->totype == 'thirdparty') {
1114 $soc = new Societe($this->db);
1115 $soc->fetch($this->toid);
1116 $out .= $soc->getNomUrl(1);
1117 } elseif ($this->totype == 'contact') {
1118 $contact = new Contact($this->db);
1119 $contact->fetch($this->toid);
1120 $out .= $contact->getNomUrl(1);
1121 } else {
1122 $out .= $this->toname;
1123 }
1124 $out .= ' &lt;'.$this->tomail.'&gt;';
1125 if ($this->withtofree) {
1126 $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) : "").'" />';
1127 }
1128 } else {
1129 // Note withto may be a text like 'AllRecipientSelected'
1130 $out .= (!is_array($this->withto) && !is_numeric($this->withto)) ? $this->withto : "";
1131 }
1132 } else {
1133 // The free input of email
1134 if (!empty($this->withtofree)) {
1135 $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) : "")).'" />';
1136 }
1137 // The select combo
1138 if (!empty($this->withto) && is_array($this->withto)) {
1139 if (!empty($this->withtofree)) {
1140 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1141 }
1142
1143 $tmparray = $this->withto;
1144 foreach ($tmparray as $key => $val) {
1145 if (is_array($val)) {
1146 $label = $val['label'];
1147 } else {
1148 $label = $val;
1149 }
1150
1151 $tmparray[$key] = array();
1152 $tmparray[$key]['id'] = $key;
1153
1154 $tmparray[$key]['label'] = $label;
1155 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1156 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1157 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1158
1159 $tmparray[$key]['labelhtml'] = $label;
1160 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1161 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1162 }
1163
1164 $withtoselected = GETPOST("receiver", 'array'); // Array of selected value
1165 if (!getDolGlobalInt('MAIN_MAIL_NO_WITH_TO_SELECTED')) {
1166 if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') {
1167 $withtoselected = array_keys($tmparray);
1168 }
1169 }
1170
1171 $out .= $form->multiselectarray("receiver", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', 0, 0);
1172 }
1173 }
1174 $out .= "</td></tr>\n";
1175 return $out;
1176 }
1177
1183 public function getHtmlForCc()
1184 {
1185 global $langs, $form;
1186 $out = '<tr><td>';
1187 $out .= $form->textwithpicto($langs->trans("MailCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1188 $out .= '</td><td>';
1189 if ($this->withtoccreadonly) {
1190 $out .= (!is_array($this->withtocc) && !is_numeric($this->withtocc)) ? $this->withtocc : "";
1191 } else {
1192 $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 : '')).'" />';
1193 if (!empty($this->withtocc) && is_array($this->withtocc)) {
1194 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1195
1196 $tmparray = $this->withtocc;
1197 foreach ($tmparray as $key => $val) {
1198 if (is_array($val)) {
1199 $label = $val['label'];
1200 } else {
1201 $label = $val;
1202 }
1203
1204 $tmparray[$key] = array();
1205 $tmparray[$key]['id'] = $key;
1206
1207 $tmparray[$key]['label'] = $label;
1208 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1209 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1210 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1211
1212 $tmparray[$key]['labelhtml'] = $label;
1213 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1214 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1215 }
1216
1217 $withtoccselected = GETPOST("receivercc", 'array'); // Array of selected value
1218
1219 $out .= $form->multiselectarray("receivercc", $tmparray, $withtoccselected, null, null, 'inline-block minwidth500', 0, 0);
1220 }
1221 }
1222 $out .= "</td></tr>\n";
1223 return $out;
1224 }
1225
1232 public function getHtmlForWithCcc()
1233 {
1234 global $langs, $form;
1235
1236 $out = '<tr><td>';
1237 $out .= $form->textwithpicto($langs->trans("MailCCC"), $langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
1238 $out .= '</td><td>';
1239 if (!empty($this->withtocccreadonly)) {
1240 $out .= (!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : "";
1241 } else {
1242 $out .= '<input class="minwidth200" id="sendtoccc" name="sendtoccc" value="'.(GETPOSTISSET("sendtoccc") ? GETPOST("sendtoccc", "alpha") : ((!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />';
1243 if (!empty($this->withtoccc) && is_array($this->withtoccc)) {
1244 $out .= " ".$langs->trans("and")."/".$langs->trans("or")." ";
1245
1246 $tmparray = $this->withtoccc;
1247 foreach ($tmparray as $key => $val) {
1248 if (is_array($val)) {
1249 $label = $val['label'];
1250 } else {
1251 $label = $val;
1252 }
1253 $tmparray[$key] = array();
1254 $tmparray[$key]['id'] = $key;
1255
1256 $tmparray[$key]['label'] = $label;
1257 $tmparray[$key]['label'] = str_replace(array('<', '>'), array('(', ')'), $tmparray[$key]['label']);
1258 // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
1259 $tmparray[$key]['label'] = dol_htmlentities($tmparray[$key]['label'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', true);
1260
1261 $tmparray[$key]['labelhtml'] = $label;
1262 $tmparray[$key]['labelhtml'] = str_replace(array('&lt;', '<', '&gt;', '>'), array('__LTCHAR__', '__LTCHAR__', '__GTCHAR__', '__GTCHAR__'), $tmparray[$key]['labelhtml']);
1263 $tmparray[$key]['labelhtml'] = str_replace(array('__LTCHAR__', '__GTCHAR__'), array('<span class="opacitymedium">(', ')</span>'), $tmparray[$key]['labelhtml']);
1264 }
1265
1266 $withtocccselected = GETPOST("receiverccc", 'array'); // Array of selected value
1267
1268 $out .= $form->multiselectarray("receiverccc", $tmparray, $withtocccselected, null, null, 'inline-block minwidth500', 0, 0);
1269 }
1270 }
1271
1272 $showinfobcc = '';
1273 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1274 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROPOSAL_TO');
1275 }
1276 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1277 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_ORDER_TO');
1278 }
1279 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1280 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_INVOICE_TO');
1281 }
1282 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1283 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO');
1284 }
1285 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1286 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO');
1287 }
1288 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO') && !empty($this->param['models']) && $this->param['models'] == 'invoice_supplier_send') {
1289 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO');
1290 }
1291 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.
1292 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_PROJECT_TO');
1293 }
1294 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO') && !empty($this->param['models']) && $this->param['models'] == 'shipping_send') {
1295 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_SHIPMENT_TO');
1296 }
1297 if (getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO') && !empty($this->param['models']) && $this->param['models'] == 'reception_send') {
1298 $showinfobcc = getDolGlobalString('MAIN_MAIL_AUTOCOPY_RECEPTION_TO');
1299 }
1300 if ($showinfobcc) {
1301 $out .= ' + '.$showinfobcc;
1302 }
1303 $out .= "</td></tr>\n";
1304 return $out;
1305 }
1306
1312 public function getHtmlForWithErrorsTo()
1313 {
1314 global $langs;
1315
1316 //if (! $this->errorstomail) $this->errorstomail=$this->frommail;
1317 $errorstomail = getDolGlobalString('MAIN_MAIL_ERRORS_TO', (!empty($this->errorstomail) ? $this->errorstomail : ''));
1318 if ($this->witherrorstoreadonly) {
1319 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1320 $out .= '<input type="hidden" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1321 $out .= $errorstomail;
1322 $out .= "</td></tr>\n";
1323 } else {
1324 $out = '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
1325 $out .= '<input class="minwidth200" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
1326 $out .= "</td></tr>\n";
1327 }
1328 return $out;
1329 }
1330
1336 public function getHtmlForDeliveryreceipt()
1337 {
1338 global $langs;
1339
1340 $out = '<tr><td><label for="deliveryreceipt">'.$langs->trans("DeliveryReceipt").'</label></td><td>';
1341
1342 if (!empty($this->withdeliveryreceiptreadonly)) {
1343 $out .= yn($this->withdeliveryreceipt);
1344 } else {
1345 $defaultvaluefordeliveryreceipt = 0;
1346 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_PROPAL') && !empty($this->param['models']) && $this->param['models'] == 'propal_send') {
1347 $defaultvaluefordeliveryreceipt = 1;
1348 }
1349 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_PROPOSAL') && !empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') {
1350 $defaultvaluefordeliveryreceipt = 1;
1351 }
1352 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_send') {
1353 $defaultvaluefordeliveryreceipt = 1;
1354 }
1355 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_INVOICE') && !empty($this->param['models']) && $this->param['models'] == 'facture_send') {
1356 $defaultvaluefordeliveryreceipt = 1;
1357 }
1358 if (getDolGlobalString('MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_ORDER') && !empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') {
1359 $defaultvaluefordeliveryreceipt = 1;
1360 }
1361 //$out .= $form->selectyesno('deliveryreceipt', (GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt), 1);
1362 $out .= '<input type="checkbox" id="deliveryreceipt" name="deliveryreceipt" value="1"'.((GETPOSTISSET("deliveryreceipt") ? GETPOST("deliveryreceipt") : $defaultvaluefordeliveryreceipt) ? ' checked="checked"' : '').'>';
1363 }
1364 $out .= "</td></tr>\n";
1365 return $out;
1366 }
1367
1375 public function getHtmlForTopic($arraydefaultmessage, $helpforsubstitution)
1376 {
1377 global $langs, $form;
1378
1379 $defaulttopic = GETPOST('subject', 'restricthtml');
1380
1381 if (!GETPOST('modelselected', 'alpha') || GETPOST('modelmailselected') != '-1') {
1382 if ($arraydefaultmessage && $arraydefaultmessage->topic) {
1383 $defaulttopic = $arraydefaultmessage->topic;
1384 } elseif (!is_numeric($this->withtopic)) {
1385 $defaulttopic = $this->withtopic;
1386 }
1387 }
1388
1389 $defaulttopic = make_substitutions($defaulttopic, $this->substit);
1390
1391 $out = '<tr>';
1392 $out .= '<td class="fieldrequired">';
1393 $out .= $form->textwithpicto($langs->trans('MailTopic'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
1394 $out .= '</td>';
1395 $out .= '<td>';
1396 if ($this->withtopicreadonly) {
1397 $out .= $defaulttopic;
1398 $out .= '<input type="hidden" class="quatrevingtpercent" id="subject" name="subject" value="'.$defaulttopic.'" />';
1399 } else {
1400 $out .= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'.((GETPOSTISSET("subject") && !GETPOST('modelselected')) ? GETPOST("subject") : ($defaulttopic ? $defaulttopic : '')).'" />';
1401 }
1402 $out .= "</td></tr>\n";
1403 return $out;
1404 }
1405
1414 public function getSectionForAIPrompt($function = 'textgeneration', $format = '', $htmlContent = 'message')
1415 {
1416 global $langs;
1417
1418 $langs->load("other");
1419
1420 $htmlContent = preg_replace('/[^a-z0-9_]/', '', $htmlContent);
1421
1422 $out = '<div id="ai_input'.$htmlContent.'" class="hidden">';
1423 $out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions'.$htmlContent.'" name="instruction" placeholder="'.$langs->trans("EnterYourAIPromptHere").'..." />';
1424 $out .= '<input id="generate_button'.$htmlContent.'" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
1425 $out .= '<div id="ai_status_message'.$htmlContent.'" class="fieldrequired hideobject marginrightonly margintoponly">';
1426 $out .= '<i class="fa fa-spinner fa-spin fa-2x fa-fw valignmiddle marginrightonly"></i>'.$langs->trans("AIProcessingPleaseWait", getDolGlobalString('AI_API_SERVICE', 'chatgpt'));
1427 $out .= '</div>';
1428
1429 $out .= "</div>\n";
1430
1431 $out .= "<script type='text/javascript'>
1432 $(document).ready(function() {
1433 // for keydown
1434 $('#ai_instructions".$htmlContent."').keydown(function(event) {
1435 if (event.keyCode === 13) {
1436 event.preventDefault();
1437 $('#generate_button".$htmlContent."').click();
1438 }
1439 });
1440
1441 $('#generate_button".$htmlContent."').click(function() {
1442 console.log('We click on generate_button".$htmlContent." ai button');
1443
1444 var instructions = $('#ai_instructions".$htmlContent."').val();
1445 var timeoutfinished = 0;
1446 var apicallfinished = 0;
1447
1448 $('#ai_status_message".$htmlContent."').show();
1449 $('.icon-container .loader').show();
1450 setTimeout(function() {
1451 timeoutfinished = 1;
1452 if (apicallfinished) {
1453 $('#ai_status_message".$htmlContent."').hide();
1454 }
1455 }, 2000);
1456
1457 // set editor in readonly
1458 if (CKEDITOR.instances.".$htmlContent.") {
1459 CKEDITOR.instances.".$htmlContent.".setReadOnly(1);
1460 }
1461
1462
1463 $.ajax({
1464 url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".currentToken()."',
1465 type: 'POST',
1466 contentType: 'application/json',
1467 data: JSON.stringify({
1468 'format': '".dol_escape_js($format)."', /* the format for output */
1469 'function': '".dol_escape_js($function)."', /* the AI feature to call */
1470 'instructions': instructions, /* the prompt string */
1471 }),
1472 success: function(response) {
1473 console.log('Add response into field \'#".$htmlContent."\': '+response);
1474
1475 jQuery('#".$htmlContent."').val(response); // If #htmlcontent is a input name or textarea
1476 jQuery('#".$htmlContent."').html(response); // If #htmlContent is a div
1477 //jQuery('#".$htmlContent."preview').val(response);
1478
1479 if (CKEDITOR.instances) {
1480 var editorInstance = CKEDITOR.instances.".$htmlContent.";
1481 if (editorInstance) {
1482 editorInstance.setReadOnly(0);
1483 editorInstance.setData(response);
1484 }
1485 //var editorInstancepreview = CKEDITOR.instances.".$htmlContent."preview;
1486 //if (editorInstancepreview) {
1487 // editorInstancepreview.setData(response);
1488 //}
1489 }
1490
1491 // remove readonly
1492 $('#ai_instructions".$htmlContent."').val('');
1493
1494 apicallfinished = 1;
1495 if (timeoutfinished) {
1496 $('#ai_status_message".$htmlContent."').hide();
1497 }
1498 },
1499 error: function(xhr, status, error) {
1500 alert(error);
1501 console.error('error ajax', status, error);
1502 $('#ai_status_message".$htmlContent."').hide();
1503 }
1504
1505 });
1506 });
1507 });
1508 </script>
1509 ";
1510 return $out;
1511 }
1512
1519 public function getModelEmailTemplate($htmlContent = 'message')
1520 {
1521 global $langs;
1522
1523 require_once DOL_DOCUMENT_ROOT.'/core/lib/emaillayout.lib.php';
1524 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1525
1526 $out = '<div id="template-selector" class="template-container hidden">';
1527 $templates = array(
1528 'empty' => 'empty',
1529 );
1530
1531 $arrayoflayoutemplates = dol_dir_list(DOL_DOCUMENT_ROOT.'/install/doctemplates/maillayout/', 'files', 0, '\.html$');
1532 foreach ($arrayoflayoutemplates as $layouttemplatefile) {
1533 $layoutname = preg_replace('/\.html$/i', '', $layouttemplatefile['name']);
1534 $templates[$layoutname] = ucfirst($layoutname);
1535 }
1536 //}
1537 // TODO Add a hook to allow to complete the list
1538
1539 foreach ($templates as $template => $templateFunction) {
1540 $contentHtml = getHtmlOfLayout($template);
1541
1542 $out .= '<div class="template-option" data-template="'.$template.'" data-content="'.htmlentities($contentHtml).'">';
1543 $out .= '<img class="maillayout" alt="'.$template.'" src="'.DOL_URL_ROOT.'/theme/common/maillayout/'.$template.'.png" />';
1544 $out .= '<span class="template-option-text">'.$langs->trans($templateFunction).'</span>';
1545 $out .= '</div>';
1546 }
1547 $out .= '</div>';
1548
1549 $out .= '<script type="text/javascript">
1550 $(document).ready(function() {
1551 $(".template-option").click(function() {
1552 var template = $(this).data("template");
1553 var subject = jQuery("#subject").val();
1554 var fromtype = jQuery("#fromtype").val();
1555 var sendto = jQuery("#sendto").val();
1556 var sendtocc = jQuery("#sendtocc").val();
1557 var sendtoccc = jQuery("#sendtoccc").val();
1558
1559 console.log("We choose a layout for email template=" + template + ", subject="+subject);
1560
1561 $(".template-option").removeClass("selected");
1562 $(this).addClass("selected");
1563
1564 var contentHtml = $(this).data("content");
1565 var csrfToken = "'.newToken().'";
1566
1567 // Remplacer la variable de substitution dans le contenu HTML
1568 contentHtml = contentHtml.replace(/__SUBJECT__/g, subject);
1569
1570 // Envoyer le contenu HTML à process_template.php pour traitement PHP
1571 $.ajax({
1572 type: "POST",
1573 url: "'.DOL_URL_ROOT.'/core/ajax/mailtemplate.php",
1574 data: { template: template, subject: subject, fromtype: fromtype, sendto: sendto, sendtocc: sendtocc, sendtoccc: sendtoccc, content: contentHtml, token: csrfToken },
1575 success: function(response) {
1576 jQuery("#'.dol_sanitizeKeyCode($htmlContent).'").val(response);
1577 var editorInstance = CKEDITOR.instances["'.dol_sanitizeKeyCode($htmlContent).'"];
1578 if (editorInstance) {
1579 editorInstance.setData(response);
1580 }
1581 },
1582 error: function(xhr, status, error) {
1583 console.error("An error occurred: " + xhr.responseText);
1584 }
1585 });
1586 });
1587 });
1588 </script>';
1589
1590 return $out;
1591 }
1592
1610 public function getEMailTemplate($dbs, $type_template, $user, $outputlangs, $id = 0, $active = 1, $label = '', $defaultfortype = -1)
1611 {
1612 global $conf;
1613
1614 if ($id == -2 && empty($label)) {
1615 $this->error = 'LabelIsMandatoryWhenIdIs-2or-3';
1616 return -1;
1617 }
1618
1619 $ret = new ModelMail($dbs);
1620
1621 $languagetosearch = (is_object($outputlangs) ? $outputlangs->defaultlang : '');
1622 // Define $languagetosearchmain to fall back on main language (for example to get 'es_ES' for 'es_MX')
1623 $tmparray = explode('_', $languagetosearch);
1624 $languagetosearchmain = $tmparray[0].'_'.strtoupper($tmparray[0]);
1625 if ($languagetosearchmain == $languagetosearch) {
1626 $languagetosearchmain = '';
1627 }
1628
1629 $sql = "SELECT rowid, entity, module, label, type_template, topic, email_from, joinfiles, content, content_lines, lang, email_from, email_to, email_tocc, email_tobcc";
1630 $sql .= " FROM ".$dbs->prefix().'c_email_templates';
1631 $sql .= " WHERE (type_template = '".$dbs->escape($type_template)."' OR type_template = 'all')";
1632 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1633 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // Get all public or private owned
1634 if ($active >= 0) {
1635 $sql .= " AND active = ".((int) $active);
1636 }
1637 if ($defaultfortype >= 0) {
1638 $sql .= " AND defaultfortype = ".((int) $defaultfortype);
1639 }
1640 if ($label) {
1641 $sql .= " AND label = '".$dbs->escape($label)."'";
1642 }
1643 if (!($id > 0) && $languagetosearch) {
1644 $sql .= " AND (lang = '".$dbs->escape($languagetosearch)."'".($languagetosearchmain ? " OR lang = '".$dbs->escape($languagetosearchmain)."'" : "")." OR lang IS NULL OR lang = '')";
1645 }
1646 if ($id > 0) {
1647 $sql .= " AND rowid = ".(int) $id;
1648 }
1649 if ($id == -1) {
1650 $sql .= " AND position = 0";
1651 }
1652 $sql .= " AND entity IN(".getEntity('c_email_templates', 1).")";
1653 if ($languagetosearch) {
1654 $sql .= $dbs->order("position,lang,label", "ASC,DESC,ASC"); // We want line with lang set first, then with lang null or ''
1655 } else {
1656 $sql .= $dbs->order("position,lang,label", "ASC,ASC,ASC"); // If no language provided, we give priority to lang not defined
1657 }
1658 //$sql .= $dbs->plimit(1);
1659 //print $sql;
1660
1661 $resql = $dbs->query($sql);
1662 if (!$resql) {
1663 dol_print_error($dbs);
1664 return -1;
1665 }
1666
1667 // Get first found
1668 while (1) {
1669 $obj = $dbs->fetch_object($resql);
1670
1671 if ($obj) {
1672 // If template is for a module, check module is enabled; if not, take next template
1673 if ($obj->module) {
1674 $tempmodulekey = $obj->module;
1675 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
1676 continue;
1677 }
1678 }
1679
1680 // If a record was found
1681 $ret->id = $obj->rowid;
1682 $ret->module = $obj->module;
1683 $ret->label = $obj->label;
1684 $ret->lang = $obj->lang;
1685 $ret->topic = $obj->topic;
1686 $ret->content = $obj->content;
1687 $ret->content_lines = $obj->content_lines;
1688 $ret->joinfiles = $obj->joinfiles;
1689 $ret->email_from = $obj->email_from;
1690
1691 break;
1692 } else {
1693 // If no record found
1694 if ($id == -2) {
1695 // Not found with the provided label
1696 return -1;
1697 } else {
1698 // If there is no template at all
1699 $defaultmessage = '';
1700
1701 if ($type_template == 'body') {
1702 // Special case to use this->withbody as content
1703 $defaultmessage = $this->withbody;
1704 } elseif ($type_template == 'facture_send') {
1705 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoice");
1706 } elseif ($type_template == 'facture_relance') {
1707 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoiceReminder");
1708 } elseif ($type_template == 'propal_send') {
1709 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendProposal");
1710 } elseif ($type_template == 'supplier_proposal_send') {
1711 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierProposal");
1712 } elseif ($type_template == 'order_send') {
1713 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendOrder");
1714 } elseif ($type_template == 'order_supplier_send') {
1715 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierOrder");
1716 } elseif ($type_template == 'invoice_supplier_send') {
1717 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierInvoice");
1718 } elseif ($type_template == 'shipping_send') {
1719 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendShipping");
1720 } elseif ($type_template == 'fichinter_send') {
1721 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendFichInter");
1722 } elseif ($type_template == 'actioncomm_send') {
1723 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendActionComm");
1724 } elseif (!empty($type_template)) {
1725 $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentGeneric");
1726 }
1727
1728 $ret->label = 'default';
1729 $ret->lang = $outputlangs->defaultlang;
1730 $ret->topic = '';
1731 $ret->joinfiles = 1;
1732 $ret->content = $defaultmessage;
1733 $ret->content_lines = '';
1734
1735 break;
1736 }
1737 }
1738 }
1739
1740 $dbs->free($resql);
1741
1742 return $ret;
1743 }
1744
1754 public function isEMailTemplate($type_template, $user, $outputlangs)
1755 {
1756 $sql = "SELECT label, topic, content, lang";
1757 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
1758 $sql .= " WHERE type_template='".$this->db->escape($type_template)."'";
1759 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1760 $sql .= " AND (fk_user is NULL or fk_user = 0 or fk_user = ".((int) $user->id).")";
1761 if (is_object($outputlangs)) {
1762 $sql .= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')";
1763 }
1764 $sql .= $this->db->order("lang,label", "ASC");
1765 //print $sql;
1766
1767 $resql = $this->db->query($sql);
1768 if ($resql) {
1769 $num = $this->db->num_rows($resql);
1770 $this->db->free($resql);
1771 return $num;
1772 } else {
1773 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
1774 return -1;
1775 }
1776 }
1777
1788 public function fetchAllEMailTemplate($type_template, $user, $outputlangs, $active = 1)
1789 {
1790 global $db, $conf;
1791
1792 $sql = "SELECT rowid, module, label, topic, content, content_lines, lang, fk_user, private, position";
1793 $sql .= " FROM ".$this->db->prefix().'c_email_templates';
1794 $sql .= " WHERE type_template IN ('".$this->db->escape($type_template)."', 'all')";
1795 $sql .= " AND entity IN (".getEntity('c_email_templates').")";
1796 $sql .= " AND (private = 0 OR fk_user = ".((int) $user->id).")"; // See all public templates or templates I own.
1797 if ($active >= 0) {
1798 $sql .= " AND active = ".((int) $active);
1799 }
1800 //if (is_object($outputlangs)) $sql.= " AND (lang = '".$this->db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')"; // Return all languages
1801 $sql .= $this->db->order("position,lang,label", "ASC");
1802 //print $sql;
1803
1804 $resql = $this->db->query($sql);
1805 if ($resql) {
1806 $num = $this->db->num_rows($resql);
1807 $this->lines_model = array();
1808 while ($obj = $this->db->fetch_object($resql)) {
1809 // If template is for a module, check module is enabled.
1810 if ($obj->module) {
1811 $tempmodulekey = $obj->module;
1812 if (empty($conf->$tempmodulekey) || !isModEnabled($tempmodulekey)) {
1813 continue;
1814 }
1815 }
1816
1817 $line = new ModelMail($db);
1818 $line->id = $obj->rowid;
1819 $line->label = $obj->label;
1820 $line->lang = $obj->lang;
1821 $line->fk_user = $obj->fk_user;
1822 $line->private = $obj->private;
1823 $line->position = $obj->position;
1824 $line->topic = $obj->topic;
1825 $line->content = $obj->content;
1826 $line->content_lines = $obj->content_lines;
1827
1828 $this->lines_model[] = $line;
1829 }
1830 $this->db->free($resql);
1831 return $num;
1832 } else {
1833 $this->error = get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
1834 return -1;
1835 }
1836 }
1837
1838
1839
1848 public function setSubstitFromObject($object, $outputlangs)
1849 {
1850 global $extrafields;
1851
1852 $parameters = array();
1853 $tmparray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
1854 complete_substitutions_array($tmparray, $outputlangs, null, $parameters);
1855
1856 $this->substit = $tmparray;
1857
1858 // Fill substit_lines with each object lines content
1859 if (is_array($object->lines)) {
1860 foreach ($object->lines as $line) {
1861 $substit_line = array(
1862 '__PRODUCT_REF__' => isset($line->product_ref) ? $line->product_ref : '',
1863 '__PRODUCT_LABEL__' => isset($line->product_label) ? $line->product_label : '',
1864 '__PRODUCT_DESCRIPTION__' => isset($line->product_desc) ? $line->product_desc : '',
1865 '__LABEL__' => isset($line->label) ? $line->label : '',
1866 '__DESCRIPTION__' => isset($line->desc) ? $line->desc : '',
1867 '__DATE_START_YMD__' => dol_print_date($line->date_start, 'day', 0, $outputlangs),
1868 '__DATE_END_YMD__' => dol_print_date($line->date_end, 'day', 0, $outputlangs),
1869 '__QUANTITY__' => $line->qty,
1870 '__SUBPRICE__' => price($line->subprice),
1871 '__AMOUNT__' => price($line->total_ttc),
1872 '__AMOUNT_EXCL_TAX__' => price($line->total_ht)
1873 );
1874
1875 // Create dynamic tags for __PRODUCT_EXTRAFIELD_FIELD__
1876 if (!empty($line->fk_product)) {
1877 if (!is_object($extrafields)) {
1878 $extrafields = new ExtraFields($this->db);
1879 }
1880 $product = new Product($this->db);
1881 $product->fetch($line->fk_product, '', '', 1);
1882 $product->fetch_optionals();
1883
1884 $extrafields->fetch_name_optionals_label($product->table_element, true);
1885
1886 if (!empty($extrafields->attributes[$product->table_element]['label']) && is_array($extrafields->attributes[$product->table_element]['label']) && count($extrafields->attributes[$product->table_element]['label']) > 0) {
1887 foreach ($extrafields->attributes[$product->table_element]['label'] as $key => $label) {
1888 $substit_line['__PRODUCT_EXTRAFIELD_'.strtoupper($key).'__'] = isset($product->array_options['options_'.$key]) ? $product->array_options['options_'.$key] : '';
1889 }
1890 }
1891 }
1892 $this->substit_lines[] = $substit_line;
1893 }
1894 }
1895 }
1896
1905 public static function getAvailableSubstitKey($mode = 'formemail', $object = null)
1906 {
1907 global $langs;
1908
1909 $tmparray = array();
1910 if ($mode == 'formemail' || $mode == 'formemailwithlines' || $mode == 'formemailforlines') {
1911 $parameters = array('mode' => $mode);
1912 $tmparray = getCommonSubstitutionArray($langs, 2, null, $object); // Note: On email templated edition, this is null because it is related to all type of objects
1913 complete_substitutions_array($tmparray, $langs, null, $parameters);
1914
1915 if ($mode == 'formwithlines') {
1916 $tmparray['__LINES__'] = '__LINES__'; // Will be set by the get_form function
1917 }
1918 if ($mode == 'formforlines') {
1919 $tmparray['__QUANTITY__'] = '__QUANTITY__'; // Will be set by the get_form function
1920 }
1921 }
1922
1923 if ($mode == 'emailing') {
1924 $parameters = array('mode' => $mode);
1925 $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
1926 complete_substitutions_array($tmparray, $langs, null, $parameters);
1927
1928 // For mass emailing, we have different keys specific to the data into tagerts list
1929 $tmparray['__ID__'] = 'IdRecord';
1930 $tmparray['__THIRDPARTY_CUSTOMER_CODE__'] = 'CustomerCode';
1931 $tmparray['__EMAIL__'] = 'EMailRecipient';
1932 $tmparray['__LASTNAME__'] = 'Lastname';
1933 $tmparray['__FIRSTNAME__'] = 'Firstname';
1934 $tmparray['__MAILTOEMAIL__'] = 'TagMailtoEmail';
1935 $tmparray['__OTHER1__'] = 'Other1';
1936 $tmparray['__OTHER2__'] = 'Other2';
1937 $tmparray['__OTHER3__'] = 'Other3';
1938 $tmparray['__OTHER4__'] = 'Other4';
1939 $tmparray['__OTHER5__'] = 'Other5';
1940 $tmparray['__CHECK_READ__'] = $langs->trans('TagCheckMail');
1941 $tmparray['__UNSUBSCRIBE__'] = $langs->trans('TagUnsubscribe');
1942 $tmparray['__UNSUBSCRIBE_URL__'] = $langs->trans('TagUnsubscribe').' (URL)';
1943
1944 $onlinepaymentenabled = 0;
1945 if (isModEnabled('paypal')) {
1946 $onlinepaymentenabled++;
1947 }
1948 if (isModEnabled('paybox')) {
1949 $onlinepaymentenabled++;
1950 }
1951 if (isModEnabled('stripe')) {
1952 $onlinepaymentenabled++;
1953 }
1954 if ($onlinepaymentenabled && getDolGlobalString('PAYMENT_SECURITY_TOKEN')) {
1955 $tmparray['__SECUREKEYPAYMENT__'] = getDolGlobalString('PAYMENT_SECURITY_TOKEN');
1956 if (getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
1957 if (isModEnabled('member')) {
1958 $tmparray['__SECUREKEYPAYMENT_MEMBER__'] = 'SecureKeyPAYMENTUniquePerMember';
1959 }
1960 if (isModEnabled('don')) {
1961 $tmparray['__SECUREKEYPAYMENT_DONATION__'] = 'SecureKeyPAYMENTUniquePerDonation';
1962 }
1963 if (isModEnabled('invoice')) {
1964 $tmparray['__SECUREKEYPAYMENT_INVOICE__'] = 'SecureKeyPAYMENTUniquePerInvoice';
1965 }
1966 if (isModEnabled('order')) {
1967 $tmparray['__SECUREKEYPAYMENT_ORDER__'] = 'SecureKeyPAYMENTUniquePerOrder';
1968 }
1969 if (isModEnabled('contract')) {
1970 $tmparray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'SecureKeyPAYMENTUniquePerContractLine';
1971 }
1972
1973 //Online payment link
1974 if (isModEnabled('member')) {
1975 $tmparray['__ONLINEPAYMENTLINK_MEMBER__'] = 'OnlinePaymentLinkUniquePerMember';
1976 }
1977 if (isModEnabled('don')) {
1978 $tmparray['__ONLINEPAYMENTLINK_DONATION__'] = 'OnlinePaymentLinkUniquePerDonation';
1979 }
1980 if (isModEnabled('invoice')) {
1981 $tmparray['__ONLINEPAYMENTLINK_INVOICE__'] = 'OnlinePaymentLinkUniquePerInvoice';
1982 }
1983 if (isModEnabled('order')) {
1984 $tmparray['__ONLINEPAYMENTLINK_ORDER__'] = 'OnlinePaymentLinkUniquePerOrder';
1985 }
1986 if (isModEnabled('contract')) {
1987 $tmparray['__ONLINEPAYMENTLINK_CONTRACTLINE__'] = 'OnlinePaymentLinkUniquePerContractLine';
1988 }
1989 }
1990 } else {
1991 /* No need to show into tooltip help, option is not enabled
1992 $vars['__SECUREKEYPAYMENT__']='';
1993 $vars['__SECUREKEYPAYMENT_MEMBER__']='';
1994 $vars['__SECUREKEYPAYMENT_INVOICE__']='';
1995 $vars['__SECUREKEYPAYMENT_ORDER__']='';
1996 $vars['__SECUREKEYPAYMENT_CONTRACTLINE__']='';
1997 */
1998 }
1999 if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
2000 $tmparray['__PUBLICLINK_NEWMEMBERFORM__'] = 'BlankSubscriptionForm';
2001 }
2002 }
2003
2004 foreach ($tmparray as $key => $val) {
2005 if (empty($val)) {
2006 $tmparray[$key] = $key;
2007 }
2008 }
2009
2010 return $tmparray;
2011 }
2012}
2013
2014
2015require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
2016
2022class ModelMail extends CommonObject
2023{
2027 public $element = 'email_template';
2028
2032 public $table_element = 'c_email_templates';
2033
2034
2035 // BEGIN MODULEBUILDER PROPERTIES
2039 public $fields = array(
2040 "rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => "1", 'position' => 10, 'notnull' => 1, "visible" => "-1",),
2041 "module" => array("type" => "varchar(32)", "label" => "Module", "enabled" => "1", 'position' => 20, 'notnull' => 0, "visible" => "-1",),
2042 "type_template" => array("type" => "varchar(32)", "label" => "Typetemplate", "enabled" => "1", 'position' => 25, 'notnull' => 0, "visible" => "-1",),
2043 "lang" => array("type" => "varchar(6)", "label" => "Lang", "enabled" => "1", 'position' => 30, 'notnull' => 0, "visible" => "-1",),
2044 "private" => array("type" => "smallint(6)", "label" => "Private", "enabled" => "1", 'position' => 35, 'notnull' => 1, "visible" => "-1",),
2045 "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",),
2046 "datec" => array("type" => "datetime", "label" => "DateCreation", "enabled" => "1", 'position' => 45, 'notnull' => 0, "visible" => "-1",),
2047 "tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => "1", 'position' => 50, 'notnull' => 1, "visible" => "-1",),
2048 "label" => array("type" => "varchar(255)", "label" => "Label", "enabled" => "1", 'position' => 55, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1", "css" => "minwidth300", "cssview" => "wordbreak", "csslist" => "tdoverflowmax150",),
2049 "position" => array("type" => "smallint(6)", "label" => "Position", "enabled" => "1", 'position' => 60, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2050 "active" => array("type" => "integer", "label" => "Active", "enabled" => "1", 'position' => 65, 'notnull' => 1, "visible" => "-1", "alwayseditable" => "1",),
2051 "topic" => array("type" => "text", "label" => "Topic", "enabled" => "1", 'position' => 70, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2052 "content" => array("type" => "mediumtext", "label" => "Content", "enabled" => "1", 'position' => 75, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2053 "content_lines" => array("type" => "text", "label" => "Contentlines", "enabled" => "1", 'position' => 80, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2054 "enabled" => array("type" => "varchar(255)", "label" => "Enabled", "enabled" => "1", 'position' => 85, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2055 "joinfiles" => array("type" => "varchar(255)", "label" => "Joinfiles", "enabled" => "1", 'position' => 90, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2056 "email_from" => array("type" => "varchar(255)", "label" => "Emailfrom", "enabled" => "1", 'position' => 95, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2057 "email_to" => array("type" => "varchar(255)", "label" => "Emailto", "enabled" => "1", 'position' => 100, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2058 "email_tocc" => array("type" => "varchar(255)", "label" => "Emailtocc", "enabled" => "1", 'position' => 105, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2059 "email_tobcc" => array("type" => "varchar(255)", "label" => "Emailtobcc", "enabled" => "1", 'position' => 110, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2060 "defaultfortype" => array("type" => "smallint(6)", "label" => "Defaultfortype", "enabled" => "1", 'position' => 115, 'notnull' => 0, "visible" => "-1", "alwayseditable" => "1",),
2061 );
2062 public $rowid;
2063 public $type_template;
2064 public $datec;
2065 public $tms;
2066 public $active;
2067 public $enabled;
2068 public $defaultfortype;
2069
2073 public $id;
2074
2078 public $label;
2079
2083 public $fk_user;
2084
2088 public $private;
2089
2093 public $topic;
2094
2098 public $content;
2099 public $content_lines;
2100 public $lang;
2101 public $joinfiles;
2102
2103 public $email_from;
2104 public $email_to;
2105 public $email_tocc;
2106 public $email_tobcc;
2107
2111 public $module;
2112
2116 public $position;
2117 // END MODULEBUILDER PROPERTIES
2118
2119
2120
2126 public function __construct(DoliDB $db)
2127 {
2128 global $langs;
2129
2130 $this->db = $db;
2131 $this->ismultientitymanaged = 0;
2132 $this->isextrafieldmanaged = 1;
2133
2134 // @phan-suppress-next-line PhanTypeMismatchProperty
2135 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
2136 $this->fields['rowid']['visible'] = 0;
2137 }
2138 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
2139 $this->fields['entity']['enabled'] = 0;
2140 }
2141
2142 // Example to show how to set values of fields definition dynamically
2143 /*if ($user->hasRight('test', 'mailtemplate', 'read')) {
2144 $this->fields['myfield']['visible'] = 1;
2145 $this->fields['myfield']['noteditable'] = 0;
2146 }*/
2147
2148 // Unset fields that are disabled
2149 foreach ($this->fields as $key => $val) {
2150 if (isset($val['enabled']) && empty($val['enabled'])) {
2151 unset($this->fields[$key]);
2152 }
2153 }
2154
2155 // Translate some data of arrayofkeyval
2156 if (is_object($langs)) {
2157 foreach ($this->fields as $key => $val) {
2158 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
2159 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
2160 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
2161 }
2162 }
2163 }
2164 }
2165 }
2166
2167
2177 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
2178 {
2179 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
2180 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
2181 $this->fetchLines($noextrafields);
2182 }
2183 return $result;
2184 }
2185}
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:634
print $object position
Definition edit.php:195
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 $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)
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
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
$conf db user
Active Directory does not allow anonymous connections.
Definition repair.php:143
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:139
getMaxFileSizeArray()
Return the max allowed for file upload.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e rowid
Definition invoice.php:2001