html.formticket.class.php 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. <?php
  2. /* Copyright (C) 2013-2015 Jean-François FERRY <hello@librethic.io>
  3. * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
  4. * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
  5. * Copyright (C) 2021 Juanjo Menent <jmenent@2byte.es>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file htdocs/core/class/html.formticket.class.php
  22. * \ingroup ticket
  23. * \brief Fichier de la classe permettant la generation du formulaire html d'envoi de mail unitaire
  24. */
  25. require_once DOL_DOCUMENT_ROOT."/core/class/html.form.class.php";
  26. require_once DOL_DOCUMENT_ROOT."/core/class/html.formmail.class.php";
  27. require_once DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php";
  28. if (!class_exists('FormCompany')) {
  29. include DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
  30. }
  31. /**
  32. * Classe permettant la generation du formulaire d'un nouveau ticket.
  33. *
  34. * @package Ticket
  35. * \remarks Utilisation: $formticket = new FormTicket($db)
  36. * \remarks $formticket->proprietes=1 ou chaine ou tableau de valeurs
  37. * \remarks $formticket->show_form() affiche le formulaire
  38. */
  39. class FormTicket
  40. {
  41. /**
  42. * @var DoliDB Database handler.
  43. */
  44. public $db;
  45. public $track_id;
  46. /**
  47. * @var int ID
  48. */
  49. public $fk_user_create;
  50. public $message;
  51. public $topic_title;
  52. public $action;
  53. public $withtopic;
  54. public $withemail;
  55. /**
  56. *
  57. * @var int $withsubstit Show substitution array
  58. */
  59. public $withsubstit;
  60. public $withfile;
  61. public $withfilereadonly;
  62. public $ispublic; // To show information or not into public form
  63. public $withtitletopic;
  64. public $withcompany; // affiche liste déroulante company
  65. public $withfromsocid;
  66. public $withfromcontactid;
  67. public $withnotifytiersatcreate;
  68. public $withusercreate; // Show name of creating user in form
  69. public $withcreatereadonly;
  70. public $withref; // Show ref field
  71. public $withcancel;
  72. /**
  73. *
  74. * @var array $substit Substitutions
  75. */
  76. public $substit = array();
  77. public $param = array();
  78. /**
  79. * @var string Error code (or message)
  80. */
  81. public $error;
  82. /**
  83. * Constructor
  84. *
  85. * @param DoliDB $db Database handler
  86. */
  87. public function __construct($db)
  88. {
  89. global $conf;
  90. $this->db = $db;
  91. $this->action = 'add';
  92. $this->withcompany = $conf->societe->enabled ? 1 : 0;
  93. $this->withfromsocid = 0;
  94. $this->withfromcontactid = 0;
  95. //$this->withthreadid=0;
  96. //$this->withtitletopic='';
  97. $this->withnotifytiersatcreate = 0;
  98. $this->withusercreate = 1;
  99. $this->withcreatereadonly = 1;
  100. $this->withemail = 0;
  101. $this->withref = 0;
  102. $this->withextrafields = 0; // Show extrafields or not
  103. //$this->withtopicreadonly=0;
  104. }
  105. /**
  106. * Show the form to input ticket
  107. *
  108. * @param int $withdolfichehead With dol_get_fiche_head() and dol_get_fiche_end()
  109. * @param string $mode Mode ('create' or 'edit')
  110. * @param int $public 1=If we show the form for the public interface
  111. * @return void
  112. */
  113. public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0)
  114. {
  115. global $conf, $langs, $user, $hookmanager;
  116. // Load translation files required by the page
  117. $langs->loadLangs(array('other', 'mails', 'ticket'));
  118. $form = new Form($this->db);
  119. $formcompany = new FormCompany($this->db);
  120. $ticketstatic = new Ticket($this->db);
  121. $soc = new Societe($this->db);
  122. if (!empty($this->withfromsocid) && $this->withfromsocid > 0) {
  123. $soc->fetch($this->withfromsocid);
  124. }
  125. $ticketstat = new Ticket($this->db);
  126. $extrafields = new ExtraFields($this->db);
  127. $extrafields->fetch_name_optionals_label($ticketstat->table_element);
  128. print "\n<!-- Begin form TICKET -->\n";
  129. if ($withdolfichehead) {
  130. print dol_get_fiche_head(null, 'card', '', 0, '');
  131. }
  132. print '<form method="POST" '.($withdolfichehead ? '' : 'style="margin-bottom: 30px;" ').'name="ticket" id="form_create_ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
  133. print '<input type="hidden" name="token" value="'.newToken().'">';
  134. print '<input type="hidden" name="action" value="'.$this->action.'">';
  135. foreach ($this->param as $key => $value) {
  136. print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
  137. }
  138. print '<input type="hidden" name="fk_user_create" value="'.$this->fk_user_create.'">';
  139. print '<table class="border centpercent">';
  140. if ($this->withref) {
  141. // Ref
  142. $defaultref = $ticketstat->getDefaultRef();
  143. print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
  144. print '<input type="text" name="ref" value="'.dol_escape_htmltag(GETPOST("ref", 'alpha') ? GETPOST("ref", 'alpha') : $defaultref).'">';
  145. print '</td></tr>';
  146. }
  147. // TITLE
  148. if ($this->withemail) {
  149. print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("Email").'</span></label></td><td>';
  150. print '<input class="text minwidth200" id="email" name="email" value="'.(GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $subject).'" autofocus>';
  151. print '</td></tr>';
  152. }
  153. // If ticket created from another object
  154. if (isset($this->param['origin']) && $this->param['originid'] > 0) {
  155. // Parse element/subelement (ex: project_task)
  156. $element = $subelement = $this->param['origin'];
  157. $regs = array();
  158. if (preg_match('/^([^_]+)_([^_]+)/i', $this->param['origin'], $regs)) {
  159. $element = $regs[1];
  160. $subelement = $regs[2];
  161. }
  162. dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
  163. $classname = ucfirst($subelement);
  164. $objectsrc = new $classname($this->db);
  165. $objectsrc->fetch(GETPOST('originid', 'int'));
  166. if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
  167. $objectsrc->fetch_lines();
  168. }
  169. $objectsrc->fetch_thirdparty();
  170. $newclassname = $classname;
  171. print '<tr><td>'.$langs->trans($newclassname).'</td><td colspan="2"><input name="'.$subelement.'id" value="'.GETPOST('originid').'" type="hidden" />'.$objectsrc->getNomUrl(1).'</td></tr>';
  172. }
  173. // Type
  174. print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">'.$langs->trans("TicketTypeRequest").'</span></label></td><td>';
  175. $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, 0, 0, 0, 'minwidth200');
  176. print '</td></tr>';
  177. // Group
  178. print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">'.$langs->trans("TicketCategory").'</span></label></td><td>';
  179. $filter = '';
  180. if ($public) {
  181. $filter = 'public=1';
  182. }
  183. $this->selectGroupTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', $filter, 2, 0, 0, 0, 'minwidth200');
  184. print '</td></tr>';
  185. // Severity
  186. print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">'.$langs->trans("TicketSeverity").'</span></label></td><td>';
  187. $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, 0);
  188. print '</td></tr>';
  189. // Subject
  190. if ($this->withtitletopic) {
  191. print '<tr><td><label for="subject"><span class="fieldrequired">'.$langs->trans("Subject").'</span></label></td><td>';
  192. // Réponse à un ticket : affichage du titre du thread en readonly
  193. if ($this->withtopicreadonly) {
  194. print $langs->trans('SubjectAnswerToTicket').' '.$this->topic_title;
  195. print '</td></tr>';
  196. } else {
  197. if ($this->withthreadid > 0) {
  198. $subject = $langs->trans('SubjectAnswerToTicket').' '.$this->withthreadid.' : '.$this->topic_title.'';
  199. }
  200. print '<input class="text minwidth500" id="subject" name="subject" value="'.(GETPOST('subject', 'alpha') ? GETPOST('subject', 'alpha') : $subject).'" autofocus />';
  201. print '</td></tr>';
  202. }
  203. }
  204. // MESSAGE
  205. $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : '';
  206. print '<tr><td><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span></label></td><td>';
  207. // If public form, display more information
  208. $toolbarname = 'dolibarr_notes';
  209. if ($this->ispublic) {
  210. $toolbarname = 'dolibarr_details';
  211. print '<div class="warning">'.($conf->global->TICKET_PUBLIC_TEXT_HELP_MESSAGE ? $conf->global->TICKET_PUBLIC_TEXT_HELP_MESSAGE : $langs->trans('TicketPublicPleaseBeAccuratelyDescribe')).'</div>';
  212. }
  213. include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  214. $uselocalbrowser = true;
  215. $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_TICKET, ROWS_8, '90%');
  216. $doleditor->Create();
  217. print '</td></tr>';
  218. if ($public && !empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) {
  219. require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
  220. print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("SecurityCode").'</span></label></td><td>';
  221. print '<span class="span-icon-security inline-block">';
  222. print '<input id="securitycode" placeholder="'.$langs->trans("SecurityCode").'" class="flat input-icon-security width150" type="text" maxlength="5" name="code" tabindex="3" />';
  223. print '</span>';
  224. print '<span class="nowrap inline-block">';
  225. print '<img class="inline-block valignmiddle" src="'.DOL_URL_ROOT.'/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />';
  226. print '<a class="inline-block valignmiddle" href="'.$php_self.'" tabindex="4" data-role="button">'.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'</a>';
  227. print '</span>';
  228. print '</td></tr>';
  229. }
  230. //Categories
  231. if ($conf->categorie->enabled) {
  232. // Categories
  233. print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
  234. $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 1);
  235. print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
  236. print "</td></tr>";
  237. }
  238. // Attached files
  239. if (!empty($this->withfile)) {
  240. // Define list of attached files
  241. $listofpaths = array();
  242. $listofnames = array();
  243. $listofmimes = array();
  244. if (!empty($_SESSION["listofpaths"])) {
  245. $listofpaths = explode(';', $_SESSION["listofpaths"]);
  246. }
  247. if (!empty($_SESSION["listofnames"])) {
  248. $listofnames = explode(';', $_SESSION["listofnames"]);
  249. }
  250. if (!empty($_SESSION["listofmimes"])) {
  251. $listofmimes = explode(';', $_SESSION["listofmimes"]);
  252. }
  253. $out = '<tr>';
  254. $out .= '<td>'.$langs->trans("MailFile").'</td>';
  255. $out .= '<td>';
  256. // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
  257. $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
  258. $out .= '<script type="text/javascript" language="javascript">';
  259. $out .= 'jQuery(document).ready(function () {';
  260. $out .= ' jQuery(".removedfile").click(function() {';
  261. $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
  262. $out .= ' });';
  263. $out .= '})';
  264. $out .= '</script>'."\n";
  265. if (count($listofpaths)) {
  266. foreach ($listofpaths as $key => $val) {
  267. $out .= '<div id="attachfile_'.$key.'">';
  268. $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
  269. if (!$this->withfilereadonly) {
  270. $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.'" />';
  271. }
  272. $out .= '<br></div>';
  273. }
  274. } else {
  275. $out .= $langs->trans("NoAttachedFiles").'<br>';
  276. }
  277. if ($this->withfile == 2) { // Can add other files
  278. $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
  279. $out .= ' ';
  280. $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="'.$langs->trans("MailingAddFile").'" />';
  281. }
  282. $out .= "</td></tr>\n";
  283. print $out;
  284. }
  285. // User of creation
  286. if ($this->withusercreate > 0 && $this->fk_user_create) {
  287. print '<tr><td class="titlefield">'.$langs->trans("CreatedBy").'</td><td>';
  288. $langs->load("users");
  289. $fuser = new User($this->db);
  290. if ($this->withcreatereadonly) {
  291. if ($res = $fuser->fetch($this->fk_user_create)) {
  292. print $fuser->getNomUrl(1);
  293. }
  294. }
  295. print ' &nbsp; ';
  296. print "</td></tr>\n";
  297. }
  298. // Customer or supplier
  299. if ($this->withcompany) {
  300. // altairis: force company and contact id for external user
  301. if (empty($user->socid)) {
  302. // Company
  303. print '<tr><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
  304. $events = array();
  305. $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
  306. print img_picto('', 'company', 'class="paddingright"');
  307. print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, '', $events, 0, 'minwidth200');
  308. print '</td></tr>';
  309. if (!empty($conf->use_javascript_ajax) && !empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT)) {
  310. $htmlname = 'socid';
  311. print '<script type="text/javascript">
  312. $(document).ready(function () {
  313. jQuery("#'.$htmlname.'").change(function () {
  314. var obj = '.json_encode($events).';
  315. $.each(obj, function(key,values) {
  316. if (values.method.length) {
  317. runJsCodeForEvent'.$htmlname.'(values);
  318. }
  319. });
  320. });
  321. function runJsCodeForEvent'.$htmlname.'(obj) {
  322. console.log("Run runJsCodeForEvent'.$htmlname.'");
  323. var id = $("#'.$htmlname.'").val();
  324. var method = obj.method;
  325. var url = obj.url;
  326. var htmlname = obj.htmlname;
  327. var showempty = obj.showempty;
  328. $.getJSON(url,
  329. {
  330. action: method,
  331. id: id,
  332. htmlname: htmlname,
  333. showempty: showempty
  334. },
  335. function(response) {
  336. $.each(obj.params, function(key,action) {
  337. if (key.length) {
  338. var num = response.num;
  339. if (num > 0) {
  340. $("#" + key).removeAttr(action);
  341. } else {
  342. $("#" + key).attr(action, action);
  343. }
  344. }
  345. });
  346. $("select#" + htmlname).html(response.value);
  347. if (response.num) {
  348. var selecthtml_str = response.value;
  349. var selecthtml_dom=$.parseHTML(selecthtml_str);
  350. if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
  351. $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
  352. }
  353. } else {
  354. $("#inputautocomplete"+htmlname).val("");
  355. }
  356. $("select#" + htmlname).change(); /* Trigger event change */
  357. }
  358. );
  359. }
  360. });
  361. </script>';
  362. }
  363. // Contact and type
  364. print '<tr><td>'.$langs->trans("Contact").'</td><td>';
  365. // If no socid, set to -1 to avoid full contacts list
  366. $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
  367. print img_picto('', 'contact', 'class="paddingright"');
  368. print $form->selectcontacts($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 0, 'minwidth200');
  369. print ' ';
  370. $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
  371. print '</td></tr>';
  372. } else {
  373. print '<tr><td class="titlefield"><input type="hidden" name="socid" value="'.$user->socid.'"/></td>';
  374. print '<td><input type="hidden" name="contactid" value="'.$user->contact_id.'"/></td>';
  375. print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
  376. }
  377. // Notify thirdparty at creation
  378. if (empty($this->ispublic)) {
  379. print '<tr><td><label for="notify_tiers_at_create">'.$langs->trans("TicketNotifyTiersAtCreation").'</label></td><td>';
  380. print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate ? ' checked="checked"' : '').'>';
  381. print '</td></tr>';
  382. }
  383. // User assigned
  384. print '<tr><td>';
  385. print $langs->trans("AssignedTo");
  386. print '</td><td>';
  387. print $form->select_dolusers(GETPOST('fk_user_assign', 'int'), 'fk_user_assign', 1);
  388. print '</td>';
  389. print '</tr>';
  390. }
  391. if (!empty($conf->projet->enabled) && !$this->ispublic) {
  392. $formproject = new FormProjets($this->db);
  393. print '<tr><td><label for="project"><span class="">'.$langs->trans("Project").'</span></label></td><td>';
  394. print img_picto('', 'project').$formproject->select_projects(-1, GETPOST('projectid', 'int'), 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
  395. print '</td></tr>';
  396. }
  397. // Other attributes
  398. $parameters = array();
  399. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $this->action); // Note that $action and $object may have been modified by hook
  400. if (empty($reshook)) {
  401. print $ticketstat->showOptionals($extrafields, 'create');
  402. }
  403. print '</table>';
  404. if ($withdolfichehead) {
  405. print dol_get_fiche_end();
  406. }
  407. print '<br><div class="center">';
  408. print '<input class="button" type="submit" name="add" value="'.$langs->trans(($this->withthreadid > 0 ? "SendResponse" : "CreateTicket")).'" />';
  409. if ($this->withcancel) {
  410. print " &nbsp; &nbsp; &nbsp;";
  411. print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
  412. }
  413. print '</div>';
  414. print '<input type="hidden" name="page_y">'."\n";
  415. print "</form>\n";
  416. print "<!-- End form TICKET -->\n";
  417. }
  418. /**
  419. * Return html list of tickets type
  420. *
  421. * @param string $selected Id du type pre-selectionne
  422. * @param string $htmlname Nom de la zone select
  423. * @param string $filtertype To filter on field type in llx_c_ticket_type (array('code'=>xx,'label'=>zz))
  424. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  425. * @param int $empty 1=peut etre vide, 0 sinon
  426. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  427. * @param int $maxlength Max length of label
  428. * @param string $morecss More CSS
  429. * @return void
  430. */
  431. public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
  432. {
  433. global $langs, $user;
  434. $ticketstat = new Ticket($this->db);
  435. dol_syslog(get_class($this)."::select_types_tickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
  436. $filterarray = array();
  437. if ($filtertype != '' && $filtertype != '-1') {
  438. $filterarray = explode(',', $filtertype);
  439. }
  440. $ticketstat->loadCacheTypesTickets();
  441. print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
  442. if ($empty) {
  443. print '<option value="">&nbsp;</option>';
  444. }
  445. if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
  446. foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
  447. // On passe si on a demande de filtrer sur des modes de paiments particuliers
  448. if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
  449. continue;
  450. }
  451. // We discard empty line if showempty is on because an empty line has already been output.
  452. if ($empty && empty($arraytypes['code'])) {
  453. continue;
  454. }
  455. if ($format == 0) {
  456. print '<option value="'.$id.'"';
  457. }
  458. if ($format == 1) {
  459. print '<option value="'.$arraytypes['code'].'"';
  460. }
  461. if ($format == 2) {
  462. print '<option value="'.$arraytypes['code'].'"';
  463. }
  464. if ($format == 3) {
  465. print '<option value="'.$id.'"';
  466. }
  467. // Si selected est text, on compare avec code, sinon avec id
  468. if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
  469. print ' selected="selected"';
  470. } elseif ($selected == $id) {
  471. print ' selected="selected"';
  472. } elseif ($arraytypes['use_default'] == "1" && !$selected && !$empty) {
  473. print ' selected="selected"';
  474. }
  475. print '>';
  476. $value = '&nbsp;';
  477. if ($format == 0) {
  478. $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
  479. } elseif ($format == 1) {
  480. $value = $arraytypes['code'];
  481. } elseif ($format == 2) {
  482. $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
  483. } elseif ($format == 3) {
  484. $value = $arraytypes['code'];
  485. }
  486. print $value;
  487. print '</option>';
  488. }
  489. }
  490. print '</select>';
  491. if ($user->admin && !$noadmininfo) {
  492. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  493. }
  494. print ajax_combobox('select'.$htmlname);
  495. }
  496. /**
  497. * Return html list of ticket anaytic codes
  498. *
  499. * @param string $selected Id categorie pre-selectionnée
  500. * @param string $htmlname Name of select component
  501. * @param string $filtertype To filter on some properties in llx_c_ticket_category ('public = 1'). This parameter must not come from input of users.
  502. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  503. * @param int $empty 1=peut etre vide, 0 sinon
  504. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  505. * @param int $maxlength Max length of label
  506. * @param string $morecss More CSS
  507. * @param int $use_multilevel If > 0 create a multilevel select which use $htmlname example: $use_multilevel = 1 permit to have 2 select boxes.
  508. * @return void
  509. */
  510. public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0)
  511. {
  512. global $langs, $user;
  513. dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
  514. $ticketstat = new Ticket($this->db);
  515. $ticketstat->loadCacheCategoriesTickets();
  516. if ($use_multilevel <= 0) {
  517. print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
  518. if ($empty) {
  519. print '<option value="">&nbsp;</option>';
  520. }
  521. if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
  522. foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
  523. // Exclude some record
  524. if ($filtertype == 'public=1') {
  525. if (empty($arraycategories['public'])) {
  526. continue;
  527. }
  528. }
  529. // We discard empty line if showempty is on because an empty line has already been output.
  530. if ($empty && empty($arraycategories['code'])) {
  531. continue;
  532. }
  533. if ($format == 0) {
  534. print '<option value="'.$id.'"';
  535. }
  536. if ($format == 1) {
  537. print '<option value="'.$arraycategories['code'].'"';
  538. }
  539. if ($format == 2) {
  540. print '<option value="'.$arraycategories['code'].'"';
  541. }
  542. if ($format == 3) {
  543. print '<option value="'.$id.'"';
  544. }
  545. // Si selected est text, on compare avec code, sinon avec id
  546. if (preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
  547. print ' selected="selected"';
  548. } elseif ($selected == $id) {
  549. print ' selected="selected"';
  550. } elseif ($arraycategories['use_default'] == "1" && !$selected && !$empty) {
  551. print ' selected="selected"';
  552. }
  553. print '>';
  554. if ($format == 0) {
  555. $value = ($maxlength ? dol_trunc($arraycategories['label'], $maxlength) : $arraycategories['label']);
  556. }
  557. if ($format == 1) {
  558. $value = $arraycategories['code'];
  559. }
  560. if ($format == 2) {
  561. $value = ($maxlength ? dol_trunc($arraycategories['label'], $maxlength) : $arraycategories['label']);
  562. }
  563. if ($format == 3) {
  564. $value = $arraycategories['code'];
  565. }
  566. print $value ? $value : '&nbsp;';
  567. print '</option>';
  568. }
  569. }
  570. print '</select>';
  571. if ($user->admin && !$noadmininfo) {
  572. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  573. }
  574. print ajax_combobox('select'.$htmlname);
  575. } elseif ($htmlname!='') {
  576. $groupticket=GETPOST($htmlname, 'aZ09');
  577. $child_id=GETPOST($htmlname.'_child_id', 'aZ09')?GETPOST($htmlname.'_child_id', 'aZ09'):0;
  578. $arraycodenotparent[] = "";
  579. $arrayidused = array();
  580. $stringtoprint = '<span class="supportemailfield bold">'.$langs->trans("GroupOfTicket").'</span> ';
  581. $stringtoprint .= '<select id ="'.$htmlname.'" class="maxwidth500 minwidth400" child_id="0">';
  582. $stringtoprint .= '<option value="">&nbsp;</option>';
  583. $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ";
  584. $sql .= $this->db->ifsql("ctc.rowid NOT IN (SELECT ctcfather.rowid FROM llx_c_ticket_category as ctcfather JOIN llx_c_ticket_category as ctcjoin ON ctcfather.rowid = ctcjoin.fk_parent)", "'NOTPARENT'", "'PARENT'")." as isparent";
  585. $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc";
  586. $sql .= " WHERE ctc.active > 0";
  587. if ($filtertype == 'public=1') {
  588. $sql .= " AND ctc.public = 1";
  589. }
  590. $sql .= " AND ctc.fk_parent = 0";
  591. $sql .= $this->db->order('ctc.pos', 'ASC');
  592. $resql = $this->db->query($sql);
  593. if ($resql) {
  594. $num_rows_level0 = $this->db->num_rows($resql);
  595. $i = 0;
  596. while ($i < $num_rows_level0) {
  597. $obj = $this->db->fetch_object($resql);
  598. if ($obj) {
  599. $grouprowid = $obj->rowid;
  600. $groupvalue = $obj->code;
  601. $grouplabel = $obj->label;
  602. $isparent = $obj->isparent;
  603. $iselected = $groupticket == $obj->code ?'selected':'';
  604. $stringtoprint .= '<option '.$iselected.' class="'.$htmlname.dol_escape_htmltag($grouprowid).'" value="'.dol_escape_htmltag($groupvalue).'" data-html="'.dol_escape_htmltag($grouplabel).'">'.dol_escape_htmltag($grouplabel).'</option>';
  605. if ($isparent == 'NOTPARENT') {
  606. $arraycodenotparent[] = $groupvalue;
  607. }
  608. $arrayidused[]=$grouprowid;
  609. }
  610. $i++;
  611. }
  612. } else {
  613. dol_print_error($this->db);
  614. }
  615. if ($num_rows_level0 == 1) {
  616. return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
  617. } else {
  618. $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400">';
  619. $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400">';
  620. }
  621. $stringtoprint .= '</select>&nbsp;';
  622. $levelid = 1;
  623. while ($levelid <= $use_multilevel) {
  624. $tabscript = array();
  625. $stringtoprint .= '<select id ="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
  626. $stringtoprint .= '<option value="">&nbsp;</option>';
  627. $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctcjoin.code as codefather, ";
  628. $sql .= $this->db->ifsql("ctc.rowid NOT IN (SELECT ctcfather.rowid FROM llx_c_ticket_category as ctcfather JOIN llx_c_ticket_category as ctcjoin ON ctcfather.rowid = ctcjoin.fk_parent)", "'NOTPARENT'", "'PARENT'")." as isparent";
  629. $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category as ctc";
  630. $sql .= " JOIN ".MAIN_DB_PREFIX."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
  631. $sql .= " WHERE ctc.active = 1";
  632. if ($filtertype == 'public=1') {
  633. $sql .= " AND ctc.public = 1";
  634. }
  635. if (!empty($arrayidused)) {
  636. $sql .= " AND ctc.fk_parent IN ( ";
  637. foreach ($arrayidused as $idused) {
  638. $sql .= $idused.", ";
  639. }
  640. $sql = substr($sql, 0, -2);
  641. $sql .= ")";
  642. } else {
  643. }
  644. $sql .= $this->db->order('ctc.pos', 'ASC');
  645. $resql = $this->db->query($sql);
  646. if ($resql) {
  647. $num_rows = $this->db->num_rows($resql);
  648. $i = 0;
  649. $arrayidused=array();
  650. while ($i < $num_rows) {
  651. $obj = $this->db->fetch_object($resql);
  652. if ($obj) {
  653. $grouprowid = $obj->rowid;
  654. $groupvalue = $obj->code;
  655. $grouplabel = $obj->label;
  656. $isparent = $obj->isparent;
  657. $fatherid = $obj->fk_parent;
  658. $arrayidused[] = $grouprowid;
  659. $groupcodefather = $obj->codefather;
  660. if ($isparent == 'NOTPARENT') {
  661. $arraycodenotparent[] = $groupvalue;
  662. }
  663. $iselected = $groupticket == $obj->code ?'selected':'';
  664. $stringtoprint .= '<option '.$iselected.' class="'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'" value="'.dol_escape_htmltag($groupvalue).'" data-html="'.dol_escape_htmltag($grouplabel).'">'.dol_escape_htmltag($grouplabel).'</option>';
  665. if (empty($tabscript[$groupcodefather])) {
  666. $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid-1:'').'")[0].value == "'.dol_escape_js($groupcodefather).'"){
  667. $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").show()
  668. console.log("We show childs tickets of '.$groupcodefather.' group ticket")
  669. }else{
  670. $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").hide()
  671. console.log("We hide childs tickets of '.$groupcodefather.' group ticket")
  672. }';
  673. }
  674. }
  675. $i++;
  676. }
  677. } else {
  678. dol_print_error($this->db);
  679. }
  680. $stringtoprint .='</select>';
  681. $stringtoprint .='<script>';
  682. $stringtoprint .='arraynotparents = '.json_encode($arraycodenotparent).';';
  683. $stringtoprint .='if (arraynotparents.includes($("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid-1:'').'")[0].value)){
  684. console.log("'.$htmlname.'_child_'.$levelid.'")
  685. if($("#'.$htmlname.'_child_'.$levelid.'")[0].value == "" && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")>'.$child_id.')){
  686. $("#'.$htmlname.'_child_'.$levelid.'").hide();
  687. console.log("We hide '.$htmlname.'_child_'.$levelid.' input")
  688. }else if(($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")!=0) && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")<'.$child_id.')){
  689. $("#'.$htmlname.'_child_'.$levelid.'").attr("disabled",true);
  690. console.log("We disable '.$htmlname.'_child_'.$levelid.' input");
  691. }else{
  692. $("#'.$htmlname.'_child_'.$levelid.'").attr("disabled",true);
  693. $("#ticketcategory_select_child_id")[0].value = $("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")
  694. $("#ticketcategory_select")[0].value = $("#'.$htmlname.'_child_'.$levelid.'")[0].value;
  695. console.log("We disable '.$htmlname.'_child_'.$levelid.' input and reload hidden input");
  696. }
  697. if(arraynotparents.includes("'.$groupticket.'") && '.$child_id.' == 0){
  698. $("#ticketcategory_select_child_id")[0].value = $("#'.$htmlname.'").attr("child_id")
  699. $("#ticketcategory_select")[0].value = $("#'.$htmlname.'")[0].value;
  700. console.log("We choose '.$htmlname.' input and reload hidden input");
  701. }
  702. }
  703. $("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid-1:'').'").change(function() {
  704. child_id = $("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid:'').'").attr("child_id");
  705. /* Change of value to select this value*/
  706. if (arraynotparents.includes(this.value) || $(this).attr("child_id") == '.$use_multilevel.') {
  707. $("#ticketcategory_select")[0].value = this.value;
  708. $("#ticketcategory_select_child_id")[0].value = $(this).attr("child_id");
  709. console.log("We choose to select "+ $("#ticketcategory_select")[0].value );
  710. }else{
  711. $("#ticketcategory_select")[0].value = "";
  712. $("#ticketcategory_select_child_id")[0].value = "";
  713. }
  714. console.log("We select a new value into combo child_id="+child_id);
  715. /* Hide all selected box that are child of the one modified */
  716. $(".groupticketchild").each(function(){
  717. if ($(this).attr("child_id") > child_id) {
  718. console.log("hide child_id="+$(this).attr("child_id"));
  719. $(this).val("");
  720. $(this).hide();
  721. }
  722. })
  723. /* Now we enable the next combo */
  724. $("#'.$htmlname.'_child_'.$levelid.'").val("");
  725. if (!arraynotparents.includes(this.value)) {
  726. $("#'.$htmlname.'_child_'.$levelid.'").show()
  727. } else {
  728. $("#'.$htmlname.'_child_'.$levelid.'").hide()
  729. }
  730. ';
  731. $levelid++;
  732. foreach ($tabscript as $script) {
  733. $stringtoprint .= $script;
  734. };
  735. $stringtoprint .='})';
  736. $stringtoprint .='</script>';
  737. }
  738. $stringtoprint .='<script>';
  739. $stringtoprint .='$("#'.$htmlname.'_child_'.$use_multilevel.'").change(function() {
  740. $("#ticketcategory_select")[0].value = this.value;
  741. $("#ticketcategory_select_child_id")[0].value = $(this).attr("child_id");
  742. console.log($("#ticketcategory_select")[0].value);
  743. })';
  744. $stringtoprint .='</script>';
  745. $stringtoprint .= ajax_combobox($htmlname);
  746. return $stringtoprint;
  747. }
  748. }
  749. /**
  750. * Return html list of ticket severitys
  751. *
  752. * @param string $selected Id severity pre-selectionnée
  753. * @param string $htmlname Nom de la zone select
  754. * @param string $filtertype To filter on field type in llx_c_ticket_severity (array('code'=>xx,'label'=>zz))
  755. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  756. * @param int $empty 1=peut etre vide, 0 sinon
  757. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  758. * @param int $maxlength Max length of label
  759. * @param string $morecss More CSS
  760. * @return void
  761. */
  762. public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
  763. {
  764. global $langs, $user;
  765. $ticketstat = new Ticket($this->db);
  766. dol_syslog(get_class($this)."::selectSeveritiesTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
  767. $filterarray = array();
  768. if ($filtertype != '' && $filtertype != '-1') {
  769. $filterarray = explode(',', $filtertype);
  770. }
  771. $ticketstat->loadCacheSeveritiesTickets();
  772. print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
  773. if ($empty) {
  774. print '<option value="">&nbsp;</option>';
  775. }
  776. if (is_array($ticketstat->cache_severity_tickets) && count($ticketstat->cache_severity_tickets)) {
  777. foreach ($ticketstat->cache_severity_tickets as $id => $arrayseverities) {
  778. // On passe si on a demande de filtrer sur des modes de paiments particuliers
  779. if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
  780. continue;
  781. }
  782. // We discard empty line if showempty is on because an empty line has already been output.
  783. if ($empty && empty($arrayseverities['code'])) {
  784. continue;
  785. }
  786. if ($format == 0) {
  787. print '<option value="'.$id.'"';
  788. }
  789. if ($format == 1) {
  790. print '<option value="'.$arrayseverities['code'].'"';
  791. }
  792. if ($format == 2) {
  793. print '<option value="'.$arrayseverities['code'].'"';
  794. }
  795. if ($format == 3) {
  796. print '<option value="'.$id.'"';
  797. }
  798. // Si selected est text, on compare avec code, sinon avec id
  799. if (preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
  800. print ' selected="selected"';
  801. } elseif ($selected == $id) {
  802. print ' selected="selected"';
  803. } elseif ($arrayseverities['use_default'] == "1" && !$selected && !$empty) {
  804. print ' selected="selected"';
  805. }
  806. print '>';
  807. if ($format == 0) {
  808. $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
  809. }
  810. if ($format == 1) {
  811. $value = $arrayseverities['code'];
  812. }
  813. if ($format == 2) {
  814. $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
  815. }
  816. if ($format == 3) {
  817. $value = $arrayseverities['code'];
  818. }
  819. print $value ? $value : '&nbsp;';
  820. print '</option>';
  821. }
  822. }
  823. print '</select>';
  824. if ($user->admin && !$noadmininfo) {
  825. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  826. }
  827. print ajax_combobox('select'.$htmlname);
  828. }
  829. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  830. /**
  831. * Clear list of attached files in send mail form (also stored in session)
  832. *
  833. * @return void
  834. */
  835. public function clear_attached_files()
  836. {
  837. // phpcs:enable
  838. global $conf, $user;
  839. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  840. // Set tmp user directory
  841. $vardir = $conf->user->dir_output."/".$user->id;
  842. $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
  843. if (is_dir($upload_dir)) {
  844. dol_delete_dir_recursive($upload_dir);
  845. }
  846. $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
  847. unset($_SESSION["listofpaths".$keytoavoidconflict]);
  848. unset($_SESSION["listofnames".$keytoavoidconflict]);
  849. unset($_SESSION["listofmimes".$keytoavoidconflict]);
  850. }
  851. /**
  852. * Show the form to add message on ticket
  853. *
  854. * @param string $width Width of form
  855. * @return void
  856. */
  857. public function showMessageForm($width = '40%')
  858. {
  859. global $conf, $langs, $user, $hookmanager, $form, $mysoc;
  860. $formmail = new FormMail($this->db);
  861. $addfileaction = 'addfile';
  862. if (!is_object($form)) {
  863. $form = new Form($this->db);
  864. }
  865. // Load translation files required by the page
  866. $langs->loadLangs(array('other', 'mails'));
  867. // Clear temp files. Must be done at beginning, before call of triggers
  868. if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
  869. $this->clear_attached_files();
  870. }
  871. // Define output language
  872. $outputlangs = $langs;
  873. $newlang = '';
  874. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
  875. $newlang = $this->param['langsmodels'];
  876. }
  877. if (!empty($newlang)) {
  878. $outputlangs = new Translate("", $conf);
  879. $outputlangs->setDefaultLang($newlang);
  880. $outputlangs->load('other');
  881. }
  882. // Get message template for $this->param["models"] into c_email_templates
  883. $arraydefaultmessage = -1;
  884. if ($this->param['models'] != 'none') {
  885. $model_id = 0;
  886. if (array_key_exists('models_id', $this->param)) {
  887. $model_id = $this->param["models_id"];
  888. }
  889. $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
  890. }
  891. // Define list of attached files
  892. $listofpaths = array();
  893. $listofnames = array();
  894. $listofmimes = array();
  895. $keytoavoidconflict = empty($this->trackid) ? '' : '-'.$this->trackid; // this->trackid must be defined
  896. if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
  897. if (!empty($arraydefaultmessage->joinfiles) && is_array($this->param['fileinit'])) {
  898. foreach ($this->param['fileinit'] as $file) {
  899. $this->add_attached_files($file, basename($file), dol_mimetype($file));
  900. }
  901. }
  902. }
  903. if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
  904. $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
  905. }
  906. if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
  907. $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
  908. }
  909. if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
  910. $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
  911. }
  912. // Define output language
  913. $outputlangs = $langs;
  914. $newlang = '';
  915. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
  916. $newlang = $this->param['langsmodels'];
  917. }
  918. if (!empty($newlang)) {
  919. $outputlangs = new Translate("", $conf);
  920. $outputlangs->setDefaultLang($newlang);
  921. $outputlangs->load('other');
  922. }
  923. print "\n<!-- Begin message_form TICKET -->\n";
  924. $send_email = GETPOST('send_email', 'int') ? GETPOST('send_email', 'int') : 0;
  925. // Example 1 : Adding jquery code
  926. print '<script type="text/javascript" language="javascript">
  927. jQuery(document).ready(function() {
  928. send_email=' . $send_email.';
  929. if (send_email) {
  930. jQuery(".email_line").show();
  931. } else {
  932. jQuery(".email_line").hide();
  933. }
  934. jQuery("#send_msg_email").click(function() {
  935. if(jQuery(this).is(":checked")) {
  936. jQuery(".email_line").show();
  937. }
  938. else {
  939. jQuery(".email_line").hide();
  940. }
  941. });';
  942. print '});
  943. </script>';
  944. print '<form method="post" name="ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
  945. print '<input type="hidden" name="token" value="'.newToken().'">';
  946. print '<input type="hidden" name="action" value="'.$this->action.'">';
  947. print '<input type="hidden" name="actionbis" value="add_message">';
  948. foreach ($this->param as $key => $value) {
  949. print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
  950. }
  951. // Get message template
  952. $model_id = 0;
  953. if (array_key_exists('models_id', $this->param)) {
  954. $model_id = $this->param["models_id"];
  955. $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
  956. }
  957. $result = $formmail->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
  958. if ($result < 0) {
  959. setEventMessages($this->error, $this->errors, 'errors');
  960. }
  961. $modelmail_array = array();
  962. foreach ($formmail->lines_model as $line) {
  963. $modelmail_array[$line->id] = $line->label;
  964. }
  965. print '<table class="border" width="'.$width.'">';
  966. // External users can't send message email
  967. if ($user->rights->ticket->write && !$user->socid) {
  968. print '<tr><td></td><td>';
  969. $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : '');
  970. print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
  971. print '<label for="send_msg_email">'.$langs->trans('SendMessageByEmail').'</label>';
  972. print '</td></tr>';
  973. // Zone to select its email template
  974. if (count($modelmail_array) > 0) {
  975. print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
  976. print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1);
  977. if ($user->admin) {
  978. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  979. }
  980. print ' &nbsp; ';
  981. print '<input class="button" type="submit" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
  982. print '</div></td>';
  983. }
  984. // Private message (not visible by customer/external user)
  985. if (!$user->socid) {
  986. print '<tr><td></td><td>';
  987. $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : '');
  988. print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
  989. print '<label for="private_message">'.$langs->trans('MarkMessageAsPrivate').'</label>';
  990. print ' '.$form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
  991. print '</td></tr>';
  992. }
  993. // Subject
  994. print '<tr class="email_line"><td class="titlefieldcreate">'.$langs->trans('Subject').'</td>';
  995. print '<td><input type="text" class="text minwidth500" name="subject" value="['.$conf->global->MAIN_INFO_SOCIETE_NOM.' - '.$langs->trans("Ticket").' '.$this->ref.'] '.$langs->trans('TicketNewMessage').'" />';
  996. print '</td></tr>';
  997. // Destinataires
  998. print '<tr class="email_line"><td>'.$langs->trans('MailRecipients').'</td><td>';
  999. $ticketstat = new Ticket($this->db);
  1000. $res = $ticketstat->fetch('', '', $this->track_id);
  1001. if ($res) {
  1002. // Retrieve email of all contacts (internal and external)
  1003. $contacts = $ticketstat->getInfosTicketInternalContact();
  1004. $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact());
  1005. // Build array to display recipient list
  1006. if (is_array($contacts) && count($contacts) > 0) {
  1007. foreach ($contacts as $key => $info_sendto) {
  1008. if ($info_sendto['email'] != '') {
  1009. $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">").' <small class="opacitymedium">('.dol_escape_htmltag($info_sendto['libelle']).")</small>";
  1010. }
  1011. }
  1012. }
  1013. if ($ticketstat->origin_email && !in_array($this->dao->origin_email, $sendto)) {
  1014. $sendto[] = dol_escape_htmltag($ticketstat->origin_email).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
  1015. }
  1016. if ($ticketstat->fk_soc > 0) {
  1017. $ticketstat->socid = $ticketstat->fk_soc;
  1018. $ticketstat->fetch_thirdparty();
  1019. if (is_array($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
  1020. $sendto[] = $ticketstat->thirdparty->email.' <small class="opacitymedium">('.$langs->trans('Customer').')</small>';
  1021. }
  1022. }
  1023. if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) {
  1024. $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO.' <small class="opacitymedium">(generic email)</small>';
  1025. }
  1026. // Print recipient list
  1027. if (is_array($sendto) && count($sendto) > 0) {
  1028. print implode(', ', $sendto);
  1029. } else {
  1030. print '<div class="warning">'.$langs->trans('WarningNoEMailsAdded').' '.$langs->trans('TicketGoIntoContactTab').'</div>';
  1031. }
  1032. }
  1033. print '</td></tr>';
  1034. }
  1035. $uselocalbrowser = false;
  1036. // Intro
  1037. // External users can't send message email
  1038. if ($user->rights->ticket->write && !$user->socid) {
  1039. $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
  1040. print '<tr class="email_line"><td><label for="mail_intro">';
  1041. print $form->textwithpicto($langs->trans("TicketMessageMailIntro"), $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
  1042. print '</label>';
  1043. print '</td><td>';
  1044. include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  1045. $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70);
  1046. $doleditor->Create();
  1047. print '</td></tr>';
  1048. }
  1049. // MESSAGE
  1050. $defaultmessage = "";
  1051. if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
  1052. $defaultmessage = $arraydefaultmessage->content;
  1053. }
  1054. $defaultmessage = str_replace('\n', "\n", $defaultmessage);
  1055. // Deal with format differences between message and signature (text / HTML)
  1056. if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
  1057. $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
  1058. } elseif (!dol_textishtml($defaultmessage) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
  1059. $defaultmessage = dol_nl2br($defaultmessage);
  1060. }
  1061. if (GETPOSTISSET("message") && !$_POST['modelselected']) {
  1062. $defaultmessage = GETPOST('message', 'restricthtml');
  1063. } else {
  1064. $defaultmessage = make_substitutions($defaultmessage, $this->substit);
  1065. // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
  1066. $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
  1067. $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
  1068. }
  1069. print '<tr><td class="tdtop"><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span>';
  1070. if ($user->rights->ticket->write && !$user->socid) {
  1071. print $form->textwithpicto('', $langs->trans("TicketMessageHelp"), 1, 'help');
  1072. }
  1073. print '</label></td><td>';
  1074. //$toolbarname = 'dolibarr_details';
  1075. $toolbarname = 'dolibarr_notes';
  1076. include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  1077. $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_5, 70);
  1078. $doleditor->Create();
  1079. print '</td></tr>';
  1080. // Signature
  1081. // External users can't send message email
  1082. if ($user->rights->ticket->write && !$user->socid) {
  1083. $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
  1084. print '<tr class="email_line"><td><label for="mail_intro">'.$langs->trans("TicketMessageMailSignature").'</label>';
  1085. print $form->textwithpicto('', $langs->trans("TicketMessageMailSignatureHelp"), 1, 'help');
  1086. print '</td><td>';
  1087. include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
  1088. $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 150, 'dolibarr_details', '', false, $uselocalbrowser, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70);
  1089. $doleditor->Create();
  1090. print '</td></tr>';
  1091. }
  1092. // Attached files
  1093. if (!empty($this->withfile)) {
  1094. $out = '<tr>';
  1095. $out .= '<td width="180">'.$langs->trans("MailFile").'</td>';
  1096. $out .= '<td>';
  1097. // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
  1098. $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
  1099. $out .= '<script type="text/javascript" language="javascript">';
  1100. $out .= 'jQuery(document).ready(function () {';
  1101. $out .= ' jQuery(".removedfile").click(function() {';
  1102. $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
  1103. $out .= ' });';
  1104. $out .= '})';
  1105. $out .= '</script>'."\n";
  1106. if (count($listofpaths)) {
  1107. foreach ($listofpaths as $key => $val) {
  1108. $out .= '<div id="attachfile_'.$key.'">';
  1109. $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
  1110. if (!$this->withfilereadonly) {
  1111. $out .= ' <input type="image" style="border: 0px;" src="'.DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/delete.png" value="'.($key + 1).'" class="removedfile reposition" id="removedfile_'.$key.'" name="removedfile_'.$key.'" />';
  1112. }
  1113. $out .= '<br></div>';
  1114. }
  1115. } else {
  1116. $out .= $langs->trans("NoAttachedFiles").'<br>';
  1117. }
  1118. if ($this->withfile == 2) { // Can add other files
  1119. $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
  1120. $out .= ' ';
  1121. $out .= '<input type="submit" class="button smallpaddingimp reposition" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
  1122. }
  1123. $out .= "</td></tr>\n";
  1124. print $out;
  1125. }
  1126. print '</table>';
  1127. print '<center><br>';
  1128. print '<input class="button" type="submit" name="btn_add_message" value="'.$langs->trans("AddMessage").'" />';
  1129. if ($this->withcancel) {
  1130. print " &nbsp; &nbsp; ";
  1131. print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
  1132. }
  1133. print "</center>\n";
  1134. print '<input type="hidden" name="page_y">'."\n";
  1135. print "</form>\n";
  1136. print "<!-- End form TICKET -->\n";
  1137. }
  1138. }