html.formmail.class.php 55 KB

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