dolibarr  19.0.0-dev
html.formticket.class.php
Go to the documentation of this file.
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-2022 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 
28 require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
29 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
30 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
31 
32 if (!class_exists('FormCompany')) {
33  include DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
34 }
35 
45 {
49  public $db;
50 
54  public $track_id;
55 
59  public $trackid;
60 
64  public $fk_user_create;
65 
66  public $message;
67  public $topic_title;
68 
69  public $action;
70 
71  public $withtopic;
72  public $withemail;
73 
77  public $withsubstit;
78 
79  public $withfile;
80  public $withfilereadonly;
81 
82  public $backtopage;
83 
84  public $ispublic; // to show information or not into public form
85 
86  public $withtitletopic;
87  public $withtopicreadonly;
88  public $withreadid;
89 
90  public $withcompany; // to show company drop-down list
91  public $withfromsocid;
92  public $withfromcontactid;
93  public $withnotifytiersatcreate;
94  public $withusercreate; // to show name of creating user in form
95  public $withcreatereadonly;
96 
100  public $withextrafields;
101 
102  public $withref; // to show ref field
103  public $withcancel;
104 
105  public $type_code;
106  public $category_code;
107  public $severity_code;
108 
109 
114  public $substit = array();
115  public $param = array();
116 
120  public $error;
121  public $errors = array();
122 
123 
129  public function __construct($db)
130  {
131  global $conf;
132 
133  $this->db = $db;
134 
135  $this->action = 'add';
136 
137  $this->withcompany = isModEnabled("societe");
138  $this->withfromsocid = 0;
139  $this->withfromcontactid = 0;
140  $this->withreadid=0;
141  //$this->withtitletopic='';
142  $this->withnotifytiersatcreate = 0;
143  $this->withusercreate = 1;
144  $this->withcreatereadonly = 1;
145  $this->withemail = 0;
146  $this->withref = 0;
147  $this->withextrafields = 0; // to show extrafields or not
148  //$this->withtopicreadonly=0;
149  }
150 
161  public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0, Contact $with_contact = null, $action = '')
162  {
163  global $conf, $langs, $user, $hookmanager;
164 
165  // Load translation files required by the page
166  $langs->loadLangs(array('other', 'mails', 'ticket'));
167 
168  $form = new Form($this->db);
169  $formcompany = new FormCompany($this->db);
170  $ticketstatic = new Ticket($this->db);
171 
172  $soc = new Societe($this->db);
173  if (!empty($this->withfromsocid) && $this->withfromsocid > 0) {
174  $soc->fetch($this->withfromsocid);
175  }
176 
177  $ticketstat = new Ticket($this->db);
178 
179  $extrafields = new ExtraFields($this->db);
180  $extrafields->fetch_name_optionals_label($ticketstat->table_element);
181 
182  print "\n<!-- Begin form TICKET -->\n";
183 
184  if ($withdolfichehead) {
185  print dol_get_fiche_head(null, 'card', '', 0, '');
186  }
187 
188  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"] : $_SERVER['PHP_SELF']).'">';
189  print '<input type="hidden" name="token" value="'.newToken().'">';
190  print '<input type="hidden" name="action" value="'.$this->action.'">';
191  print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
192  foreach ($this->param as $key => $value) {
193  print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
194  }
195  print '<input type="hidden" name="fk_user_create" value="'.$this->fk_user_create.'">';
196 
197  print '<table class="border centpercent">';
198 
199  if ($this->withref) {
200  // Ref
201  $defaultref = $ticketstat->getDefaultRef();
202  print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
203  print '<input type="text" name="ref" value="'.dol_escape_htmltag(GETPOST("ref", 'alpha') ? GETPOST("ref", 'alpha') : $defaultref).'">';
204  print '</td></tr>';
205  }
206 
207  // TITLE
208  $email = GETPOSTISSET('email') ? GETPOST('email', 'alphanohtml') : '';
209  if ($this->withemail) {
210  print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("Email").'</span></label></td><td>';
211  print '<input class="text minwidth200" id="email" name="email" value="'.$email.'" autofocus>';
212  print '</td></tr>';
213 
214  if ($with_contact) {
215  // contact search and result
216  $html_contact_search = '';
217  $html_contact_search .= '<tr id="contact_search_line">';
218  $html_contact_search .= '<td class="titlefield">';
219  $html_contact_search .= '<label for="contact"><span class="fieldrequired">' . $langs->trans('Contact') . '</span></label>';
220  $html_contact_search .= '<input type="hidden" id="contact_id" name="contact_id" value="" />';
221  $html_contact_search .= '</td>';
222  $html_contact_search .= '<td id="contact_search_result"></td>';
223  $html_contact_search .= '</tr>';
224  print $html_contact_search;
225  // contact lastname
226  $html_contact_lastname = '';
227  $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>';
228  $html_contact_lastname .= '<input type="text" id="contact_lastname" name="contact_lastname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_lastname') ? GETPOST('contact_lastname', 'alphanohtml') : '') . '" />';
229  $html_contact_lastname .= '</td></tr>';
230  print $html_contact_lastname;
231  // contact firstname
232  $html_contact_firstname = '';
233  $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>';
234  $html_contact_firstname .= '<input type="text" id="contact_firstname" name="contact_firstname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_firstname') ? GETPOST('contact_firstname', 'alphanohtml') : '') . '" />';
235  $html_contact_firstname .= '</td></tr>';
236  print $html_contact_firstname;
237  // company name
238  $html_company_name = '';
239  $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>';
240  $html_company_name .= '<input type="text" id="company_name" name="company_name" value="' . dol_escape_htmltag(GETPOSTISSET('company_name') ? GETPOST('company_name', 'alphanohtml') : '') . '" />';
241  $html_company_name .= '</td></tr>';
242  print $html_company_name;
243  // contact phone
244  $html_contact_phone = '';
245  $html_contact_phone .= '<tr id="contact_phone_line" class="contact_field"><td><label for="contact_phone"><span>' . $langs->trans('Phone') . '</span></label></td><td>';
246  $html_contact_phone .= '<input type="text" id="contact_phone" name="contact_phone" value="' . dol_escape_htmltag(GETPOSTISSET('contact_phone') ? GETPOST('contact_phone', 'alphanohtml') : '') . '" />';
247  $html_contact_phone .= '</td></tr>';
248  print $html_contact_phone;
249 
250  // search contact form email
251  $langs->load('errors');
252  print '<script nonce="'.getNonce().'" type="text/javascript">
253  jQuery(document).ready(function() {
254  var contact = jQuery.parseJSON("'.dol_escape_js(json_encode($with_contact), 2).'");
255  jQuery("#contact_search_line").hide();
256  if (contact) {
257  if (contact.id > 0) {
258  jQuery("#contact_search_line").show();
259  jQuery("#contact_id").val(contact.id);
260  jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
261  jQuery(".contact_field").hide();
262  } else {
263  jQuery(".contact_field").show();
264  }
265  }
266 
267  jQuery("#email").change(function() {
268  jQuery("#contact_search_line").show();
269  jQuery("#contact_search_result").html("'.dol_escape_js($langs->trans('Select2SearchInProgress')).'");
270  jQuery("#contact_id").val("");
271  jQuery("#contact_lastname").val("");
272  jQuery("#contact_firstname").val("");
273  jQuery("#company_name").val("");
274  jQuery("#contact_phone").val("");
275 
276  jQuery.getJSON(
277  "'.dol_escape_js(dol_buildpath('/public/ticket/ajax/ajax.php', 1)).'",
278  {
279  action: "getContacts",
280  email: jQuery("#email").val()
281  },
282  function(response) {
283  if (response.error) {
284  jQuery("#contact_search_result").html("<span class=\"error\">"+response.error+"</span>");
285  } else {
286  var contact_list = response.contacts;
287  if (contact_list.length == 1) {
288  var contact = contact_list[0];
289  jQuery("#contact_id").val(contact.id);
290  jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
291  jQuery(".contact_field").hide();
292  } else if (contact_list.length <= 0) {
293  jQuery("#contact_search_line").hide();
294  jQuery(".contact_field").show();
295  }
296  }
297  }
298  ).fail(function(jqxhr, textStatus, error) {
299  var error_msg = "'.dol_escape_js($langs->trans('ErrorAjaxRequestFailed')).'"+" ["+textStatus+"] : "+error;
300  jQuery("#contact_search_result").html("<span class=\"error\">"+error_msg+"</span>");
301  });
302  });
303  });
304  </script>';
305  }
306  }
307 
308  // If ticket created from another object
309  $subelement = '';
310  if (isset($this->param['origin']) && $this->param['originid'] > 0) {
311  // Parse element/subelement (ex: project_task)
312  $element = $subelement = $this->param['origin'];
313  $regs = array();
314  if (preg_match('/^([^_]+)_([^_]+)/i', $this->param['origin'], $regs)) {
315  $element = $regs[1];
316  $subelement = $regs[2];
317  }
318 
319  dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
320  $classname = ucfirst($subelement);
321  $objectsrc = new $classname($this->db);
322  $objectsrc->fetch(GETPOST('originid', 'int'));
323 
324  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
325  $objectsrc->fetch_lines();
326  }
327 
328  $objectsrc->fetch_thirdparty();
329  $newclassname = $classname;
330  print '<tr><td>'.$langs->trans($newclassname).'</td><td colspan="2"><input name="'.$subelement.'id" value="'.GETPOST('originid').'" type="hidden" />'.$objectsrc->getNomUrl(1).'</td></tr>';
331  }
332 
333  // Type of Ticket
334  print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">'.$langs->trans("TicketTypeRequest").'</span></label></td><td>';
335  $this->selectTypesTickets((GETPOST('type_code', 'alpha') ? GETPOST('type_code', 'alpha') : $this->type_code), 'type_code', '', 2, 1, 0, 0, 'minwidth200');
336  print '</td></tr>';
337 
338  // Group => Category
339  print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">'.$langs->trans("TicketCategory").'</span></label></td><td>';
340  $filter = '';
341  if ($public) {
342  $filter = 'public=1';
343  }
344  $selected = (GETPOST('category_code') ? GETPOST('category_code') : $this->category_code);
345  $this->selectGroupTickets($selected, 'category_code', $filter, 2, 1, 0, 0, 'minwidth200');
346  print '</td></tr>';
347 
348  // Severity => Priority
349  print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">'.$langs->trans("TicketSeverity").'</span></label></td><td>';
350  $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', 2, 1);
351  print '</td></tr>';
352 
353  if (!empty($conf->knowledgemanagement->enabled)) {
354  // KM Articles
355  print '<tr id="KWwithajax" class="hidden"><td></td></tr>';
356  print '<!-- Script to manage change of ticket group -->
357  <script nonce="'.getNonce().'">
358  jQuery(document).ready(function() {
359  function groupticketchange() {
360  console.log("We called groupticketchange, so we try to load list KM linked to event");
361  $("#KWwithajax").html("");
362  idgroupticket = $("#selectcategory_code").val();
363 
364  console.log("We have selected id="+idgroupticket);
365 
366  if (idgroupticket != "") {
367  $.ajax({ url: \''.DOL_URL_ROOT.'/core/ajax/fetchKnowledgeRecord.php\',
368  data: { action: \'getKnowledgeRecord\', idticketgroup: idgroupticket, token: \''.newToken().'\', lang:\''.$langs->defaultlang.'\', public:'.($public).' },
369  type: \'GET\',
370  success: function(response) {
371  var urllist = \'\';
372  console.log("We received response "+response);
373  if (typeof response == "object") {
374  console.log("response is already type object, no need to parse it");
375  } else {
376  console.log("response is type "+(typeof response));
377  response = JSON.parse(response);
378  }
379  for (key in response) {
380  answer = response[key].answer;
381  urllist += \'<li><a href="#" title="\'+response[key].title+\'" class="button_KMpopup" data-html="\'+answer+\'">\' +response[key].title+\'</a></li>\';
382  }
383  if (urllist != "") {
384  $("#KWwithajax").html(\'<td>'.$langs->trans("KMFoundForTicketGroup").'</td><td><ul>\'+urllist+\'</ul></td>\');
385  $("#KWwithajax").show();
386  $(".button_KMpopup").on("click",function(){
387  console.log("Open popup with jQuery(...).dialog() with KM article")
388  var $dialog = $("<div></div>").html($(this).attr("data-html"))
389  .dialog({
390  autoOpen: false,
391  modal: true,
392  height: (window.innerHeight - 150),
393  width: "80%",
394  title: $(this).attr("title"),
395  });
396  $dialog.dialog("open");
397  console.log($dialog);
398  })
399  }
400  },
401  error : function(output) {
402  console.error("Error on Fetch of KM articles");
403  },
404  });
405  }
406  };
407  $("#selectcategory_code").on("change",function() { groupticketchange(); });
408  if ($("#selectcategory_code").val() != "") {
409  groupticketchange();
410  }
411  });
412  </script>'."\n";
413  }
414 
415  // Subject
416  if ($this->withtitletopic) {
417  print '<tr><td><label for="subject"><span class="fieldrequired">'.$langs->trans("Subject").'</span></label></td><td>';
418  // Answer to a ticket : display of the thread title in readonly
419  if ($this->withtopicreadonly) {
420  print $langs->trans('SubjectAnswerToTicket').' '.$this->topic_title;
421  } else {
422  if (isset($this->withreadid) && $this->withreadid > 0) {
423  $subject = $langs->trans('SubjectAnswerToTicket').' '.$this->withreadid.' : '.$this->topic_title;
424  } else {
425  $subject = GETPOST('subject', 'alpha');
426  }
427  print '<input class="text minwidth500" id="subject" name="subject" value="'.$subject.'"'.(empty($this->withemail)?' autofocus':'').' />';
428  }
429  print '</td></tr>';
430  }
431 
432  // MESSAGE
433  $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : '';
434  print '<tr><td><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span></label></td><td>';
435 
436  // If public form, display more information
437  $toolbarname = 'dolibarr_notes';
438  if ($this->ispublic) {
439  $toolbarname = 'dolibarr_details';
440  print '<div class="warning hideonsmartphone">'.(getDolGlobalString("TICKET_PUBLIC_TEXT_HELP_MESSAGE", $langs->trans('TicketPublicPleaseBeAccuratelyDescribe'))).'</div>';
441  }
442  include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
443  $uselocalbrowser = true;
444  $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_8, '90%');
445  $doleditor->Create();
446  print '</td></tr>';
447 
448  if ($public && !empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA_TICKET)) {
449  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
450  print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("SecurityCode").'</span></label></td><td>';
451  print '<span class="span-icon-security inline-block">';
452  print '<input id="securitycode" placeholder="'.$langs->trans("SecurityCode").'" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" />';
453  print '</span>';
454  print '<span class="nowrap inline-block">';
455  print '<img class="inline-block valignmiddle" src="'.DOL_URL_ROOT.'/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />';
456  print '<a class="inline-block valignmiddle" href="" tabindex="4" data-role="button">'.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'</a>';
457  print '</span>';
458  print '</td></tr>';
459  }
460 
461  // Categories
462  if (isModEnabled('categorie')) {
463  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
464  $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 1);
465 
466  if (count($cate_arbo)) {
467  // Categories
468  print '<tr><td class="wordbreak">'.$langs->trans("Categories").'</td><td>';
469  print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
470  print "</td></tr>";
471  }
472  }
473 
474  // Attached files
475  if (!empty($this->withfile)) {
476  // Define list of attached files
477  $listofpaths = array();
478  $listofnames = array();
479  $listofmimes = array();
480  if (!empty($_SESSION["listofpaths"])) {
481  $listofpaths = explode(';', $_SESSION["listofpaths"]);
482  }
483 
484  if (!empty($_SESSION["listofnames"])) {
485  $listofnames = explode(';', $_SESSION["listofnames"]);
486  }
487 
488  if (!empty($_SESSION["listofmimes"])) {
489  $listofmimes = explode(';', $_SESSION["listofmimes"]);
490  }
491 
492  $out = '<tr>';
493  $out .= '<td>'.$langs->trans("MailFile").'</td>';
494  $out .= '<td>';
495  // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
496  $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
497  $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
498  $out .= 'jQuery(document).ready(function () {';
499  $out .= ' jQuery(".removedfile").click(function() {';
500  $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
501  $out .= ' });';
502  $out .= '})';
503  $out .= '</script>'."\n";
504  if (count($listofpaths)) {
505  foreach ($listofpaths as $key => $val) {
506  $out .= '<div id="attachfile_'.$key.'">';
507  $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
508  if (!$this->withfilereadonly) {
509  $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.'" />';
510  }
511  $out .= '<br></div>';
512  }
513  } else {
514  $out .= $langs->trans("NoAttachedFiles").'<br>';
515  }
516  if ($this->withfile == 2) { // Can add other files
517  $maxfilesizearray = getMaxFileSizeArray();
518  $maxmin = $maxfilesizearray['maxmin'];
519  if ($maxmin > 0) {
520  $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
521  }
522  $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
523  $out .= ' ';
524  $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="'.$langs->trans("MailingAddFile").'" />';
525  }
526  $out .= "</td></tr>\n";
527 
528  print $out;
529  }
530 
531  // User of creation
532  if ($this->withusercreate > 0 && $this->fk_user_create) {
533  print '<tr><td class="titlefield">'.$langs->trans("CreatedBy").'</td><td>';
534  $langs->load("users");
535  $fuser = new User($this->db);
536 
537  if ($this->withcreatereadonly) {
538  if ($res = $fuser->fetch($this->fk_user_create)) {
539  print $fuser->getNomUrl(1);
540  }
541  }
542  print ' &nbsp; ';
543  print "</td></tr>\n";
544  }
545 
546  // Customer or supplier
547  if ($this->withcompany) {
548  // altairis: force company and contact id for external user
549  if (empty($user->socid)) {
550  // Company
551  print '<tr><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
552  $events = array();
553  $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
554  print img_picto('', 'company', 'class="paddingright"');
555  print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, '', $events, 0, 'minwidth200');
556  print '</td></tr>';
557  if (!empty($conf->use_javascript_ajax) && !empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT)) {
558  $htmlname = 'socid';
559  print '<script nonce="'.getNonce().'" type="text/javascript">
560  $(document).ready(function () {
561  jQuery("#'.$htmlname.'").change(function () {
562  var obj = '.json_encode($events).';
563  $.each(obj, function(key,values) {
564  if (values.method.length) {
565  runJsCodeForEvent'.$htmlname.'(values);
566  }
567  });
568  });
569 
570  function runJsCodeForEvent'.$htmlname.'(obj) {
571  console.log("Run runJsCodeForEvent'.$htmlname.'");
572  var id = $("#'.$htmlname.'").val();
573  var method = obj.method;
574  var url = obj.url;
575  var htmlname = obj.htmlname;
576  var showempty = obj.showempty;
577  $.getJSON(url,
578  {
579  action: method,
580  id: id,
581  htmlname: htmlname,
582  showempty: showempty
583  },
584  function(response) {
585  $.each(obj.params, function(key,action) {
586  if (key.length) {
587  var num = response.num;
588  if (num > 0) {
589  $("#" + key).removeAttr(action);
590  } else {
591  $("#" + key).attr(action, action);
592  }
593  }
594  });
595  $("select#" + htmlname).html(response.value);
596  if (response.num) {
597  var selecthtml_str = response.value;
598  var selecthtml_dom=$.parseHTML(selecthtml_str);
599  if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
600  $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
601  }
602  } else {
603  $("#inputautocomplete"+htmlname).val("");
604  }
605  $("select#" + htmlname).change(); /* Trigger event change */
606  }
607  );
608  }
609  });
610  </script>';
611  }
612 
613  // Contact and type
614  print '<tr><td>'.$langs->trans("Contact").'</td><td>';
615  // If no socid, set to -1 to avoid full contacts list
616  $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
617  print img_picto('', 'contact', 'class="paddingright"');
618  print $form->selectcontacts($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 0, 'minwidth200');
619  print ' ';
620  $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
621  print '</td></tr>';
622  } else {
623  print '<tr><td class="titlefield"><input type="hidden" name="socid" value="'.$user->socid.'"/></td>';
624  print '<td><input type="hidden" name="contactid" value="'.$user->contact_id.'"/></td>';
625  print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
626  }
627 
628  // Notify thirdparty at creation
629  if (empty($this->ispublic)) {
630  print '<tr><td><label for="notify_tiers_at_create">'.$langs->trans("TicketNotifyTiersAtCreation").'</label></td><td>';
631  print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate ? ' checked="checked"' : '').'>';
632  print '</td></tr>';
633  }
634 
635  // User assigned
636  print '<tr><td>';
637  print $langs->trans("AssignedTo");
638  print '</td><td>';
639  print img_picto('', 'user', 'class="pictofixedwidth"');
640  print $form->select_dolusers(GETPOST('fk_user_assign', 'int'), 'fk_user_assign', 1);
641  print '</td>';
642  print '</tr>';
643  }
644 
645  if ($subelement != 'project') {
646  if (isModEnabled('project') && !$this->ispublic) {
647  $formproject = new FormProjets($this->db);
648  print '<tr><td><label for="project"><span class="">'.$langs->trans("Project").'</span></label></td><td>';
649  print img_picto('', 'project').$formproject->select_projects(-1, GETPOST('projectid', 'int'), 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
650  print '</td></tr>';
651  }
652  }
653 
654  // Other attributes
655  $parameters = array();
656  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
657  if (empty($reshook)) {
658  print $ticketstat->showOptionals($extrafields, 'create');
659  }
660 
661  print '</table>';
662 
663  if ($withdolfichehead) {
664  print dol_get_fiche_end();
665  }
666 
667  print '<br><br>';
668 
669  print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "CreateTicket"), ($this->withcancel ? "Cancel" : ""));
670 
671  /*
672  print '<div class="center">';
673  print '<input type="submit" class="button" name="add" value="'.$langs->trans(($this->withreadid > 0 ? "SendResponse" : "CreateTicket")).'" />';
674  if ($this->withcancel) {
675  print " &nbsp; &nbsp; &nbsp;";
676  print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
677  }
678  print '</div>';
679  */
680 
681  print '<input type="hidden" name="page_y">'."\n";
682 
683  print "</form>\n";
684  print "<!-- End form TICKET -->\n";
685  }
686 
701  public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $multiselect = 0)
702  {
703  global $langs, $user;
704 
705  $selected = is_array($selected) ? $selected : (!empty($selected) ? explode(',', $selected) : array());
706  $ticketstat = new Ticket($this->db);
707 
708  dol_syslog(get_class($this) . "::select_types_tickets " . implode(';', $selected) . ", " . $htmlname . ", " . $filtertype . ", " . $format . ", " . $multiselect, LOG_DEBUG);
709 
710  $filterarray = array();
711 
712  if ($filtertype != '' && $filtertype != '-1') {
713  $filterarray = explode(',', $filtertype);
714  }
715 
716  $ticketstat->loadCacheTypesTickets();
717 
718  print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.($multiselect?'[]':'').'"'.($multiselect?' multiple':'').'>';
719  if ($empty) {
720  print '<option value="">&nbsp;</option>';
721  }
722 
723  if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
724  foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
725  // On passe si on a demande de filtrer sur des modes de paiments particuliers
726  if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
727  continue;
728  }
729 
730  // If 'showempty' is enabled we discard empty line because an empty line has already been output.
731  if ($empty && empty($arraytypes['code'])) {
732  continue;
733  }
734 
735  if ($format == 0) {
736  print '<option value="'.$id.'"';
737  }
738 
739  if ($format == 1) {
740  print '<option value="'.$arraytypes['code'].'"';
741  }
742 
743  if ($format == 2) {
744  print '<option value="'.$arraytypes['code'].'"';
745  }
746 
747  if ($format == 3) {
748  print '<option value="'.$id.'"';
749  }
750 
751  // If text is selected, we compare with code, otherwise with id
752  if (in_array($arraytypes['code'], $selected)) {
753  print ' selected="selected"';
754  } elseif (in_array($id, $selected)) {
755  print ' selected="selected"';
756  } elseif ($arraytypes['use_default'] == "1" && !$selected && !$empty) {
757  print ' selected="selected"';
758  }
759 
760  print '>';
761 
762  $value = '&nbsp;';
763  if ($format == 0) {
764  $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
765  } elseif ($format == 1) {
766  $value = $arraytypes['code'];
767  } elseif ($format == 2) {
768  $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
769  } elseif ($format == 3) {
770  $value = $arraytypes['code'];
771  }
772 
773  print $value ? $value : '&nbsp;';
774  print '</option>';
775  }
776  }
777  print '</select>';
778  if (isset($user->admin) && $user->admin && !$noadmininfo) {
779  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
780  }
781 
782  print ajax_combobox('select'.$htmlname);
783  }
784 
800  public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0, $outputlangs = null)
801  {
802  global $conf, $langs, $user;
803 
804  dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
805 
806  if (is_null($outputlangs) || !is_object($outputlangs)) {
807  $outputlangs = $langs;
808  }
809  $outputlangs->load("ticket");
810 
811  $publicgroups = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
812 
813  $ticketstat = new Ticket($this->db);
814  $ticketstat->loadCacheCategoriesTickets($publicgroups ? 1 : -1); // get list of active ticket groups
815 
816  if ($use_multilevel <= 0) {
817  print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
818  if ($empty) {
819  print '<option value="">&nbsp;</option>';
820  }
821 
822  if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
823  foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
824  // Exclude some record
825  if ($publicgroups) {
826  if (empty($arraycategories['public'])) {
827  continue;
828  }
829  }
830 
831  // We discard empty line if showempty is on because an empty line has already been output.
832  if ($empty && empty($arraycategories['code'])) {
833  continue;
834  }
835 
836  $label = ($arraycategories['label'] != '-' ? $arraycategories['label'] : '');
837  if ($outputlangs->trans("TicketCategoryShort".$arraycategories['code']) != ("TicketCategoryShort".$arraycategories['code'])) {
838  $label = $outputlangs->trans("TicketCategoryShort".$arraycategories['code']);
839  } elseif ($outputlangs->trans($arraycategories['code']) != $arraycategories['code']) {
840  $label = $outputlangs->trans($arraycategories['code']);
841  }
842 
843  if ($format == 0) {
844  print '<option value="'.$id.'"';
845  }
846 
847  if ($format == 1) {
848  print '<option value="'.$arraycategories['code'].'"';
849  }
850 
851  if ($format == 2) {
852  print '<option value="'.$arraycategories['code'].'"';
853  }
854 
855  if ($format == 3) {
856  print '<option value="'.$id.'"';
857  }
858 
859  // If selected is text, we compare with code, otherwise with id
860  if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
861  print ' selected="selected"';
862  } elseif (isset($selected) && $selected == $id) {
863  print ' selected="selected"';
864  } elseif ($arraycategories['use_default'] == "1" && !$selected && !$empty) {
865  print ' selected="selected"';
866  } elseif (count($ticketstat->cache_category_tickets) == 1) {
867  print ' selected="selected"';
868  }
869 
870  print '>';
871 
872  $value = '';
873  if ($format == 0) {
874  $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
875  }
876 
877  if ($format == 1) {
878  $value = $arraycategories['code'];
879  }
880 
881  if ($format == 2) {
882  $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
883  }
884 
885  if ($format == 3) {
886  $value = $arraycategories['code'];
887  }
888 
889  print $value ? $value : '&nbsp;';
890  print '</option>';
891  }
892  }
893  print '</select>';
894  if (isset($user->admin) && $user->admin && !$noadmininfo) {
895  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
896  }
897 
898  print ajax_combobox('select'.$htmlname);
899  } elseif ($htmlname!='') {
900  $selectedgroups = array();
901  $groupvalue = "";
902  $groupticket=GETPOST($htmlname, 'aZ09');
903  $child_id=GETPOST($htmlname.'_child_id', 'aZ09')?GETPOST($htmlname.'_child_id', 'aZ09'):0;
904  if (!empty($groupticket)) {
905  $tmpgroupticket = $groupticket;
906  $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code";
907  $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'";
908  $resql = $this->db->query($sql);
909  if ($resql) {
910  $obj = $this->db->fetch_object($resql);
911  $selectedgroups[] = $obj->code;
912  while ($obj->fk_parent > 0) {
913  $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)."'";
914  $resql = $this->db->query($sql);
915  if ($resql) {
916  $obj = $this->db->fetch_object($resql);
917  $selectedgroups[] = $obj->code;
918  }
919  }
920  }
921  }
922 
923  $arrayidused = array();
924  $arrayidusedconcat = array();
925  $arraycodenotparent = array();
926  $arraycodenotparent[] = "";
927 
928  $stringtoprint = '<span class="supportemailfield bold">'.$langs->trans("GroupOfTicket").'</span> ';
929  $stringtoprint .= '<select id ="'.$htmlname.'" class="minwidth500" child_id="0">';
930  $stringtoprint .= '<option value="">&nbsp;</option>';
931 
932  $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ";
933  $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";
934  $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
935  $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
936  if ($filtertype == 'public=1') {
937  $sql .= " AND ctc.public = 1";
938  }
939  $sql .= " AND ctc.fk_parent = 0";
940  $sql .= $this->db->order('ctc.pos', 'ASC');
941 
942  $resql = $this->db->query($sql);
943  if ($resql) {
944  $num_rows_level0 = $this->db->num_rows($resql);
945  $i = 0;
946  while ($i < $num_rows_level0) {
947  $obj = $this->db->fetch_object($resql);
948  if ($obj) {
949  $label = ($obj->label != '-' ? $obj->label : '');
950  if ($outputlangs->trans("TicketCategoryShort".$obj->code) != ("TicketCategoryShort".$obj->code)) {
951  $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
952  } elseif ($outputlangs->trans($obj->code) != $obj->code) {
953  $label = $outputlangs->trans($obj->code);
954  }
955 
956  $grouprowid = $obj->rowid;
957  $groupvalue = $obj->code;
958  $grouplabel = $label;
959 
960  $isparent = $obj->isparent;
961  if (is_array($selectedgroups)) {
962  $iselected = in_array($obj->code, $selectedgroups) ?'selected':'';
963  } else {
964  $iselected = $groupticket == $obj->code ?'selected':'';
965  }
966  $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>';
967  if ($isparent == 'NOTPARENT') {
968  $arraycodenotparent[] = $groupvalue;
969  }
970  $arrayidused[] = $grouprowid;
971  $arrayidusedconcat[] = $grouprowid;
972  }
973  $i++;
974  }
975  } else {
976  dol_print_error($this->db);
977  }
978  if (count($arrayidused) == 1) {
979  return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
980  } else {
981  $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400">';
982  $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400">';
983  }
984  $stringtoprint .= '</select>&nbsp;';
985 
986  $levelid = 1; // The first combobox
987  while ($levelid <= $use_multilevel) { // Loop to take the child of the combo
988  $tabscript = array();
989  $stringtoprint .= '<select id ="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
990  $stringtoprint .= '<option value="">&nbsp;</option>';
991 
992  $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather";
993  $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
994  $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
995  $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
996  $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(join(',', $arrayidusedconcat)).")";
997 
998  if ($filtertype == 'public=1') {
999  $sql .= " AND ctc.public = 1";
1000  }
1001  // Add a test to take only record that are direct child
1002  if (!empty($arrayidused)) {
1003  $sql .= " AND ctc.fk_parent IN ( ";
1004  foreach ($arrayidused as $idused) {
1005  $sql .= $idused.", ";
1006  }
1007  $sql = substr($sql, 0, -2);
1008  $sql .= ")";
1009  }
1010  $sql .= $this->db->order('ctc.pos', 'ASC');
1011 
1012  $resql = $this->db->query($sql);
1013  if ($resql) {
1014  $num_rows = $this->db->num_rows($resql);
1015  $i = 0;
1016  $arrayidused=array();
1017  while ($i < $num_rows) {
1018  $obj = $this->db->fetch_object($resql);
1019  if ($obj) {
1020  $label = ($obj->label != '-' ? $obj->label : '');
1021  if ($outputlangs->trans("TicketCategoryShort".$obj->code) != ("TicketCategoryShort".$obj->code)) {
1022  $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1023  } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1024  $label = $outputlangs->trans($obj->code);
1025  }
1026 
1027  $grouprowid = $obj->rowid;
1028  $groupvalue = $obj->code;
1029  $grouplabel = $label;
1030  $isparent = $obj->isparent;
1031  $fatherid = $obj->fk_parent;
1032  $arrayidused[] = $grouprowid;
1033  $arrayidusedconcat[] = $grouprowid;
1034  $groupcodefather = $obj->codefather;
1035  if ($isparent == 'NOTPARENT') {
1036  $arraycodenotparent[] = $groupvalue;
1037  }
1038  if (is_array($selectedgroups)) {
1039  $iselected = in_array($obj->code, $selectedgroups) ?'selected':'';
1040  } else {
1041  $iselected = $groupticket == $obj->code ?'selected':'';
1042  }
1043  $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>';
1044  if (empty($tabscript[$groupcodefather])) {
1045  $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ?'_child_'.($levelid-1):'').'").val() == "'.dol_escape_js($groupcodefather).'"){
1046  $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").show()
1047  console.log("We show childs tickets of '.$groupcodefather.' group ticket")
1048  }else{
1049  $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").hide()
1050  console.log("We hide childs tickets of '.$groupcodefather.' group ticket")
1051  }';
1052  }
1053  }
1054  $i++;
1055  }
1056  } else {
1057  dol_print_error($this->db);
1058  }
1059  $stringtoprint .='</select>';
1060 
1061  $stringtoprint .='<script nonce="'.getNonce().'">';
1062  $stringtoprint .='arraynotparents = '.json_encode($arraycodenotparent).';'; // when the last visible combo list is number x, this is the array of group
1063  $stringtoprint .='if (arraynotparents.includes($("#'.$htmlname.($levelid > 1 ?'_child_'.($levelid-1):'').'").val())){
1064  console.log("'.$htmlname.'_child_'.$levelid.'")
1065  if($("#'.$htmlname.'_child_'.$levelid.'").val() == "" && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")>'.$child_id.')){
1066  $("#'.$htmlname.'_child_'.$levelid.'").hide();
1067  console.log("We hide '.$htmlname.'_child_'.$levelid.' input")
1068  }
1069  if(arraynotparents.includes("'.$groupticket.'") && '.$child_id.' == 0){
1070  $("#ticketcategory_select_child_id").val($("#'.$htmlname.'").attr("child_id"))
1071  $("#ticketcategory_select").val($("#'.$htmlname.'").val()) ;
1072  console.log("We choose '.$htmlname.' input and reload hidden input");
1073  }
1074  }
1075  $("#'.$htmlname.($levelid > 1 ?'_child_'.($levelid-1):'').'").change(function() {
1076  child_id = $("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid:'').'").attr("child_id");
1077 
1078  /* Change of value to select this value*/
1079  if (arraynotparents.includes($(this).val()) || $(this).attr("child_id") == '.$use_multilevel.') {
1080  $("#ticketcategory_select").val($(this).val());
1081  $("#ticketcategory_select_child_id").val($(this).attr("child_id")) ;
1082  console.log("We choose to select "+ $(this).val());
1083  }else{
1084  if ($("#'.$htmlname.'_child_'.$levelid.' option").length <= 1) {
1085  $("#ticketcategory_select").val($(this).val());
1086  $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1087  console.log("We choose to select "+ $(this).val() + " and next combo has no item, so we keep this selection");
1088  } else {
1089  console.log("We choose to select "+ $(this).val() + " but next combo has some item, so we clean selected item");
1090  $("#ticketcategory_select").val("");
1091  $("#ticketcategory_select_child_id").val("");
1092  }
1093  }
1094 
1095  console.log("We select a new value into combo child_id="+child_id);
1096 
1097  // Hide all selected box that are child of the one modified
1098  $(".groupticketchild").each(function(){
1099  if ($(this).attr("child_id") > child_id) {
1100  console.log("hide child_id="+$(this).attr("child_id"));
1101  $(this).val("");
1102  $(this).hide();
1103  }
1104  })
1105 
1106  // Now we enable the next combo
1107  $("#'.$htmlname.'_child_'.$levelid.'").val("");
1108  if (!arraynotparents.includes($(this).val()) && $("#'.$htmlname.'_child_'.$levelid.' option").length > 1) {
1109  console.log($("#'.$htmlname.'_child_'.$levelid.' option").length);
1110  $("#'.$htmlname.'_child_'.$levelid.'").show()
1111  } else {
1112  $("#'.$htmlname.'_child_'.$levelid.'").hide()
1113  }
1114  ';
1115  $levelid++;
1116  foreach ($tabscript as $script) {
1117  $stringtoprint .= $script;
1118  }
1119  $stringtoprint .='})';
1120  $stringtoprint .='</script>';
1121  }
1122  $stringtoprint .='<script nonce="'.getNonce().'">';
1123  $stringtoprint .='$("#'.$htmlname.'_child_'.$use_multilevel.'").change(function() {
1124  $("#ticketcategory_select").val($(this).val());
1125  $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1126  console.log($("#ticketcategory_select").val());
1127  })';
1128  $stringtoprint .='</script>';
1129  $stringtoprint .= ajax_combobox($htmlname);
1130 
1131  return $stringtoprint;
1132  }
1133  }
1134 
1148  public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
1149  {
1150  global $langs, $user;
1151 
1152  $ticketstat = new Ticket($this->db);
1153 
1154  dol_syslog(get_class($this)."::selectSeveritiesTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
1155 
1156  $filterarray = array();
1157 
1158  if ($filtertype != '' && $filtertype != '-1') {
1159  $filterarray = explode(',', $filtertype);
1160  }
1161 
1162  $ticketstat->loadCacheSeveritiesTickets();
1163 
1164  print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
1165  if ($empty) {
1166  print '<option value="">&nbsp;</option>';
1167  }
1168 
1169  if (is_array($ticketstat->cache_severity_tickets) && count($ticketstat->cache_severity_tickets)) {
1170  foreach ($ticketstat->cache_severity_tickets as $id => $arrayseverities) {
1171  // On passe si on a demande de filtrer sur des modes de paiments particuliers
1172  if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
1173  continue;
1174  }
1175 
1176  // We discard empty line if showempty is on because an empty line has already been output.
1177  if ($empty && empty($arrayseverities['code'])) {
1178  continue;
1179  }
1180 
1181  if ($format == 0) {
1182  print '<option value="'.$id.'"';
1183  }
1184 
1185  if ($format == 1) {
1186  print '<option value="'.$arrayseverities['code'].'"';
1187  }
1188 
1189  if ($format == 2) {
1190  print '<option value="'.$arrayseverities['code'].'"';
1191  }
1192 
1193  if ($format == 3) {
1194  print '<option value="'.$id.'"';
1195  }
1196 
1197  // If text is selected, we compare with code, otherwise with id
1198  if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
1199  print ' selected="selected"';
1200  } elseif (isset($selected) && $selected == $id) {
1201  print ' selected="selected"';
1202  } elseif ($arrayseverities['use_default'] == "1" && !$selected && !$empty) {
1203  print ' selected="selected"';
1204  }
1205 
1206  print '>';
1207 
1208  $value = '';
1209  if ($format == 0) {
1210  $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1211  }
1212 
1213  if ($format == 1) {
1214  $value = $arrayseverities['code'];
1215  }
1216 
1217  if ($format == 2) {
1218  $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1219  }
1220 
1221  if ($format == 3) {
1222  $value = $arrayseverities['code'];
1223  }
1224 
1225  print $value ? $value : '&nbsp;';
1226  print '</option>';
1227  }
1228  }
1229  print '</select>';
1230  if (isset($user->admin) && $user->admin && !$noadmininfo) {
1231  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1232  }
1233 
1234  print ajax_combobox('select'.$htmlname);
1235  }
1236 
1237  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1243  public function clear_attached_files()
1244  {
1245  // phpcs:enable
1246  global $conf, $user;
1247  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1248 
1249  // Set tmp user directory
1250  $vardir = $conf->user->dir_output."/".$user->id;
1251  $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
1252  if (is_dir($upload_dir)) {
1253  dol_delete_dir_recursive($upload_dir);
1254  }
1255 
1256  if (!empty($this->trackid)) { // TODO Always use trackid (ticXXX) instead of track_id (abcd123)
1257  $keytoavoidconflict = '-'.$this->trackid;
1258  } else {
1259  $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id;
1260  }
1261  unset($_SESSION["listofpaths".$keytoavoidconflict]);
1262  unset($_SESSION["listofnames".$keytoavoidconflict]);
1263  unset($_SESSION["listofmimes".$keytoavoidconflict]);
1264  }
1265 
1272  public function showMessageForm($width = '40%')
1273  {
1274  global $conf, $langs, $user, $hookmanager, $form, $mysoc;
1275 
1276  $formmail = new FormMail($this->db);
1277  $addfileaction = 'addfile';
1278 
1279  if (!is_object($form)) {
1280  $form = new Form($this->db);
1281  }
1282 
1283  // Load translation files required by the page
1284  $langs->loadLangs(array('other', 'mails', 'ticket'));
1285 
1286  // Clear temp files. Must be done at beginning, before call of triggers
1287  if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1288  $this->clear_attached_files();
1289  }
1290 
1291  // Define output language
1292  $outputlangs = $langs;
1293  $newlang = '';
1294  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1295  $newlang = $this->param['langsmodels'];
1296  }
1297  if (!empty($newlang)) {
1298  $outputlangs = new Translate("", $conf);
1299  $outputlangs->setDefaultLang($newlang);
1300  $outputlangs->load('other');
1301  }
1302 
1303  // Get message template for $this->param["models"] into c_email_templates
1304  $arraydefaultmessage = -1;
1305  if (isset($this->param['models']) && $this->param['models'] != 'none') {
1306  $model_id = 0;
1307  if (array_key_exists('models_id', $this->param)) {
1308  $model_id = (int) $this->param["models_id"];
1309  }
1310 
1311  $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
1312  }
1313 
1314  // Define list of attached files
1315  $listofpaths = array();
1316  $listofnames = array();
1317  $listofmimes = array();
1318 
1319  if (!empty($this->trackid)) {
1320  $keytoavoidconflict = '-'.$this->trackid;
1321  } else {
1322  $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1323  }
1324  //var_dump($keytoavoidconflict);
1325  if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1326  if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
1327  foreach ($this->param['fileinit'] as $file) {
1328  $formmail->add_attached_files($file, basename($file), dol_mimetype($file));
1329  }
1330  }
1331  }
1332  //var_dump($_SESSION);
1333  //var_dump($_SESSION["listofpaths".$keytoavoidconflict]);
1334  if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
1335  $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
1336  }
1337  if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
1338  $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
1339  }
1340  if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
1341  $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
1342  }
1343 
1344  // Define output language
1345  $outputlangs = $langs;
1346  $newlang = '';
1347  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1348  $newlang = $this->param['langsmodels'];
1349  }
1350  if (!empty($newlang)) {
1351  $outputlangs = new Translate("", $conf);
1352  $outputlangs->setDefaultLang($newlang);
1353  $outputlangs->load('other');
1354  }
1355 
1356  print "\n<!-- Begin message_form TICKET -->\n";
1357 
1358  $send_email = GETPOST('send_email', 'int') ? GETPOST('send_email', 'int') : 0;
1359 
1360  // Example 1 : Adding jquery code
1361  print '<script nonce="'.getNonce().'" type="text/javascript">
1362  jQuery(document).ready(function() {
1363  send_email=' . $send_email.';
1364  if (send_email) {
1365  if (!jQuery("#send_msg_email").is(":checked")) {
1366  jQuery("#send_msg_email").prop("checked", true).trigger("change");
1367  }
1368  jQuery(".email_line").show();
1369  } else {
1370  if (!jQuery("#private_message").is(":checked")) {
1371  jQuery("#private_message").prop("checked", true).trigger("change");
1372  }
1373  jQuery(".email_line").hide();
1374  }
1375  ';
1376 
1377  // If constant set, allow to send private messages as email
1378  if (empty($conf->global->TICKET_SEND_PRIVATE_EMAIL)) {
1379  print 'jQuery("#send_msg_email").click(function() {
1380  console.log("Click send_msg_email");
1381  if(jQuery(this).is(":checked")) {
1382  if (jQuery("#private_message").is(":checked")) {
1383  jQuery("#private_message").prop("checked", false).trigger("change");
1384  }
1385  jQuery(".email_line").show();
1386  }
1387  else {
1388  jQuery(".email_line").hide();
1389  }
1390  });
1391 
1392  jQuery("#private_message").click(function() {
1393  console.log("Click private_message");
1394  if (jQuery(this).is(":checked")) {
1395  if (jQuery("#send_msg_email").is(":checked")) {
1396  jQuery("#send_msg_email").prop("checked", false).trigger("change");
1397  }
1398  jQuery(".email_line").hide();
1399  }
1400  });';
1401  }
1402 
1403  print '});
1404  </script>';
1405 
1406 
1407  print '<form method="post" name="ticket" id="ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
1408  print '<input type="hidden" name="token" value="'.newToken().'">';
1409  print '<input type="hidden" name="action" value="'.$this->action.'">';
1410  print '<input type="hidden" name="actionbis" value="add_message">';
1411  print '<input type="hidden" name="backtopage" value="'.$this->backtopage.'">';
1412  if (!empty($this->trackid)) {
1413  print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
1414  } else {
1415  print '<input type="hidden" name="trackid" value="'.(empty($this->track_id) ? '' : $this->track_id).'">';
1416  $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1417  }
1418  foreach ($this->param as $key => $value) {
1419  print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
1420  }
1421 
1422  // Get message template
1423  $model_id = 0;
1424  if (array_key_exists('models_id', $this->param)) {
1425  $model_id = $this->param["models_id"];
1426  $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
1427  }
1428 
1429  $result = $formmail->fetchAllEMailTemplate(!empty($this->param["models"]) ? $this->param["models"] : "", $user, $outputlangs);
1430  if ($result < 0) {
1431  setEventMessages($this->error, $this->errors, 'errors');
1432  }
1433  $modelmail_array = array();
1434  foreach ($formmail->lines_model as $line) {
1435  $modelmail_array[$line->id] = $line->label;
1436  }
1437 
1438  print '<table class="border" width="'.$width.'">';
1439 
1440  // External users can't send message email
1441  if ($user->hasRight("ticket", "write") && !$user->socid) {
1442  $ticketstat = new Ticket($this->db);
1443  $res = $ticketstat->fetch('', '', $this->track_id);
1444 
1445  print '<tr><td></td><td>';
1446  $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : (getDolGlobalInt('TICKETS_MESSAGE_FORCE_MAIL')?'checked':''));
1447  print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
1448  print '<label for="send_msg_email">'.$langs->trans('SendMessageByEmail').'</label>';
1449  $texttooltip = $langs->trans("TicketMessageSendEmailHelp");
1450  if (empty($conf->global->TICKET_SEND_PRIVATE_EMAIL)) {
1451  $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2b");
1452  } else {
1453  $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2a", '{s1}');
1454  }
1455  $texttooltip = str_replace('{s1}', $langs->trans('MarkMessageAsPrivate'), $texttooltip);
1456  print ' '.$form->textwithpicto('', $texttooltip, 1, 'help');
1457  print '</td></tr>';
1458 
1459  // Private message (not visible by customer/external user)
1460  if (!$user->socid) {
1461  print '<tr><td></td><td>';
1462  $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : '');
1463  print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
1464  print '<label for="private_message">'.$langs->trans('MarkMessageAsPrivate').'</label>';
1465  print ' '.$form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
1466  print '</td></tr>';
1467  }
1468 
1469  // Zone to select its email template
1470  if (count($modelmail_array) > 0) {
1471  print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
1472  print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, "", "", 0, 0, 0, '', 'minwidth200');
1473  if ($user->admin) {
1474  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1475  }
1476  print ' &nbsp; ';
1477  print '<input type="submit" class="button" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
1478  print '</div></td>';
1479  }
1480  // Subject/topic
1481  $topic = "";
1482  foreach ($formmail->lines_model as $line) {
1483  if ($this->param['models_id'] == $line->id) {
1484  $topic = $line->topic;
1485  break;
1486  }
1487  }
1488  print '<tr class="email_line"><td>'.$langs->trans('Subject').'</td>';
1489  if (empty($topic)) {
1490  print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '.$langs->trans('TicketNewMessage').'" />';
1491  } else {
1492  print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '.$topic.'" />';
1493  }
1494  print '</td></tr>';
1495 
1496  // Recipients / adressed-to
1497  print '<tr class="email_line"><td>'.$langs->trans('MailRecipients');
1498  print ' '.$form->textwithpicto('', $langs->trans("TicketMessageRecipientsHelp"), 1, 'help');
1499  print '</td><td>';
1500  if ($res) {
1501  // Retrieve email of all contacts (internal and external)
1502  $contacts = $ticketstat->getInfosTicketInternalContact(1);
1503  $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact(1));
1504 
1505  $sendto = array();
1506 
1507  // Build array to display recipient list
1508  if (is_array($contacts) && count($contacts) > 0) {
1509  foreach ($contacts as $key => $info_sendto) {
1510  if ($info_sendto['email'] != '') {
1511  $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">").' <small class="opacitymedium">('.dol_escape_htmltag($info_sendto['libelle']).")</small>";
1512  }
1513  }
1514  }
1515 
1516  if ($ticketstat->origin_email && !in_array($ticketstat->origin_email, $sendto)) {
1517  $sendto[] = dol_escape_htmltag($ticketstat->origin_email).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1518  }
1519 
1520  if ($ticketstat->fk_soc > 0) {
1521  $ticketstat->socid = $ticketstat->fk_soc;
1522  $ticketstat->fetch_thirdparty();
1523 
1524  if (is_array($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
1525  $sendto[] = $ticketstat->thirdparty->email.' <small class="opacitymedium">('.$langs->trans('Customer').')</small>';
1526  }
1527  }
1528 
1529  if (getDolGlobalInt('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS')) {
1530  $sendto[] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO').' <small class="opacitymedium">(generic email)</small>';
1531  }
1532 
1533  // Print recipient list
1534  if (is_array($sendto) && count($sendto) > 0) {
1535  print img_picto('', 'email', 'class="pictofixedwidth"');
1536  print implode(', ', $sendto);
1537  } else {
1538  print '<div class="warning">'.$langs->trans('WarningNoEMailsAdded').' '.$langs->trans('TicketGoIntoContactTab').'</div>';
1539  }
1540  }
1541  print '</td></tr>';
1542  }
1543 
1544  $uselocalbrowser = false;
1545 
1546  // Intro
1547  // External users can't send message email
1548  /*
1549  if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_INTRO)) {
1550  $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
1551  print '<tr class="email_line"><td><label for="mail_intro">';
1552  print $form->textwithpicto($langs->trans("TicketMessageMailIntro"), $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
1553  print '</label>';
1554 
1555  print '</td><td>';
1556  include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1557 
1558  $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_2, 70);
1559 
1560  $doleditor->Create();
1561  print '</td></tr>';
1562  }
1563  */
1564 
1565  // Attached files
1566  if (!empty($this->withfile)) {
1567  $out = '<tr>';
1568  $out .= '<td width="180">'.$langs->trans("MailFile").'</td>';
1569  $out .= '<td>';
1570  // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
1571  $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
1572  $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1573  $out .= 'jQuery(document).ready(function () {';
1574  $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1575  $out .= ' jQuery("#addedfile").on("change", function() {';
1576  $out .= ' if (jQuery(this).val().length) {';
1577  $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", false);';
1578  $out .= ' } else {';
1579  $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1580  $out .= ' }';
1581  $out .= ' });';
1582  $out .= ' jQuery(".removedfile").click(function() {';
1583  $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
1584  $out .= ' });';
1585  $out .= '})';
1586  $out .= '</script>'."\n";
1587 
1588  if (count($listofpaths)) {
1589  foreach ($listofpaths as $key => $val) {
1590  $out .= '<div id="attachfile_'.$key.'">';
1591  $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
1592  if (!$this->withfilereadonly) {
1593  $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.'" />';
1594  }
1595  $out .= '<br></div>';
1596  }
1597  } else {
1598  //$out .= $langs->trans("NoAttachedFiles").'<br>';
1599  }
1600  if ($this->withfile == 2) { // Can add other files
1601  $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
1602  $out .= ' ';
1603  $out .= '<input type="submit" class="button smallpaddingimp reposition" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
1604  }
1605  $out .= "</td></tr>\n";
1606 
1607  print $out;
1608  }
1609 
1610  // MESSAGE
1611 
1612  $defaultmessage = "";
1613  if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
1614  $defaultmessage = $arraydefaultmessage->content;
1615  }
1616  $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1617 
1618  // Deal with format differences between message and signature (text / HTML)
1619  if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1620  $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1621  } elseif (!dol_textishtml($defaultmessage) && isset($this->substit['__USER_SIGNATURE__']) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1622  $defaultmessage = dol_nl2br($defaultmessage);
1623  }
1624  if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1625  $defaultmessage = GETPOST('message', 'restricthtml');
1626  } else {
1627  $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1628  // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1629  $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1630  $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1631  }
1632 
1633  print '<tr><td colspan="2"><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span>';
1634  if ($user->hasRight("ticket", "write") && !$user->socid) {
1635  $texttooltip = $langs->trans("TicketMessageHelp");
1636  if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO') || getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1637  $texttooltip .= '<br><br>'.$langs->trans("ForEmailMessageWillBeCompletedWith").'...';
1638  }
1639  if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO')) {
1640  $texttooltip .= '<br><u>'.$langs->trans("TicketMessageMailIntro").'</u><br>'.getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO');
1641  }
1642  if (getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1643  $texttooltip .= '<br><br><u>'.$langs->trans("TicketMessageMailFooter").'</u><br>'.getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE');
1644  }
1645  print $form->textwithpicto('', $texttooltip, 1, 'help');
1646  }
1647  print '</label></td></tr>';
1648 
1649 
1650  print '<tr><td colspan="2">';
1651  //$toolbarname = 'dolibarr_details';
1652  $toolbarname = 'dolibarr_notes';
1653  include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1654  $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_5, 70);
1655  $doleditor->Create();
1656  print '</td></tr>';
1657 
1658  // Footer
1659  // External users can't send message email
1660  /*if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_SIGNATURE)) {
1661  $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
1662  print '<tr class="email_line"><td><label for="mail_intro">'.$langs->trans("TicketMessageMailFooter").'</label>';
1663  print $form->textwithpicto('', $langs->trans("TicketMessageMailFooterHelp"), 1, 'help');
1664  print '</td><td>';
1665  include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1666  $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_2, 70);
1667  $doleditor->Create();
1668  print '</td></tr>';
1669  }
1670  */
1671 
1672  print '</table>';
1673 
1674  print '<center><br>';
1675  print '<input type="submit" class="button" name="btn_add_message" value="'.$langs->trans("Add").'"';
1676  // Add a javascript test to avoid to forget to submit file before sending email
1677  if ($this->withfile == 2 && !empty($conf->use_javascript_ajax)) {
1678  print ' onClick="if (document.ticket.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1679  }
1680  print ' />';
1681  if (!empty($this->withcancel)) {
1682  print " &nbsp; &nbsp; ";
1683  print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
1684  }
1685  print "</center>\n";
1686 
1687  print '<input type="hidden" name="page_y">'."\n";
1688 
1689  print "</form>\n";
1690 
1691  // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1692  if (!empty($conf->global->MAIN_MAILFORM_DISABLE_ENTERKEY)) {
1693  print '<script type="text/javascript">';
1694  print 'jQuery(document).ready(function () {';
1695  print ' $(document).on("keypress", \'#ticket\', function (e) { /* Note this is called at every key pressed ! */
1696  var code = e.keyCode || e.which;
1697  if (code == 13) {
1698  console.log("Enter was intercepted and blocked");
1699  e.preventDefault();
1700  return false;
1701  }
1702  });';
1703  print '})';
1704  print '</script>';
1705  }
1706 
1707  print "<!-- End form TICKET -->\n";
1708  }
1709 }
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:449
Class to manage contact/addresses.
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
Class to build HTML component for third parties management Only common components are here.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new For...
Class to manage building of HTML components.
selectGroupTickets($selected='', $htmlname='ticketcategory', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $morecss='', $use_multilevel=0, $outputlangs=null)
Return html list of ticket anaytic codes.
selectSeveritiesTickets($selected='', $htmlname='ticketseverity', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $morecss='')
Return html list of ticket severitys (priorities)
showMessageForm($width='40%')
Show the form to add message on ticket.
selectTypesTickets($selected='', $htmlname='tickettype', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $morecss='', $multiselect=0)
Return html list of tickets type.
__construct($db)
Constructor.
showForm($withdolfichehead=0, $mode='edit', $public=0, Contact $with_contact=null, $action='')
Show the form to input ticket.
clear_attached_files()
Clear list of attached files in send mail form (also stored in session)
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
Definition: files.lib.php:1485
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_textishtml($msg, $option=0)
Return if a text is a html content.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
table tableforfield button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
Definition: style.css.php:848
Class to generate the form for creating a new ticket.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
getMaxFileSizeArray()
Return the max allowed for file upload.