html.formticket.class.php 64 KB

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