html.formmail.class.php 64 KB

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