html.formmail.class.php 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  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 Frédéric France <frederic.france@netlogic.fr>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. /**
  23. * \file htdocs/core/class/html.formmail.class.php
  24. * \ingroup core
  25. * \brief Fichier de la classe permettant la generation du formulaire html d'envoi de mail unitaire
  26. */
  27. require_once DOL_DOCUMENT_ROOT .'/core/class/html.form.class.php';
  28. /**
  29. * Classe permettant la generation du formulaire html d'envoi de mail unitaire
  30. * Usage: $formail = new FormMail($db)
  31. * $formmail->proprietes=1 ou chaine ou tableau de valeurs
  32. * $formmail->show_form() affiche le formulaire
  33. */
  34. class FormMail extends Form
  35. {
  36. /**
  37. * @var DoliDB Database handler.
  38. */
  39. public $db;
  40. public $withform; // 1=Include HTML form tag and show submit button, 0=Do not include form tag and submit button, -1=Do not include form tag but include submit button
  41. public $fromname;
  42. public $frommail;
  43. /**
  44. * @var string user, company, robot
  45. */
  46. public $fromtype;
  47. /**
  48. * @var int ID
  49. */
  50. public $fromid;
  51. /**
  52. * @var string thirdparty etc
  53. */
  54. public $totype;
  55. /**
  56. * @var int ID
  57. */
  58. public $toid;
  59. public $replytoname;
  60. public $replytomail;
  61. public $toname;
  62. public $tomail;
  63. public $trackid;
  64. public $withsubstit; // Show substitution array
  65. public $withfrom;
  66. /**
  67. * @var int
  68. * @deprecated Fill withto with array before calling method.
  69. * @see withto
  70. */
  71. public $withtosocid;
  72. /**
  73. * @var int|int[]
  74. */
  75. public $withto; // Show recipient emails
  76. public $withtofree; // Show free text for recipient emails
  77. public $withtocc;
  78. public $withtoccc;
  79. public $withtopic;
  80. public $withfile; // 0=No attaches files, 1=Show attached files, 2=Can add new attached files
  81. public $withmaindocfile; // 1=Add a checkbox "Attach also main document" for mass actions (checked by default), -1=Add checkbox (not checked by default)
  82. public $withbody;
  83. public $withfromreadonly;
  84. public $withreplytoreadonly;
  85. public $withtoreadonly;
  86. public $withtoccreadonly;
  87. public $withtocccreadonly;
  88. public $withtopicreadonly;
  89. public $withfilereadonly;
  90. public $withdeliveryreceipt;
  91. public $withcancel;
  92. public $withfckeditor;
  93. public $substit=array();
  94. public $substit_lines=array();
  95. public $param=array();
  96. public $withtouser=array();
  97. public $withtoccuser=array();
  98. public $lines_model;
  99. /**
  100. * Constructor
  101. *
  102. * @param DoliDB $db Database handler
  103. */
  104. function __construct($db)
  105. {
  106. $this->db = $db;
  107. $this->withform=1;
  108. $this->withfrom=1;
  109. $this->withto=1;
  110. $this->withtofree=1;
  111. $this->withtocc=1;
  112. $this->withtoccc=0;
  113. $this->witherrorsto=0;
  114. $this->withtopic=1;
  115. $this->withfile=0; // 1=Add section "Attached files". 2=Can add files.
  116. $this->withmaindocfile=0; // 1=Add a checkbox "Attach also main document" for mass actions (checked by default), -1=Add checkbox (not checked by default)
  117. $this->withbody=1;
  118. $this->withfromreadonly=1;
  119. $this->withreplytoreadonly=1;
  120. $this->withtoreadonly=0;
  121. $this->withtoccreadonly=0;
  122. $this->withtocccreadonly=0;
  123. $this->witherrorstoreadonly=0;
  124. $this->withtopicreadonly=0;
  125. $this->withfilereadonly=0;
  126. $this->withbodyreadonly=0;
  127. $this->withdeliveryreceiptreadonly=0;
  128. $this->withfckeditor=-1; // -1 = Auto
  129. }
  130. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  131. /**
  132. * Clear list of attached files in send mail form (also stored in session)
  133. *
  134. * @return void
  135. */
  136. function clear_attached_files()
  137. {
  138. // phpcs:enable
  139. global $conf,$user;
  140. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  141. // Set tmp user directory
  142. $vardir=$conf->user->dir_output."/".$user->id;
  143. $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
  144. if (is_dir($upload_dir)) dol_delete_dir_recursive($upload_dir);
  145. $keytoavoidconflict = empty($this->trackid)?'':'-'.$this->trackid; // this->trackid must be defined
  146. unset($_SESSION["listofpaths".$keytoavoidconflict]);
  147. unset($_SESSION["listofnames".$keytoavoidconflict]);
  148. unset($_SESSION["listofmimes".$keytoavoidconflict]);
  149. }
  150. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  151. /**
  152. * Add a file into the list of attached files (stored in SECTION array)
  153. *
  154. * @param string $path Full absolute path on filesystem of file, including file name
  155. * @param string $file Only filename (can be basename($path))
  156. * @param string $type Mime type (can be dol_mimetype($file))
  157. * @return void
  158. */
  159. function add_attached_files($path, $file='', $type='')
  160. {
  161. // phpcs:enable
  162. $listofpaths=array();
  163. $listofnames=array();
  164. $listofmimes=array();
  165. if (empty($file)) $file=basename($path);
  166. if (empty($type)) $type=dol_mimetype($file);
  167. $keytoavoidconflict = empty($this->trackid)?'':'-'.$this->trackid; // this->trackid must be defined
  168. if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
  169. if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
  170. if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
  171. if (! in_array($file,$listofnames))
  172. {
  173. $listofpaths[]=$path;
  174. $listofnames[]=$file;
  175. $listofmimes[]=$type;
  176. $_SESSION["listofpaths".$keytoavoidconflict]=join(';',$listofpaths);
  177. $_SESSION["listofnames".$keytoavoidconflict]=join(';',$listofnames);
  178. $_SESSION["listofmimes".$keytoavoidconflict]=join(';',$listofmimes);
  179. }
  180. }
  181. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  182. /**
  183. * Remove a file from the list of attached files (stored in SECTION array)
  184. *
  185. * @param string $keytodelete Key in file array (0, 1, 2, ...)
  186. * @return void
  187. */
  188. function remove_attached_files($keytodelete)
  189. {
  190. // phpcs:enable
  191. $listofpaths=array();
  192. $listofnames=array();
  193. $listofmimes=array();
  194. $keytoavoidconflict = empty($this->trackid)?'':'-'.$this->trackid; // this->trackid must be defined
  195. if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
  196. if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
  197. if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
  198. if ($keytodelete >= 0)
  199. {
  200. unset ($listofpaths[$keytodelete]);
  201. unset ($listofnames[$keytodelete]);
  202. unset ($listofmimes[$keytodelete]);
  203. $_SESSION["listofpaths".$keytoavoidconflict]=join(';',$listofpaths);
  204. $_SESSION["listofnames".$keytoavoidconflict]=join(';',$listofnames);
  205. $_SESSION["listofmimes".$keytoavoidconflict]=join(';',$listofmimes);
  206. //var_dump($_SESSION['listofpaths']);
  207. }
  208. }
  209. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  210. /**
  211. * Return list of attached files (stored in SECTION array)
  212. *
  213. * @return array array('paths'=> ,'names'=>, 'mimes'=> )
  214. */
  215. function get_attached_files()
  216. {
  217. // phpcs:enable
  218. $listofpaths=array();
  219. $listofnames=array();
  220. $listofmimes=array();
  221. $keytoavoidconflict = empty($this->trackid)?'':'-'.$this->trackid; // this->trackid must be defined
  222. if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
  223. if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
  224. if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
  225. return array('paths'=>$listofpaths, 'names'=>$listofnames, 'mimes'=>$listofmimes);
  226. }
  227. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  228. /**
  229. * Show the form to input an email
  230. * this->withfile: 0=No attaches files, 1=Show attached files, 2=Can add new attached files
  231. * this->withmaindocfile
  232. *
  233. * @param string $addfileaction Name of action when posting file attachments
  234. * @param string $removefileaction Name of action when removing file attachments
  235. * @return void
  236. */
  237. function show_form($addfileaction='addfile',$removefileaction='removefile')
  238. {
  239. // phpcs:enable
  240. print $this->get_form($addfileaction,$removefileaction);
  241. }
  242. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  243. /**
  244. * Get the form to input an email
  245. * this->withfile: 0=No attaches files, 1=Show attached files, 2=Can add new attached files
  246. * this->withfile
  247. * this->param: Contains more parameters like email templates info
  248. *
  249. * @param string $addfileaction Name of action when posting file attachments
  250. * @param string $removefileaction Name of action when removing file attachments
  251. * @return string Form to show
  252. */
  253. function get_form($addfileaction='addfile', $removefileaction='removefile')
  254. {
  255. // phpcs:enable
  256. global $conf, $langs, $user, $hookmanager, $form;
  257. if (! is_object($form)) $form=new Form($this->db);
  258. // Load translation files required by the page
  259. $langs->loadLangs(array('other', 'mails'));
  260. // Clear temp files. Must be done at beginning, before call of triggers
  261. if (GETPOST('mode','alpha') == 'init' || (GETPOST('modelmailselected','alpha') && GETPOST('modelmailselected','alpha') != '-1'))
  262. {
  263. $this->clear_attached_files();
  264. }
  265. // Call hook getFormMail
  266. $hookmanager->initHooks(array('formmail'));
  267. $parameters=array(
  268. 'addfileaction' => $addfileaction,
  269. 'removefileaction'=> $removefileaction,
  270. 'trackid'=> $this->trackid
  271. );
  272. $reshook=$hookmanager->executeHooks('getFormMail', $parameters, $this);
  273. if (!empty($reshook))
  274. {
  275. return $hookmanager->resPrint;
  276. }
  277. else
  278. {
  279. $out='';
  280. $disablebademails=1;
  281. // Define output language
  282. $outputlangs = $langs;
  283. $newlang = '';
  284. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $this->param['langsmodels'];
  285. if (! empty($newlang))
  286. {
  287. $outputlangs = new Translate("", $conf);
  288. $outputlangs->setDefaultLang($newlang);
  289. $outputlangs->load('other');
  290. }
  291. // Get message template for $this->param["models"] into c_email_templates
  292. $arraydefaultmessage = -1;
  293. if ($this->param['models'] != 'none')
  294. {
  295. $model_id=0;
  296. if (array_key_exists('models_id',$this->param))
  297. {
  298. $model_id=$this->param["models_id"];
  299. }
  300. $arraydefaultmessage=$this->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
  301. }
  302. // Define list of attached files
  303. $listofpaths=array();
  304. $listofnames=array();
  305. $listofmimes=array();
  306. $keytoavoidconflict = empty($this->trackid)?'':'-'.$this->trackid; // this->trackid must be defined
  307. if (GETPOST('mode','alpha') == 'init' || (GETPOST('modelmailselected','alpha') && GETPOST('modelmailselected','alpha') != '-1'))
  308. {
  309. if (! empty($arraydefaultmessage->joinfiles) && is_array($this->param['fileinit']))
  310. {
  311. foreach($this->param['fileinit'] as $file)
  312. {
  313. $this->add_attached_files($file, basename($file), dol_mimetype($file));
  314. }
  315. }
  316. }
  317. if (! empty($_SESSION["listofpaths".$keytoavoidconflict])) $listofpaths=explode(';',$_SESSION["listofpaths".$keytoavoidconflict]);
  318. if (! empty($_SESSION["listofnames".$keytoavoidconflict])) $listofnames=explode(';',$_SESSION["listofnames".$keytoavoidconflict]);
  319. if (! empty($_SESSION["listofmimes".$keytoavoidconflict])) $listofmimes=explode(';',$_SESSION["listofmimes".$keytoavoidconflict]);
  320. $out.= "\n".'<!-- Begin form mail type='.$this->param["models"].' --><div id="mailformdiv"></div>'."\n";
  321. if ($this->withform == 1)
  322. {
  323. $out.= '<form method="POST" name="mailform" id="mailform" enctype="multipart/form-data" action="'.$this->param["returnurl"].'#formmail">'."\n";
  324. $out.= '<a id="formmail" name="formmail"></a>';
  325. $out.= '<input style="display:none" type="submit" id="sendmail" name="sendmail">';
  326. $out.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'" />';
  327. $out.= '<input type="hidden" name="trackid" value="'.$this->trackid.'" />';
  328. }
  329. if (! empty($this->withfrom))
  330. {
  331. if (! empty($this->withfromreadonly))
  332. {
  333. $out.= '<input type="hidden" id="fromname" name="fromname" value="'.$this->fromname.'" />';
  334. $out.= '<input type="hidden" id="frommail" name="frommail" value="'.$this->frommail.'" />';
  335. }
  336. }
  337. foreach ($this->param as $key=>$value)
  338. {
  339. $out.= '<input type="hidden" id="'.$key.'" name="'.$key.'" value="'.$value.'" />'."\n";
  340. }
  341. $modelmail_array=array();
  342. if ($this->param['models'] != 'none')
  343. {
  344. $result = $this->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
  345. if ($result < 0)
  346. {
  347. setEventMessages($this->error, $this->errors, 'errors');
  348. }
  349. foreach($this->lines_model as $line)
  350. {
  351. $langs->trans("members");
  352. if (preg_match('/\((.*)\)/', $line->label, $reg))
  353. {
  354. $modelmail_array[$line->id]=$langs->trans($reg[1]); // langs->trans when label is __(xxx)__
  355. }
  356. else
  357. {
  358. $modelmail_array[$line->id]=$line->label;
  359. }
  360. if ($line->lang) $modelmail_array[$line->id].=' ('.$line->lang.')';
  361. if ($line->private) $modelmail_array[$line->id].=' - '.$langs->trans("Private");
  362. //if ($line->fk_user != $user->id) $modelmail_array[$line->id].=' - '.$langs->trans("By").' ';
  363. }
  364. }
  365. // Zone to select email template
  366. if (count($modelmail_array)>0)
  367. {
  368. // If list of template is filled
  369. $out.= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
  370. $out.= '<span class="opacitymedium">'.$langs->trans('SelectMailModel').':</span> '.$this->selectarray('modelmailselected', $modelmail_array, 0, 1, 0, 0, '', 0, 0, 0, '', 'minwidth100');
  371. if ($user->admin) $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')),1);
  372. $out.= ' &nbsp; ';
  373. $out.= '<input class="button" type="submit" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
  374. $out.= ' &nbsp; ';
  375. $out.= '</div>';
  376. }
  377. elseif (! empty($this->param['models']) && in_array($this->param['models'], array(
  378. 'propal_send','order_send','facture_send',
  379. 'shipping_send','fichinter_send','supplier_proposal_send','order_supplier_send',
  380. 'invoice_supplier_send','thirdparty','contract','user','all'
  381. )))
  382. {
  383. // If list of template is empty
  384. $out.= '<div class="center" style="padding: 0px 0 12px 0">'."\n";
  385. $out.= $langs->trans('SelectMailModel').': <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.
  386. if ($user->admin) $out.= info_admin($langs->trans("YouCanChangeValuesForThisListFrom", $langs->transnoentitiesnoconv('Setup').' - '.$langs->transnoentitiesnoconv('EMails')),1);
  387. $out.= ' &nbsp; ';
  388. $out.= '<input class="button" type="submit" value="'.$langs->trans('Apply').'" name="modelselected" disabled="disabled" id="modelselected">';
  389. $out.= ' &nbsp; ';
  390. $out.= '</div>';
  391. }
  392. $out.= '<table class="tableforemailform boxtablenotop" width="100%">'."\n";
  393. // Substitution array/string
  394. $helpforsubstitution='';
  395. if (is_array($this->substit) && count($this->substit)) $helpforsubstitution.=$langs->trans('AvailableVariables').' :<br>'."\n";
  396. foreach($this->substit as $key => $val)
  397. {
  398. $helpforsubstitution.=$key.' -> '.$langs->trans(dol_string_nohtmltag($val)).'<br>';
  399. }
  400. if (! empty($this->withsubstit)) // Unset or set ->withsubstit=0 to disable this.
  401. {
  402. $out.= '<tr><td colspan="2" align="right">';
  403. //$out.='<div class="floatright">';
  404. if (is_numeric($this->withsubstit)) $out.= $form->textwithpicto($langs->trans("EMailTestSubstitutionReplacedByGenericValues"), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // Old usage
  405. else $out.= $form->textwithpicto($langs->trans('AvailableVariables'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltip'); // New usage
  406. $out.= "</td></tr>\n";
  407. //$out.='</div>';
  408. }
  409. /*var_dump(! empty($this->withfromreadonly));
  410. var_dump($this->withfrom);
  411. var_dump($this->fromtype);
  412. var_dump($this->fromname);*/
  413. // From
  414. if (! empty($this->withfrom))
  415. {
  416. if (! empty($this->withfromreadonly))
  417. {
  418. $out.= '<tr><td class="fieldrequired minwidth200">'.$langs->trans("MailFrom").'</td><td>';
  419. // $this->fromtype is the default value to use to select sender
  420. if (! ($this->fromtype === 'user' && $this->fromid > 0)
  421. && ! ($this->fromtype === 'company')
  422. && ! ($this->fromtype === 'robot')
  423. && ! preg_match('/user_aliases/', $this->fromtype)
  424. && ! preg_match('/global_aliases/', $this->fromtype)
  425. && ! preg_match('/senderprofile/', $this->fromtype)
  426. )
  427. {
  428. // Use this->fromname and this->frommail or error if not defined
  429. $out.= $this->fromname;
  430. if ($this->frommail)
  431. {
  432. $out.= ' &lt;'.$this->frommail.'&gt;';
  433. }
  434. else
  435. {
  436. if ($this->fromtype)
  437. {
  438. $langs->load('errors');
  439. $out.= '<span class="warning"> &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt; </span>';
  440. }
  441. }
  442. } else {
  443. $liste = array();
  444. // Add user email
  445. if (empty($user->email))
  446. {
  447. $langs->load('errors');
  448. $liste['user'] = $user->getFullName($langs) . ' &lt;'.$langs->trans('ErrorNoMailDefinedForThisUser').'&gt;';
  449. }
  450. else
  451. {
  452. $liste['user'] = $user->getFullName($langs) .' &lt;'.$user->email.'&gt;';
  453. }
  454. // Add also company main email
  455. $liste['company'] = $conf->global->MAIN_INFO_SOCIETE_NOM .' &lt;'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'&gt;';
  456. // Add also email aliases if there is some
  457. $listaliases=array('user_aliases'=>$user->email_aliases, 'global_aliases'=>$conf->global->MAIN_INFO_SOCIETE_MAIL_ALIASES);
  458. // Also add robot email
  459. if (! empty($this->fromalsorobot))
  460. {
  461. if (! empty($conf->global->MAIN_MAIL_EMAIL_FROM) && $conf->global->MAIN_MAIL_EMAIL_FROM != $conf->global->MAIN_INFO_SOCIETE_MAIL)
  462. {
  463. $liste['robot'] = $conf->global->MAIN_MAIL_EMAIL_FROM;
  464. if ($this->frommail)
  465. {
  466. $liste['robot'] .= ' &lt;'.$conf->global->MAIN_MAIL_EMAIL_FROM.'&gt;';
  467. }
  468. }
  469. }
  470. // Add also email aliases from the c_email_senderprofile table
  471. $sql='SELECT rowid, label, email FROM '.MAIN_DB_PREFIX.'c_email_senderprofile WHERE active = 1 ORDER BY position';
  472. $resql = $this->db->query($sql);
  473. if ($resql)
  474. {
  475. $num = $this->db->num_rows($resql);
  476. $i=0;
  477. while($i < $num)
  478. {
  479. $obj = $this->db->fetch_object($resql);
  480. if ($obj)
  481. {
  482. $listaliases['senderprofile_'.$obj->rowid] = $obj->label.' <'.$obj->email.'>';
  483. }
  484. $i++;
  485. }
  486. }
  487. else dol_print_error($this->db);
  488. foreach($listaliases as $typealias => $listalias)
  489. {
  490. $posalias=0;
  491. $listaliasarray=explode(',', $listalias);
  492. foreach ($listaliasarray as $listaliasval)
  493. {
  494. $posalias++;
  495. $listaliasval=trim($listaliasval);
  496. if ($listaliasval)
  497. {
  498. $listaliasval=preg_replace('/</', '&lt;', $listaliasval);
  499. $listaliasval=preg_replace('/>/', '&gt;', $listaliasval);
  500. if (! preg_match('/&lt;/', $listaliasval)) $listaliasval='&lt;'.$listaliasval.'&gt;';
  501. $liste[$typealias.'_'.$posalias]=$listaliasval;
  502. }
  503. }
  504. }
  505. // Set the default "From"
  506. $defaultfrom='';
  507. $reshook=$hookmanager->executeHooks('getDefaultFromEmail', $parameters, $this);
  508. if (empty($reshook))
  509. {
  510. $defaultfrom = $this->fromtype;
  511. }
  512. if (! empty($hookmanager->resArray['defaultfrom'])) $defaultfrom=$hookmanager->resArray['defaultfrom'];
  513. // Using combo here make the '<email>' no more visible on list.
  514. //$out.= ' '.$form->selectarray('fromtype', $liste, $this->fromtype, 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 1, '', $disablebademails);
  515. $out.= ' '.$form->selectarray('fromtype', $liste, $defaultfrom, 0, 0, 0, '', 0, 0, 0, '', 'fromforsendingprofile maxwidth200onsmartphone', 0, '', $disablebademails);
  516. }
  517. $out.= "</td></tr>\n";
  518. }
  519. else
  520. {
  521. $out.= '<tr><td class="fieldrequired width200">'.$langs->trans("MailFrom")."</td><td>";
  522. $out.= $langs->trans("Name").':<input type="text" id="fromname" name="fromname" class="maxwidth200onsmartphone" value="'.$this->fromname.'" />';
  523. $out.= '&nbsp; &nbsp; ';
  524. $out.= $langs->trans("EMail").':&lt;<input type="text" id="frommail" name="frommail" class="maxwidth200onsmartphone" value="'.$this->frommail.'" />&gt;';
  525. $out.= "</td></tr>\n";
  526. }
  527. }
  528. // To
  529. if (! empty($this->withto) || is_array($this->withto))
  530. {
  531. $out.= '<tr><td class="fieldrequired">';
  532. if ($this->withtofree) $out.= $form->textwithpicto($langs->trans("MailTo"),$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
  533. else $out.= $langs->trans("MailTo");
  534. $out.= '</td><td>';
  535. if ($this->withtoreadonly)
  536. {
  537. if (! empty($this->toname) && ! empty($this->tomail))
  538. {
  539. $out.= '<input type="hidden" id="toname" name="toname" value="'.$this->toname.'" />';
  540. $out.= '<input type="hidden" id="tomail" name="tomail" value="'.$this->tomail.'" />';
  541. if ($this->totype == 'thirdparty')
  542. {
  543. $soc=new Societe($this->db);
  544. $soc->fetch($this->toid);
  545. $out.= $soc->getNomUrl(1);
  546. }
  547. else if ($this->totype == 'contact')
  548. {
  549. $contact=new Contact($this->db);
  550. $contact->fetch($this->toid);
  551. $out.= $contact->getNomUrl(1);
  552. }
  553. else
  554. {
  555. $out.= $this->toname;
  556. }
  557. $out.= ' &lt;'.$this->tomail.'&gt;';
  558. if ($this->withtofree)
  559. {
  560. $out.= '<br>'.$langs->trans("and").' <input class="minwidth200" id="sendto" name="sendto" value="'.(! is_array($this->withto) && ! is_numeric($this->withto)? (isset($_REQUEST["sendto"])?$_REQUEST["sendto"]:$this->withto) :"").'" />';
  561. }
  562. }
  563. else
  564. {
  565. // Note withto may be a text like 'AllRecipientSelected'
  566. $out.= (! is_array($this->withto) && ! is_numeric($this->withto))?$this->withto:"";
  567. }
  568. }
  569. else
  570. {
  571. if (! empty($this->withtofree))
  572. {
  573. $out.= '<input class="minwidth200" id="sendto" name="sendto" value="'.(! is_array($this->withto) && ! is_numeric($this->withto)? (isset($_REQUEST["sendto"])?$_REQUEST["sendto"]:$this->withto) :"").'" />';
  574. }
  575. if (! empty($this->withto) && is_array($this->withto))
  576. {
  577. if (! empty($this->withtofree)) $out.= " ".$langs->trans("and")."/".$langs->trans("or")." ";
  578. // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
  579. $tmparray = $this->withto;
  580. foreach($tmparray as $key => $val)
  581. {
  582. $tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
  583. }
  584. $withtoselected=GETPOST("receiver",'none'); // Array of selected value
  585. if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action','aZ09') == 'presend')
  586. {
  587. $withtoselected = array_keys($tmparray);
  588. }
  589. $out.= $form->multiselectarray("receiver", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
  590. }
  591. }
  592. $out.= "</td></tr>\n";
  593. }
  594. // To User
  595. if (! empty($this->withtouser) && is_array($this->withtouser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT))
  596. {
  597. $out.= '<tr><td>';
  598. $out.= $langs->trans("MailToUsers");
  599. $out.= '</td><td>';
  600. // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
  601. $tmparray = $this->withtouser;
  602. foreach($tmparray as $key => $val)
  603. {
  604. $tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
  605. }
  606. $withtoselected=GETPOST("receiveruser",'none'); // Array of selected value
  607. if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action','aZ09') == 'presend')
  608. {
  609. $withtoselected = array_keys($tmparray);
  610. }
  611. $out.= $form->multiselectarray("receiveruser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
  612. $out.= "</td></tr>\n";
  613. }
  614. // withoptiononeemailperrecipient
  615. if (! empty($this->withoptiononeemailperrecipient))
  616. {
  617. $out.= '<tr><td class="minwidth200">';
  618. $out.= $langs->trans("GroupEmails");
  619. $out.= '</td><td>';
  620. $out.=' <input type="checkbox" name="oneemailperrecipient"'.($this->withoptiononeemailperrecipient > 0?' checked="checked"':'').'> ';
  621. $out.= $langs->trans("OneEmailPerRecipient");
  622. $out.='<span class="hideonsmartphone">';
  623. $out.=' - ';
  624. $out.= $langs->trans("WarningIfYouCheckOneRecipientPerEmail");
  625. $out.='</span>';
  626. $out.= '</td></tr>';
  627. }
  628. // CC
  629. if (! empty($this->withtocc) || is_array($this->withtocc))
  630. {
  631. $out.= '<tr><td>';
  632. $out.= $form->textwithpicto($langs->trans("MailCC"),$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
  633. $out.= '</td><td>';
  634. if ($this->withtoccreadonly)
  635. {
  636. $out.= (! is_array($this->withtocc) && ! is_numeric($this->withtocc))?$this->withtocc:"";
  637. }
  638. else
  639. {
  640. $out.= '<input class="minwidth200" id="sendtocc" name="sendtocc" value="'.((! is_array($this->withtocc) && ! is_numeric($this->withtocc))? (isset($_POST["sendtocc"])?$_POST["sendtocc"]:$this->withtocc) : (isset($_POST["sendtocc"])?$_POST["sendtocc"]:"") ).'" />';
  641. if (! empty($this->withtocc) && is_array($this->withtocc))
  642. {
  643. $out.= " ".$langs->trans("and")."/".$langs->trans("or")." ";
  644. // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
  645. $tmparray = $this->withtocc;
  646. foreach($tmparray as $key => $val)
  647. {
  648. $tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
  649. }
  650. $withtoccselected=GETPOST("receivercc"); // Array of selected value
  651. $out.= $form->multiselectarray("receivercc", $tmparray, $withtoccselected, null, null, 'inline-block minwidth500',null, "");
  652. }
  653. }
  654. $out.= "</td></tr>\n";
  655. }
  656. // To User cc
  657. if (! empty($this->withtoccuser) && is_array($this->withtoccuser) && !empty($conf->global->MAIN_MAIL_ENABLED_USER_DEST_SELECT))
  658. {
  659. $out.= '<tr><td>';
  660. $out.= $langs->trans("MailToCCUsers");
  661. $out.= '</td><td>';
  662. // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
  663. $tmparray = $this->withtoccuser;
  664. foreach($tmparray as $key => $val)
  665. {
  666. $tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
  667. }
  668. $withtoselected=GETPOST("receiverccuser",'none'); // Array of selected value
  669. if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action','aZ09') == 'presend')
  670. {
  671. $withtoselected = array_keys($tmparray);
  672. }
  673. $out.= $form->multiselectarray("receiverccuser", $tmparray, $withtoselected, null, null, 'inline-block minwidth500', null, "");
  674. $out.= "</td></tr>\n";
  675. }
  676. // CCC
  677. if (! empty($this->withtoccc) || is_array($this->withtoccc))
  678. {
  679. $out.= '<tr><td>';
  680. $out.= $form->textwithpicto($langs->trans("MailCCC"),$langs->trans("YouCanUseCommaSeparatorForSeveralRecipients"));
  681. $out.= '</td><td>';
  682. if (! empty($this->withtocccreadonly))
  683. {
  684. $out.= (! is_array($this->withtoccc) && ! is_numeric($this->withtoccc))?$this->withtoccc:"";
  685. }
  686. else
  687. {
  688. $out.= '<input class="minwidth200" id="sendtoccc" name="sendtoccc" value="'.((! is_array($this->withtoccc) && ! is_numeric($this->withtoccc))? (isset($_POST["sendtoccc"])?$_POST["sendtoccc"]:$this->withtoccc) : (isset($_POST["sendtoccc"])?$_POST["sendtoccc"]:"") ).'" />';
  689. if (! empty($this->withtoccc) && is_array($this->withtoccc))
  690. {
  691. $out.= " ".$langs->trans("and")."/".$langs->trans("or")." ";
  692. // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time
  693. $tmparray = $this->withtoccc;
  694. foreach($tmparray as $key => $val)
  695. {
  696. $tmparray[$key]=dol_htmlentities($tmparray[$key], null, 'UTF-8', true);
  697. }
  698. $withtocccselected=GETPOST("receiverccc"); // Array of selected value
  699. $out.= $form->multiselectarray("receiverccc", $tmparray, $withtocccselected, null, null, null,null, "90%");
  700. }
  701. }
  702. $showinfobcc='';
  703. if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO) && ! empty($this->param['models']) && $this->param['models'] == 'propal_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO;
  704. if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO) && ! empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO;
  705. if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO) && ! empty($this->param['models']) && $this->param['models'] == 'order_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO;
  706. if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO) && ! empty($this->param['models']) && $this->param['models'] == 'facture_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO;
  707. if ($showinfobcc) $out.=' + '.$showinfobcc;
  708. $out.= "</td></tr>\n";
  709. }
  710. // Replyto
  711. if (! empty($this->withreplyto))
  712. {
  713. if ($this->withreplytoreadonly)
  714. {
  715. $out.= '<input type="hidden" id="replyname" name="replyname" value="'.$this->replytoname.'" />';
  716. $out.= '<input type="hidden" id="replymail" name="replymail" value="'.$this->replytomail.'" />';
  717. $out.= "<tr><td>".$langs->trans("MailReply")."</td><td>".$this->replytoname.($this->replytomail?(" &lt;".$this->replytomail."&gt;"):"");
  718. $out.= "</td></tr>\n";
  719. }
  720. }
  721. // Errorsto
  722. if (! empty($this->witherrorsto))
  723. {
  724. //if (! $this->errorstomail) $this->errorstomail=$this->frommail;
  725. $errorstomail = (! empty($conf->global->MAIN_MAIL_ERRORS_TO) ? $conf->global->MAIN_MAIL_ERRORS_TO : $this->errorstomail);
  726. if ($this->witherrorstoreadonly)
  727. {
  728. $out.= '<input type="hidden" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
  729. $out.= '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
  730. $out.= $errorstomail;
  731. $out.= "</td></tr>\n";
  732. }
  733. else
  734. {
  735. $out.= '<tr><td>'.$langs->trans("MailErrorsTo").'</td><td>';
  736. $out.= '<input size="30" id="errorstomail" name="errorstomail" value="'.$errorstomail.'" />';
  737. $out.= "</td></tr>\n";
  738. }
  739. }
  740. // Ask delivery receipt
  741. if (! empty($this->withdeliveryreceipt))
  742. {
  743. $out.= '<tr><td>'.$langs->trans("DeliveryReceipt").'</td><td>';
  744. if (! empty($this->withdeliveryreceiptreadonly))
  745. {
  746. $out.= yn($this->withdeliveryreceipt);
  747. }
  748. else
  749. {
  750. $defaultvaluefordeliveryreceipt=0;
  751. if (! empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_PROPAL) && ! empty($this->param['models']) && $this->param['models'] == 'propal_send') $defaultvaluefordeliveryreceipt=1;
  752. if (! empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_SUPPLIER_PROPOSAL) && ! empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') $defaultvaluefordeliveryreceipt=1;
  753. if (! empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_ORDER) && ! empty($this->param['models']) && $this->param['models'] == 'order_send') $defaultvaluefordeliveryreceipt=1;
  754. if (! empty($conf->global->MAIL_FORCE_DELIVERY_RECEIPT_INVOICE) && ! empty($this->param['models']) && $this->param['models'] == 'facture_send') $defaultvaluefordeliveryreceipt=1;
  755. $out.= $form->selectyesno('deliveryreceipt', (isset($_POST["deliveryreceipt"])?$_POST["deliveryreceipt"]:$defaultvaluefordeliveryreceipt), 1);
  756. }
  757. $out.= "</td></tr>\n";
  758. }
  759. // Topic
  760. if (! empty($this->withtopic))
  761. {
  762. $defaulttopic=GETPOST('subject','none');
  763. if (! GETPOST('modelselected','alpha') || GETPOST('modelmailselected') != '-1')
  764. {
  765. if ($arraydefaultmessage && $arraydefaultmessage->topic) {
  766. $defaulttopic = $arraydefaultmessage->topic;
  767. } elseif (! is_numeric($this->withtopic)) {
  768. $defaulttopic = $this->withtopic;
  769. }
  770. }
  771. $defaulttopic=make_substitutions($defaulttopic,$this->substit);
  772. $out.= '<tr>';
  773. $out.= '<td class="fieldrequired">';
  774. $out.=$form->textwithpicto($langs->trans('MailTopic'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfromtopic');
  775. $out.='</td>';
  776. $out.= '<td>';
  777. if ($this->withtopicreadonly)
  778. {
  779. $out.= $defaulttopic;
  780. $out.= '<input type="hidden" class="quatrevingtpercent" id="subject" name="subject" value="'.$defaulttopic.'" />';
  781. }
  782. else
  783. {
  784. $out.= '<input type="text" class="quatrevingtpercent" id="subject" name="subject" value="'. ((isset($_POST["subject"]) && ! $_POST['modelselected'])?$_POST["subject"]:($defaulttopic?$defaulttopic:'')) .'" />';
  785. }
  786. $out.= "</td></tr>\n";
  787. }
  788. // Attached files
  789. if (! empty($this->withfile))
  790. {
  791. $out.= '<tr>';
  792. $out.= '<td>'.$langs->trans("MailFile").'</td>';
  793. $out.= '<td>';
  794. if ($this->withmaindocfile) // withmaindocfile is set to 1 or -1 to show the checkbox (-1 = checked or 1 = not checked)
  795. {
  796. if (GETPOSTISSET('sendmail'))
  797. {
  798. $this->withmaindocfile = (GETPOST('addmaindocfile', 'alpha') ? -1 : 1);
  799. }
  800. // If a template was selected, we use setup of template to define if join file checkbox is selected or not.
  801. elseif (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0)
  802. {
  803. $this->withmaindocfile = ($arraydefaultmessage->joinfiles ? -1 : 1);
  804. }
  805. }
  806. if (! empty($this->withmaindocfile))
  807. {
  808. if ($this->withmaindocfile == 1)
  809. {
  810. $out.='<input type="checkbox" name="addmaindocfile" value="1" />';
  811. }
  812. if ($this->withmaindocfile == -1)
  813. {
  814. $out.='<input type="checkbox" name="addmaindocfile" value="1" checked="checked" />';
  815. }
  816. $out.=' '.$langs->trans("JoinMainDoc").'.<br>';
  817. }
  818. if (is_numeric($this->withfile))
  819. {
  820. // TODO Trick to have param removedfile containing nb of file to delete. But this does not works without javascript
  821. $out.= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
  822. $out.= '<script type="text/javascript" language="javascript">';
  823. $out.= 'jQuery(document).ready(function () {';
  824. $out.= ' jQuery(".removedfile").click(function() {';
  825. $out.= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
  826. $out.= ' });';
  827. $out.= '})';
  828. $out.= '</script>'."\n";
  829. if (count($listofpaths))
  830. {
  831. foreach($listofpaths as $key => $val)
  832. {
  833. $out.= '<div id="attachfile_'.$key.'">';
  834. $out.= img_mime($listofnames[$key]).' '.$listofnames[$key];
  835. if (! $this->withfilereadonly)
  836. {
  837. $out.= ' <input type="image" style="border: 0px;" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/delete.png" value="'.($key+1).'" class="removedfile" id="removedfile_'.$key.'" name="removedfile_'.$key.'" />';
  838. //$out.= ' <a href="'.$_SERVER["PHP_SELF"].'?removedfile='.($key+1).' id="removedfile_'.$key.'">'.img_delete($langs->trans("Delete").'</a>';
  839. }
  840. $out.= '<br></div>';
  841. }
  842. }
  843. else if (empty($this->withmaindocfile)) // Do not show message if we asked to show the checkbox
  844. {
  845. $out.= $langs->trans("NoAttachedFiles").'<br>';
  846. }
  847. if ($this->withfile == 2) // Can add other files
  848. {
  849. if (!empty($conf->global->FROM_MAIL_USE_INPUT_FILE_MULTIPLE)) $out.= '<input type="file" class="flat" id="addedfile" name="addedfile[]" value="'.$langs->trans("Upload").'" multiple />';
  850. else $out.= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
  851. $out.= ' ';
  852. $out.= '<input class="button" type="submit" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
  853. }
  854. }
  855. else
  856. {
  857. $out.=$this->withfile;
  858. }
  859. $out.= "</td></tr>\n";
  860. }
  861. // Message
  862. if (! empty($this->withbody))
  863. {
  864. $defaultmessage=GETPOST('message','none');
  865. if (! GETPOST('modelselected','alpha') || GETPOST('modelmailselected') != '-1')
  866. {
  867. if ($arraydefaultmessage && $arraydefaultmessage->content) {
  868. $defaultmessage = $arraydefaultmessage->content;
  869. } elseif (! is_numeric($this->withbody)) {
  870. $defaultmessage = $this->withbody;
  871. }
  872. }
  873. // Complete substitution array with the url to make online payment
  874. $paymenturl=''; $validpaymentmethod=array();
  875. if (empty($this->substit['__REF__']))
  876. {
  877. $paymenturl='';
  878. }
  879. else
  880. {
  881. // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
  882. require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
  883. $langs->loadLangs(array('paypal','other'));
  884. $typeforonlinepayment='free';
  885. if ($this->param["models"]=='order' || $this->param["models"]=='order_send') $typeforonlinepayment='order'; // TODO use detection on something else than template
  886. if ($this->param["models"]=='invoice' || $this->param["models"]=='facture_send') $typeforonlinepayment='invoice'; // TODO use detection on something else than template
  887. if ($this->param["models"]=='member') $typeforonlinepayment='member'; // TODO use detection on something else than template
  888. $url=getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']);
  889. $paymenturl=$url;
  890. $validpaymentmethod = getValidOnlinePaymentMethods('');
  891. }
  892. if (count($validpaymentmethod) > 0 && $paymenturl)
  893. {
  894. $langs->load('other');
  895. $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']=str_replace('\n', "\n", $langs->transnoentities("PredefinedMailContentLink", $paymenturl));
  896. $this->substit['__ONLINE_PAYMENT_URL__']=$paymenturl;
  897. }
  898. else
  899. {
  900. $this->substit['__ONLINE_PAYMENT_TEXT_AND_URL__']='';
  901. $this->substit['__ONLINE_PAYMENT_URL__']='';
  902. }
  903. //Add lines substitution key from each line
  904. $lines = '';
  905. $defaultlines = $arraydefaultmessage->content_lines;
  906. if (isset($defaultlines))
  907. {
  908. foreach ($this->substit_lines as $substit_line)
  909. {
  910. $lines .= make_substitutions($defaultlines,$substit_line)."\n";
  911. }
  912. }
  913. $this->substit['__LINES__']=$lines;
  914. $defaultmessage=str_replace('\n',"\n",$defaultmessage);
  915. // Deal with format differences between message and signature (text / HTML)
  916. if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
  917. $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
  918. } else if(!dol_textishtml($defaultmessage) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
  919. $defaultmessage = dol_nl2br($defaultmessage);
  920. }
  921. if (isset($_POST["message"]) && ! $_POST['modelselected']) $defaultmessage=$_POST["message"];
  922. else
  923. {
  924. $defaultmessage=make_substitutions($defaultmessage,$this->substit);
  925. // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
  926. $defaultmessage=preg_replace("/^(<br>)+/","",$defaultmessage);
  927. $defaultmessage=preg_replace("/^\n+/","",$defaultmessage);
  928. }
  929. $out.= '<tr>';
  930. $out.= '<td valign="top">';
  931. $out.=$form->textwithpicto($langs->trans('MailText'), $helpforsubstitution, 1, 'help', '', 0, 2, 'substittooltipfrombody');
  932. $out.='</td>';
  933. $out.= '<td>';
  934. if ($this->withbodyreadonly)
  935. {
  936. $out.= nl2br($defaultmessage);
  937. $out.= '<input type="hidden" id="message" name="message" value="'.$defaultmessage.'" />';
  938. }
  939. else
  940. {
  941. if (! isset($this->ckeditortoolbar)) $this->ckeditortoolbar = 'dolibarr_notes';
  942. // Editor wysiwyg
  943. require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  944. if ($this->withfckeditor == -1)
  945. {
  946. if (! empty($conf->global->FCKEDITOR_ENABLE_MAIL)) $this->withfckeditor=1;
  947. else $this->withfckeditor=0;
  948. }
  949. $doleditor=new DolEditor('message',$defaultmessage,'',280,$this->ckeditortoolbar,'In',true,true,$this->withfckeditor,8,'95%');
  950. $out.= $doleditor->Create(1);
  951. }
  952. $out.= "</td></tr>\n";
  953. }
  954. $out.= '</table>'."\n";
  955. if ($this->withform == 1 || $this->withform == -1)
  956. {
  957. $out.= '<br><div class="center">';
  958. $out.= '<input class="button" type="submit" id="sendmail" name="sendmail" value="'.$langs->trans("SendMail").'"';
  959. // Add a javascript test to avoid to forget to submit file before sending email
  960. if ($this->withfile == 2 && $conf->use_javascript_ajax)
  961. {
  962. $out.= ' onClick="if (document.mailform.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
  963. }
  964. $out.= ' />';
  965. if ($this->withcancel)
  966. {
  967. $out.= ' &nbsp; &nbsp; ';
  968. $out.= '<input class="button" type="submit" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'" />';
  969. }
  970. $out.= '</div>'."\n";
  971. }
  972. if ($this->withform == 1) $out.= '</form>'."\n";
  973. // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
  974. if (! empty($conf->global->MAIN_MAILFORM_DISABLE_ENTERKEY))
  975. {
  976. $out.= '<script type="text/javascript" language="javascript">';
  977. $out.= 'jQuery(document).ready(function () {';
  978. $out.= ' $(document).on("keypress", \'#mailform\', function (e) { /* Note this is called at every key pressed ! */
  979. var code = e.keyCode || e.which;
  980. if (code == 13) {
  981. e.preventDefault();
  982. return false;
  983. }
  984. });';
  985. $out.=' })';
  986. $out.= '</script>';
  987. }
  988. $out.= "<!-- End form mail -->\n";
  989. return $out;
  990. }
  991. }
  992. /**
  993. * Return templates of email with type = $type_template or type = 'all'.
  994. * This search into table c_email_templates. Used by the get_form function.
  995. *
  996. * @param DoliDB $db Database handler
  997. * @param string $type_template Get message for model/type=$type_template, type='all' also included.
  998. * @param string $user Get template public or limited to this user
  999. * @param Translate $outputlangs Output lang object
  1000. * @param int $id Id of template to find, or -1 for first found with position 0, or 0 for first found whatever is position (priority order depends on lang provided or not) or -2 for exact match with label (no answer if not found)
  1001. * @param int $active 1=Only active template, 0=Only disabled, -1=All
  1002. * @param string $label Label of template
  1003. * @return ModelMail One instance of ModelMail
  1004. */
  1005. public function getEMailTemplate($db, $type_template, $user, $outputlangs, $id=0, $active=1, $label='')
  1006. {
  1007. $ret = new ModelMail();
  1008. if ($id == -2 && empty($label))
  1009. {
  1010. $this->error = 'LabelIsMandatoryWhenIdIs-2';
  1011. return -1;
  1012. }
  1013. $sql = "SELECT rowid, label, topic, joinfiles, content, content_lines, lang";
  1014. $sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates';
  1015. $sql.= " WHERE (type_template='".$db->escape($type_template)."' OR type_template='all')";
  1016. $sql.= " AND entity IN (".getEntity('c_email_templates').")";
  1017. $sql.= " AND (private = 0 OR fk_user = ".$user->id.")"; // Get all public or private owned
  1018. if ($active >= 0) $sql.=" AND active = ".$active;
  1019. if ($label) $sql.=" AND label ='".$db->escape($label)."'";
  1020. if (! ($id > 0) && is_object($outputlangs)) $sql.= " AND (lang = '".$db->escape($outputlangs->defaultlang)."' OR lang IS NULL OR lang = '')";
  1021. if ($id > 0) $sql.= " AND rowid=".$id;
  1022. if ($id == -1) $sql.= " AND position=0";
  1023. if (is_object($outputlangs)) $sql.= $db->order("position,lang,label","ASC,DESC,ASC"); // We want line with lang set first, then with lang null or ''
  1024. else $sql.= $db->order("position,lang,label","ASC,ASC,ASC"); // If no language provided, we give priority to lang not defined
  1025. $sql.= $db->plimit(1);
  1026. //print $sql;
  1027. $resql = $db->query($sql);
  1028. if ($resql)
  1029. {
  1030. // Get first found
  1031. $obj = $db->fetch_object($resql);
  1032. if ($obj) {
  1033. $ret->id = $obj->rowid;
  1034. $ret->label = $obj->label;
  1035. $ret->lang = $obj->lang;
  1036. $ret->topic = $obj->topic;
  1037. $ret->content = $obj->content;
  1038. $ret->content_lines = $obj->content_lines;
  1039. $ret->joinfiles = $obj->joinfiles;
  1040. }
  1041. elseif($id == -2) {
  1042. // Not found with the provided label
  1043. return -1;
  1044. }
  1045. else { // If there is no template at all
  1046. $defaultmessage='';
  1047. if ($type_template=='body') { $defaultmessage=$this->withbody; } // Special case to use this->withbody as content
  1048. elseif ($type_template=='facture_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendInvoice"); }
  1049. elseif ($type_template=='facture_relance') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendInvoiceReminder"); }
  1050. elseif ($type_template=='propal_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendProposal"); }
  1051. elseif ($type_template=='supplier_proposal_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendSupplierProposal"); }
  1052. elseif ($type_template=='order_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendOrder"); }
  1053. elseif ($type_template=='order_supplier_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendSupplierOrder"); }
  1054. elseif ($type_template=='invoice_supplier_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendSupplierInvoice"); }
  1055. elseif ($type_template=='shipping_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendShipping"); }
  1056. elseif ($type_template=='fichinter_send') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentSendFichInter"); }
  1057. elseif ($type_template=='thirdparty') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentThirdparty"); }
  1058. elseif ($type_template=='user') { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContentUser"); }
  1059. elseif (!empty($type_template)) { $defaultmessage=$outputlangs->transnoentities("PredefinedMailContent".ucfirst($type_template)); }
  1060. $ret->label = 'default';
  1061. $ret->lang = $outputlangs->defaultlang;
  1062. $ret->topic = '';
  1063. $ret->joinfiles = 1;
  1064. $ret->content = $defaultmessage;
  1065. $ret->content_lines ='';
  1066. }
  1067. $db->free($resql);
  1068. return $ret;
  1069. }
  1070. else
  1071. {
  1072. dol_print_error($db);
  1073. return -1;
  1074. }
  1075. }
  1076. /**
  1077. * Find if template exists
  1078. * Search into table c_email_templates
  1079. *
  1080. * @param string $type_template Get message for key module
  1081. * @param string $user Use template public or limited to this user
  1082. * @param Translate $outputlangs Output lang object
  1083. * @return int <0 if KO,
  1084. */
  1085. public function isEMailTemplate($type_template, $user, $outputlangs)
  1086. {
  1087. $ret=array();
  1088. $sql = "SELECT label, topic, content, lang";
  1089. $sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates';
  1090. $sql.= " WHERE type_template='".$this->db->escape($type_template)."'";
  1091. $sql.= " AND entity IN (".getEntity('c_email_templates').")";
  1092. $sql.= " AND (fk_user is NULL or fk_user = 0 or fk_user = ".$user->id.")";
  1093. if (is_object($outputlangs)) $sql.= " AND (lang = '".$outputlangs->defaultlang."' OR lang IS NULL OR lang = '')";
  1094. $sql.= $this->db->order("lang,label","ASC");
  1095. //print $sql;
  1096. $resql = $this->db->query($sql);
  1097. if ($resql)
  1098. {
  1099. $num= $this->db->num_rows($resql);
  1100. $this->db->free($resql);
  1101. return $num;
  1102. }
  1103. else
  1104. {
  1105. $this->error=get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
  1106. return -1;
  1107. }
  1108. }
  1109. /**
  1110. * Find if template exists and are available for current user, then set them into $this->lines_module.
  1111. * Search into table c_email_templates
  1112. *
  1113. * @param string $type_template Get message for key module
  1114. * @param string $user Use template public or limited to this user
  1115. * @param Translate $outputlangs Output lang object
  1116. * @param int $active 1=Only active template, 0=Only disabled, -1=All
  1117. * @return int <0 if KO, nb of records found if OK
  1118. */
  1119. public function fetchAllEMailTemplate($type_template, $user, $outputlangs, $active=1)
  1120. {
  1121. $ret=array();
  1122. $sql = "SELECT rowid, label, topic, content, content_lines, lang, fk_user, private, position";
  1123. $sql.= " FROM ".MAIN_DB_PREFIX.'c_email_templates';
  1124. $sql.= " WHERE type_template IN ('".$this->db->escape($type_template)."', 'all')";
  1125. $sql.= " AND entity IN (".getEntity('c_email_templates').")";
  1126. $sql.= " AND (private = 0 OR fk_user = ".$user->id.")"; // See all public templates or templates I own.
  1127. if ($active >= 0) $sql.=" AND active = ".$active;
  1128. //if (is_object($outputlangs)) $sql.= " AND (lang = '".$outputlangs->defaultlang."' OR lang IS NULL OR lang = '')"; // Return all languages
  1129. $sql.= $this->db->order("position,lang,label","ASC");
  1130. //print $sql;
  1131. $resql = $this->db->query($sql);
  1132. if ($resql)
  1133. {
  1134. $num=$this->db->num_rows($resql);
  1135. $this->lines_model=array();
  1136. while ($obj = $this->db->fetch_object($resql))
  1137. {
  1138. $line = new ModelMail();
  1139. $line->id=$obj->rowid;
  1140. $line->label=$obj->label;
  1141. $line->lang=$obj->lang;
  1142. $line->fk_user=$obj->fk_user;
  1143. $line->private=$obj->private;
  1144. $line->position=$obj->position;
  1145. $line->topic=$obj->topic;
  1146. $line->content=$obj->content;
  1147. $line->content_lines=$obj->content_lines;
  1148. $this->lines_model[]=$line;
  1149. }
  1150. $this->db->free($resql);
  1151. return $num;
  1152. }
  1153. else
  1154. {
  1155. $this->error=get_class($this).' '.__METHOD__.' ERROR:'.$this->db->lasterror();
  1156. return -1;
  1157. }
  1158. }
  1159. /**
  1160. * Set substit array from object. This is call when suggesting the email template into forms before sending email.
  1161. *
  1162. * @param CommonObject $object Object to use
  1163. * @param Translate $outputlangs Object lang
  1164. * @return void
  1165. * @see getCommonSubstitutionArray
  1166. */
  1167. function setSubstitFromObject($object, $outputlangs)
  1168. {
  1169. global $conf, $user;
  1170. $parameters=array();
  1171. $tmparray=getCommonSubstitutionArray($outputlangs, 0, null, $object);
  1172. complete_substitutions_array($tmparray, $outputlangs, null, $parameters);
  1173. $this->substit=$tmparray;
  1174. // Fill substit_lines with each object lines content
  1175. if (is_array($object->lines))
  1176. {
  1177. foreach ($object->lines as $line)
  1178. {
  1179. $substit_line = array(
  1180. '__PRODUCT_REF__' => isset($line->product_ref) ? $line->product_ref : '',
  1181. '__PRODUCT_LABEL__' => isset($line->product_label) ? $line->product_label : '',
  1182. '__PRODUCT_DESCRIPTION__' => isset($line->product_desc) ? $line->product_desc : '',
  1183. '__LABEL__' => isset($line->label) ? $line->label : '',
  1184. '__DESCRIPTION__' => isset($line->desc) ? $line->desc : '',
  1185. '__DATE_START_YMD__' => dol_print_date($line->date_start, 'day', 0, $outputlangs),
  1186. '__DATE_END_YMD__' => dol_print_date($line->date_end, 'day', 0, $outputlangs),
  1187. '__QUANTITY__' => $line->qty,
  1188. '__SUBPRICE__' => price($line->subprice),
  1189. '__AMOUNT__' => price($line->total_ttc),
  1190. '__AMOUNT_EXCL_TAX__' => price($line->total_ht)
  1191. );
  1192. // Create dynamic tags for __PRODUCT_EXTRAFIELD_FIELD__
  1193. if (!empty($line->fk_product))
  1194. {
  1195. if (! is_object($extrafields)) $extrafields = new ExtraFields($this->db);
  1196. $extrafields->fetch_name_optionals_label('product', true);
  1197. $product = new Product($this->db);
  1198. $product->fetch($line->fk_product, '', '', 1);
  1199. $product->fetch_optionals();
  1200. if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0)
  1201. {
  1202. foreach ($extrafields->attributes[$product->table_element]['label'] as $key => $label) {
  1203. $substit_line['__PRODUCT_EXTRAFIELD_' . strtoupper($key) . '__'] = $product->array_options['options_' . $key];
  1204. }
  1205. }
  1206. }
  1207. $this->substit_lines[] = $substit_line;
  1208. }
  1209. }
  1210. }
  1211. /**
  1212. * Get list of substitution keys available for emails. This is used for tooltips help.
  1213. * This include the complete_substitutions_array.
  1214. *
  1215. * @param string $mode 'formemail', 'formemailwithlines', 'formemailforlines', 'emailing', ...
  1216. * @param Object $object Object if applicable
  1217. * @return array Array of substitution values for emails.
  1218. */
  1219. static function getAvailableSubstitKey($mode='formemail', $object=null)
  1220. {
  1221. global $conf, $langs;
  1222. $tmparray=array();
  1223. if ($mode == 'formemail' || $mode == 'formemailwithlines' || $mode == 'formemailforlines')
  1224. {
  1225. $parameters=array('mode'=>$mode);
  1226. $tmparray=getCommonSubstitutionArray($langs, 2, null, $object); // Note: On email templated edition, this is null because it is related to all type of objects
  1227. complete_substitutions_array($tmparray, $langs, null, $parameters);
  1228. if ($mode == 'formwithlines')
  1229. {
  1230. $tmparray['__LINES__'] = '__LINES__'; // Will be set by the get_form function
  1231. }
  1232. if ($mode == 'formforlines')
  1233. {
  1234. $tmparray['__QUANTITY__'] = '__QUANTITY__'; // Will be set by the get_form function
  1235. }
  1236. }
  1237. if ($mode == 'emailing')
  1238. {
  1239. $parameters=array('mode'=>$mode);
  1240. $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
  1241. complete_substitutions_array($tmparray, $langs, null, $parameters);
  1242. // For mass emailing, we have different keys
  1243. $tmparray['__ID__'] = 'IdRecord';
  1244. $tmparray['__EMAIL__'] = 'EMailRecipient';
  1245. $tmparray['__LASTNAME__'] = 'Lastname';
  1246. $tmparray['__FIRSTNAME__'] = 'Firstname';
  1247. $tmparray['__MAILTOEMAIL__'] = 'TagMailtoEmail';
  1248. $tmparray['__OTHER1__'] = 'Other1';
  1249. $tmparray['__OTHER2__'] = 'Other2';
  1250. $tmparray['__OTHER3__'] = 'Other3';
  1251. $tmparray['__OTHER4__'] = 'Other4';
  1252. $tmparray['__OTHER5__'] = 'Other5';
  1253. $tmparray['__USER_SIGNATURE__'] = 'TagSignature';
  1254. $tmparray['__CHECK_READ__'] = 'TagCheckMail';
  1255. $tmparray['__UNSUBSCRIBE__'] = 'TagUnsubscribe';
  1256. //,'__PERSONALIZED__' => 'Personalized' // Hidden because not used yet in mass emailing
  1257. $onlinepaymentenabled = 0;
  1258. if (! empty($conf->paypal->enabled)) $onlinepaymentenabled++;
  1259. if (! empty($conf->paybox->enabled)) $onlinepaymentenabled++;
  1260. if (! empty($conf->stripe->enabled)) $onlinepaymentenabled++;
  1261. if ($onlinepaymentenabled && ! empty($conf->global->PAYMENT_SECURITY_TOKEN))
  1262. {
  1263. $tmparray['__SECUREKEYPAYMENT__']=$conf->global->PAYMENT_SECURITY_TOKEN;
  1264. if (! empty($conf->global->PAYMENT_SECURITY_TOKEN_UNIQUE))
  1265. {
  1266. if ($conf->adherent->enabled) $tmparray['__SECUREKEYPAYMENT_MEMBER__']='SecureKeyPAYMENTUniquePerMember';
  1267. if ($conf->facture->enabled) $tmparray['__SECUREKEYPAYMENT_INVOICE__']='SecureKeyPAYMENTUniquePerInvoice';
  1268. if ($conf->commande->enabled) $tmparray['__SECUREKEYPAYMENT_ORDER__']='SecureKeyPAYMENTUniquePerOrder';
  1269. if ($conf->contrat->enabled) $tmparray['__SECUREKEYPAYMENT_CONTRACTLINE__']='SecureKeyPAYMENTUniquePerContractLine';
  1270. }
  1271. }
  1272. else
  1273. {
  1274. /* No need to show into tooltip help, option is not enabled
  1275. $vars['__SECUREKEYPAYMENT__']='';
  1276. $vars['__SECUREKEYPAYMENT_MEMBER__']='';
  1277. $vars['__SECUREKEYPAYMENT_INVOICE__']='';
  1278. $vars['__SECUREKEYPAYMENT_ORDER__']='';
  1279. $vars['__SECUREKEYPAYMENT_CONTRACTLINE__']='';
  1280. */
  1281. }
  1282. }
  1283. foreach($tmparray as $key => $val)
  1284. {
  1285. if (empty($val)) $tmparray[$key]=$key;
  1286. }
  1287. return $tmparray;
  1288. }
  1289. }
  1290. /**
  1291. * ModelMail
  1292. */
  1293. class ModelMail
  1294. {
  1295. /**
  1296. * @var int ID
  1297. */
  1298. public $id;
  1299. /**
  1300. * @var string Model mail label
  1301. */
  1302. public $label;
  1303. public $topic;
  1304. public $content;
  1305. public $content_lines;
  1306. public $lang;
  1307. public $joinfiles;
  1308. }