dolibarr 21.0.0-beta
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-2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2021 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2023 Charlene Benke <charlene.r@patas-monkey.com>
8 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024 Irvine FLEITH <irvine.fleith@atm-consulting.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
31require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
32require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
33require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
34
35if (!class_exists('FormCompany')) {
36 include DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
37}
38
48{
52 public $db;
53
57 public $track_id;
58
62 public $trackid;
63
67 public $fk_user_create;
68
72 public $message;
76 public $topic_title;
77
81 public $action;
82
86 public $withtopic;
90 public $withemail;
91
95 public $withsubstit;
96
100 public $withfile;
104 public $withfilereadonly;
105
109 public $backtopage;
110
114 public $ispublic; // to show information or not into public form
115
119 public $withtitletopic;
123 public $withtopicreadonly;
127 public $withreadid;
128
132 public $withcompany; // to show company drop-down list
136 public $withfromsocid;
140 public $withfromcontactid;
144 public $withnotifytiersatcreate;
148 public $withusercreate; // to show name of creating user in form
152 public $withcreatereadonly;
153
157 public $withextrafields;
158
162 public $withref; // to show ref field
166 public $withcancel;
167
171 public $type_code;
175 public $category_code;
179 public $severity_code;
180
181
186 public $substit = array();
190 public $param = array();
191
195 public $error;
199 public $errors = array();
200
201
207 public function __construct($db)
208 {
209 global $conf;
210
211 $this->db = $db;
212
213 $this->action = 'add';
214
215 $this->withcompany = (int) (!getDolGlobalInt("TICKETS_NO_COMPANY_ON_FORM") && isModEnabled("societe"));
216 $this->withfromsocid = 0;
217 $this->withfromcontactid = 0;
218 $this->withreadid = 0;
219 //$this->withtitletopic='';
220 $this->withnotifytiersatcreate = 0;
221 $this->withusercreate = 1;
222 $this->withcreatereadonly = 1;
223 $this->withemail = 0;
224 $this->withref = 0;
225 $this->withextrafields = 0; // to show extrafields or not
226 //$this->withtopicreadonly=0;
227 }
228
237 public static function checkRequiredFields(array $fields, int &$errors)
238 {
239 global $langs;
240
241 foreach ($fields as $field => $type) {
242 if (!GETPOST($field, $type['check'])) {
243 $errors++;
244 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities($type['langs'])), null, 'errors');
245 }
246 }
247 }
248
260 public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0, $with_contact = null, $action = '', $object = null)
261 {
262 global $conf, $langs, $user, $hookmanager;
263
264 // Load translation files required by the page
265 $langs->loadLangs(array('other', 'mails', 'ticket'));
266
267 if ($mode == 'create') {
268 $ref = GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : '';
269 $type_code = GETPOSTISSET('type_code') ? GETPOST('type_code', 'alpha') : '';
270 $category_code = GETPOSTISSET('category_code') ? GETPOST('category_code', 'alpha') : '';
271 $severity_code = GETPOSTISSET('severity_code') ? GETPOST('severity_code', 'alpha') : '';
272 $subject = GETPOSTISSET('subject') ? GETPOST('subject', 'alpha') : '';
273 $email = GETPOSTISSET('email') ? GETPOST('email', 'alpha') : '';
274 $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : '';
275 $projectid = GETPOSTISSET('projectid') ? GETPOST('projectid', 'int') : '';
276 $user_assign = GETPOSTISSET('fk_user_assign') ? GETPOSTINT('fk_user_assign') : $this->fk_user_create;
277 } else {
278 $ref = GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $object->ref;
279 $type_code = GETPOSTISSET('type_code') ? GETPOST('type_code', 'alpha') : $object->type_code;
280 $category_code = GETPOSTISSET('category_code') ? GETPOST('category_code', 'alpha') : $object->category_code;
281 $severity_code = GETPOSTISSET('severity_code') ? GETPOST('severity_code', 'alpha') : $object->severity_code;
282 $subject = GETPOSTISSET('subject') ? GETPOST('subject', 'alpha') : $object->subject;
283 $email = GETPOSTISSET('email') ? GETPOST('email', 'alpha') : $object->email_from;
284 $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : $object->message;
285 $projectid = GETPOSTISSET('projectid') ? GETPOST('projectid', 'int') : $object->fk_project;
286 $user_assign = GETPOSTISSET('fk_user_assign') ? GETPOSTINT('fk_user_assign') : $object->fk_user_assign;
287 }
288
289 $form = new Form($this->db);
290 $formcompany = new FormCompany($this->db);
291 $ticketstatic = new Ticket($this->db);
292
293 $soc = new Societe($this->db);
294 if (!empty($this->withfromsocid) && $this->withfromsocid > 0) {
295 $soc->fetch($this->withfromsocid);
296 }
297
298 $ticketstat = new Ticket($this->db);
299
300 $extrafields = new ExtraFields($this->db);
301 $extrafields->fetch_name_optionals_label($ticketstat->table_element);
302
303 print "\n<!-- Begin form TICKET -->\n";
304
305 if ($withdolfichehead) {
306 print dol_get_fiche_head([], 'card', '', 0, '');
307 }
308
309 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']).'">';
310 print '<input type="hidden" name="token" value="'.newToken().'">';
311 print '<input type="hidden" name="action" value="'.$this->action.'">';
312 if (!empty($object->id)) {
313 print '<input type="hidden" name="id" value="'. $object->id .'">';
314 }
315 print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
316 foreach ($this->param as $key => $value) {
317 print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
318 }
319 print '<input type="hidden" name="fk_user_create" value="'.$this->fk_user_create.'">';
320
321 print '<table class="border centpercent">';
322
323 // Ref
324 if ($this->withref) {
325 $defaultref = $ticketstat->getDefaultRef();
326
327 if ($mode == 'edit') {
328 $defaultref = $object->ref;
329 }
330 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
331 print '<input type="text" name="ref" value="'.dol_escape_htmltag($defaultref).'">';
332 print '</td></tr>';
333 }
334
335 // Title
336 if ($this->withemail) {
337 print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("Email").'</span></label></td><td>';
338 print '<input class="text minwidth200" id="email" name="email" value="'.$email.'" autofocus>'; // Do not use "required", it breaks button cancel
339 print '</td></tr>';
340
341 if ($with_contact) {
342 // contact search and result
343 $html_contact_search = '';
344 $html_contact_search .= '<tr id="contact_search_line">';
345 $html_contact_search .= '<td class="titlefield">';
346 $html_contact_search .= '<label for="contact"><span class="fieldrequired">' . $langs->trans('Contact') . '</span></label>';
347 $html_contact_search .= '<input type="hidden" id="contact_id" name="contact_id" value="" />';
348 $html_contact_search .= '</td>';
349 $html_contact_search .= '<td id="contact_search_result"></td>';
350 $html_contact_search .= '</tr>';
351 print $html_contact_search;
352 // contact lastname
353 $html_contact_lastname = '';
354 $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>';
355 $html_contact_lastname .= '<input type="text" id="contact_lastname" name="contact_lastname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_lastname') ? GETPOST('contact_lastname', 'alphanohtml') : '') . '" />';
356 $html_contact_lastname .= '</td></tr>';
357 print $html_contact_lastname;
358 // contact firstname
359 $html_contact_firstname = '';
360 $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>';
361 $html_contact_firstname .= '<input type="text" id="contact_firstname" name="contact_firstname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_firstname') ? GETPOST('contact_firstname', 'alphanohtml') : '') . '" />';
362 $html_contact_firstname .= '</td></tr>';
363 print $html_contact_firstname;
364 // company name
365 $html_company_name = '';
366 $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>';
367 $html_company_name .= '<input type="text" id="company_name" name="company_name" value="' . dol_escape_htmltag(GETPOSTISSET('company_name') ? GETPOST('company_name', 'alphanohtml') : '') . '" />';
368 $html_company_name .= '</td></tr>';
369 print $html_company_name;
370 // contact phone
371 $html_contact_phone = '';
372 $html_contact_phone .= '<tr id="contact_phone_line" class="contact_field"><td><label for="contact_phone"><span>' . $langs->trans('Phone') . '</span></label></td><td>';
373 $html_contact_phone .= '<input type="text" id="contact_phone" name="contact_phone" value="' . dol_escape_htmltag(GETPOSTISSET('contact_phone') ? GETPOST('contact_phone', 'alphanohtml') : '') . '" />';
374 $html_contact_phone .= '</td></tr>';
375 print $html_contact_phone;
376
377 // search contact form email
378 $langs->load('errors');
379 print '<script nonce="'.getNonce().'" type="text/javascript">
380 jQuery(document).ready(function() {
381 var contact = jQuery.parseJSON("'.dol_escape_js(json_encode($with_contact), 2).'");
382 jQuery("#contact_search_line").hide();
383 if (contact) {
384 if (contact.id > 0) {
385 jQuery("#contact_search_line").show();
386 jQuery("#contact_id").val(contact.id);
387 jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
388 jQuery(".contact_field").hide();
389 } else {
390 jQuery(".contact_field").show();
391 }
392 }
393
394 jQuery("#email").change(function() {
395 jQuery("#contact_search_line").show();
396 jQuery("#contact_search_result").html("'.dol_escape_js($langs->trans('Select2SearchInProgress')).'");
397 jQuery("#contact_id").val("");
398 jQuery("#contact_lastname").val("");
399 jQuery("#contact_firstname").val("");
400 jQuery("#company_name").val("");
401 jQuery("#contact_phone").val("");
402
403 jQuery.getJSON(
404 "'.dol_escape_js(dol_buildpath('/public/ticket/ajax/ajax.php', 1)).'",
405 {
406 action: "getContacts",
407 email: jQuery("#email").val()
408 },
409 function(response) {
410 if (response.error) {
411 jQuery("#contact_search_result").html("<span class=\"error\">"+response.error+"</span>");
412 } else {
413 var contact_list = response.contacts;
414 if (contact_list.length == 1) {
415 var contact = contact_list[0];
416 jQuery("#contact_id").val(contact.id);
417 jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
418 jQuery(".contact_field").hide();
419 } else if (contact_list.length <= 0) {
420 jQuery("#contact_search_line").hide();
421 jQuery(".contact_field").show();
422 }
423 }
424 }
425 ).fail(function(jqxhr, textStatus, error) {
426 var error_msg = "'.dol_escape_js($langs->trans('ErrorAjaxRequestFailed')).'"+" ["+textStatus+"] : "+error;
427 jQuery("#contact_search_result").html("<span class=\"error\">"+error_msg+"</span>");
428 });
429 });
430 });
431 </script>';
432 }
433 }
434
435 // If ticket created from another object
436 $subelement = '';
437 if (isset($this->param['origin']) && $this->param['originid'] > 0) {
438 // Parse element/subelement (ex: project_task)
439 $element = $subelement = $this->param['origin'];
440 $regs = array();
441 if (preg_match('/^([^_]+)_([^_]+)/i', $this->param['origin'], $regs)) {
442 $element = $regs[1];
443 $subelement = $regs[2];
444 }
445
446 dol_include_once('/'.$element.'/class/'.$subelement.'.class.php');
447 $classname = ucfirst($subelement);
448 $objectsrc = new $classname($this->db);
449 '@phan-var-force CommonObject $objectsrc';
450 $objectsrc->fetch(GETPOSTINT('originid'));
451
452 if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
453 $objectsrc->fetch_lines();
454 }
455
456 $objectsrc->fetch_thirdparty();
457 $newclassname = $classname;
458 print '<tr><td>'.$langs->trans($newclassname).'</td><td colspan="2"><input name="'.$subelement.'id" value="'.GETPOST('originid').'" type="hidden" />'.$objectsrc->getNomUrl(1).'</td></tr>';
459 }
460
461 // Type of Ticket
462 print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">'.$langs->trans("TicketTypeRequest").'</span></label></td><td>';
463 $this->selectTypesTickets($type_code, 'type_code', '', 2, 'ifone', 0, 0, 'minwidth200 maxwidth500');
464 print '</td></tr>';
465
466 // Group => Category
467 print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">'.$langs->trans("TicketCategory").'</span></label></td><td>';
468 $filter = '';
469 if ($public) {
470 $filter = '(public:=:1)';
471 }
472 $this->selectGroupTickets($category_code, 'category_code', $filter, 2, 'ifone', 0, 0, 'minwidth200 maxwidth500');
473 print '</td></tr>';
474
475 // Severity => Priority
476 print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">'.$langs->trans("TicketSeverity").'</span></label></td><td>';
477 $this->selectSeveritiesTickets($severity_code, 'severity_code', '', 2, 'ifone', 0, 0, 'minwidth200 maxwidth500');
478 print '</td></tr>';
479
480 if (isModEnabled('knowledgemanagement')) {
481 // KM Articles
482 print '<tr id="KWwithajax" class="hidden"><td></td></tr>';
483 print '<!-- Script to manage change of ticket group -->
484 <script nonce="'.getNonce().'">
485 jQuery(document).ready(function() {
486 function groupticketchange() {
487 console.log("We called groupticketchange, so we try to load list KM linked to event");
488 $("#KWwithajax").html("");
489 idgroupticket = $("#selectcategory_code").val();
490
491 console.log("We have selected id="+idgroupticket);
492
493 if (idgroupticket != "") {
494 $.ajax({ url: \''.DOL_URL_ROOT.'/core/ajax/fetchKnowledgeRecord.php\',
495 data: { action: \'getKnowledgeRecord\', idticketgroup: idgroupticket, token: \''.newToken().'\', lang:\''.$langs->defaultlang.'\', public:'.($public).' },
496 type: \'GET\',
497 success: function(response) {
498 var urllist = \'\';
499 console.log("We received response "+response);
500 if (typeof response == "object") {
501 console.log("response is already type object, no need to parse it");
502 } else {
503 console.log("response is type "+(typeof response));
504 response = JSON.parse(response);
505 }
506 for (key in response) {
507 answer = response[key].answer;
508 urllist += \'<li><a href="#" title="\'+response[key].title+\'" class="button_KMpopup" data-html="\'+answer+\'">\' +response[key].title+\'</a></li>\';
509 }
510 if (urllist != "") {
511 $("#KWwithajax").html(\'<td>'.$langs->trans("KMFoundForTicketGroup").'</td><td><ul>\'+urllist+\'</ul></td>\');
512 $("#KWwithajax").show();
513 $(".button_KMpopup").on("click",function(){
514 console.log("Open popup with jQuery(...).dialog() with KM article")
515 var $dialog = $("<div></div>").html($(this).attr("data-html"))
516 .dialog({
517 autoOpen: false,
518 modal: true,
519 height: (window.innerHeight - 150),
520 width: "80%",
521 title: $(this).attr("title"),
522 });
523 $dialog.dialog("open");
524 console.log($dialog);
525 })
526 }
527 },
528 error : function(output) {
529 console.error("Error on Fetch of KM articles");
530 },
531 });
532 }
533 };
534 $("#selectcategory_code").on("change",function() { groupticketchange(); });
535 if ($("#selectcategory_code").val() != "") {
536 groupticketchange();
537 }
538 });
539 </script>'."\n";
540 }
541
542 // Subject
543 if ($this->withtitletopic) {
544 print '<tr><td><label for="subject"><span class="fieldrequired">'.$langs->trans("Subject").'</span></label></td><td>';
545 // Answer to a ticket : display of the thread title in readonly
546 if ($this->withtopicreadonly) {
547 print $langs->trans('SubjectAnswerToTicket').' '.$this->topic_title;
548 } else {
549 if (isset($this->withreadid) && $this->withreadid > 0) {
550 $subject = $langs->trans('SubjectAnswerToTicket').' '.$this->withreadid.' : '.$this->topic_title;
551 }
552 print '<input class="text minwidth500" id="subject" name="subject" value="'.$subject.'"'.(empty($this->withemail) ? ' autofocus' : '').' />';
553 }
554 print '</td></tr>';
555 }
556
557 // Message
558 print '<tr><td><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span></label></td><td>';
559
560 // If public form, display more information
561 $toolbarname = 'dolibarr_notes';
562 if ($this->ispublic) {
563 $toolbarname = 'dolibarr_details'; // TODO Allow image so use can do paste of image into content but disallow file manager
564 print '<div class="warning hideonsmartphone">'.(getDolGlobalString("TICKET_PUBLIC_TEXT_HELP_MESSAGE", $langs->trans('TicketPublicPleaseBeAccuratelyDescribe'))).'</div>';
565 }
566 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
567 $uselocalbrowser = true;
568 $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_8, '90%');
569 $doleditor->Create();
570 print '</td></tr>';
571
572 // Categories
573 if (isModEnabled('category') && !$public) {
574 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
575 $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
576
577 if (count($cate_arbo)) {
578 // Categories
579 print '<tr><td class="wordbreak"></td><td>';
580 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0, '', '', $langs->transnoentitiesnoconv("Categories"));
581 print "</td></tr>";
582 }
583 }
584
585 // Attached files
586 if (!empty($this->withfile)) {
587 // Define list of attached files
588 $listofpaths = array();
589 $listofnames = array();
590 $listofmimes = array();
591 if (!empty($_SESSION["listofpaths"])) {
592 $listofpaths = explode(';', $_SESSION["listofpaths"]);
593 }
594
595 if (!empty($_SESSION["listofnames"])) {
596 $listofnames = explode(';', $_SESSION["listofnames"]);
597 }
598
599 if (!empty($_SESSION["listofmimes"])) {
600 $listofmimes = explode(';', $_SESSION["listofmimes"]);
601 }
602
603 $out = '<tr>';
604 $out .= '<td></td>';
605 $out .= '<td>';
606 // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
607 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
608 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
609 $out .= 'jQuery(document).ready(function () {';
610 $out .= ' jQuery(".removedfile").click(function() {';
611 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
612 $out .= ' });';
613 $out .= '})';
614 $out .= '</script>'."\n";
615 if (count($listofpaths)) {
616 foreach ($listofpaths as $key => $val) {
617 $out .= '<div id="attachfile_'.$key.'">';
618 $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
619 if (!$this->withfilereadonly) {
620 $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.'" />';
621 }
622 $out .= '<br></div>';
623 }
624 }
625 if ($this->withfile == 2) { // Can add other files
626 $maxfilesizearray = getMaxFileSizeArray();
627 $maxmin = $maxfilesizearray['maxmin'];
628 if ($maxmin > 0) {
629 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
630 }
631 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
632 $out .= ' ';
633 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="'.$langs->trans("MailingAddFile").'" />';
634 }
635 $out .= "</td></tr>\n";
636
637 print $out;
638 }
639
640 // User of creation
641 if ($this->withusercreate > 0 && $this->fk_user_create) {
642 print '<tr><td class="titlefield">'.$langs->trans("CreatedBy").'</td><td>';
643 $langs->load("users");
644 $fuser = new User($this->db);
645
646 if ($this->withcreatereadonly) {
647 if ($res = $fuser->fetch($this->fk_user_create)) {
648 print $fuser->getNomUrl(1);
649 }
650 }
651 print ' &nbsp; ';
652 print "</td></tr>\n";
653 }
654
655 // Customer or supplier
656 if ($this->withcompany) {
657 // force company and contact id for external user
658 if (empty($user->socid)) {
659 // Company
660 print '<tr><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
661 $events = array();
662 $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
663 print img_picto('', 'company', 'class="paddingright"');
664 print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, 0, $events, 0, 'minwidth200');
665 print '</td></tr>';
666 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
667 $htmlname = 'socid';
668 print '<script nonce="'.getNonce().'" type="text/javascript">
669 $(document).ready(function () {
670 jQuery("#'.$htmlname.'").change(function () {
671 var obj = '.json_encode($events).';
672 $.each(obj, function(key,values) {
673 if (values.method.length) {
674 runJsCodeForEvent'.$htmlname.'(values);
675 }
676 });
677 });
678
679 function runJsCodeForEvent'.$htmlname.'(obj) {
680 console.log("Run runJsCodeForEvent'.$htmlname.'");
681 var id = $("#'.$htmlname.'").val();
682 var method = obj.method;
683 var url = obj.url;
684 var htmlname = obj.htmlname;
685 var showempty = obj.showempty;
686 $.getJSON(url,
687 {
688 action: method,
689 id: id,
690 htmlname: htmlname,
691 showempty: showempty
692 },
693 function(response) {
694 $.each(obj.params, function(key,action) {
695 if (key.length) {
696 var num = response.num;
697 if (num > 0) {
698 $("#" + key).removeAttr(action);
699 } else {
700 $("#" + key).attr(action, action);
701 }
702 }
703 });
704 $("select#" + htmlname).html(response.value);
705 if (response.num) {
706 var selecthtml_str = response.value;
707 var selecthtml_dom=$.parseHTML(selecthtml_str);
708 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
709 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
710 }
711 } else {
712 $("#inputautocomplete"+htmlname).val("");
713 }
714 $("select#" + htmlname).change(); /* Trigger event change */
715 }
716 );
717 }
718 });
719 </script>';
720 }
721 if ($mode == 'create') {
722 // Contact and type
723 print '<tr><td>'.$langs->trans("Contact").'</td><td>';
724 // If no socid, set to -1 to avoid full contacts list
725 $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
726 print img_picto('', 'contact', 'class="paddingright"');
727 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
728 print $form->select_contact($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 1, 'maxwidth300 widthcentpercentminusx', true);
729
730 print ' ';
731 $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
732 print '</td></tr>';
733 }
734 } else {
735 print '<tr><td class="titlefield"><input type="hidden" name="socid" value="'.$user->socid.'"/></td>';
736 print '<td><input type="hidden" name="contactid" value="'.$user->contact_id.'"/></td>';
737 print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
738 }
739
740 // Notify thirdparty at creation
741 if (empty($this->ispublic) && $action == 'create') {
742 print '<tr><td><label for="notify_tiers_at_create">'.$langs->trans("TicketNotifyTiersAtCreation").'</label></td><td>';
743 print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate ? ' checked="checked"' : '').'>';
744 print '</td></tr>';
745 }
746
747 // User assigned
748 print '<tr><td>';
749 print $langs->trans("AssignedTo");
750 print '</td><td>';
751 print img_picto('', 'user', 'class="pictofixedwidth"');
752 print $form->select_dolusers($user_assign, 'fk_user_assign', 1);
753 print '</td>';
754 print '</tr>';
755 }
756
757 if ($subelement != 'project') {
758 if (isModEnabled('project') && !$this->ispublic) {
759 $formproject = new FormProjets($this->db);
760 print '<tr><td><label for="project"><span class="">'.$langs->trans("Project").'</span></label></td><td>';
761 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects(-1, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
762 print '</td></tr>';
763 }
764 }
765
766 if ($subelement != 'contract' && $subelement != 'contrat') {
767 if (isModEnabled('contract') && !$this->ispublic) {
768 $langs->load('contracts');
769 $formcontract = new FormContract($this->db);
770 print '<tr><td><label for="contract"><span class="">'.$langs->trans("Contract").'</span></label></td><td>';
771 print img_picto('', 'contract', 'class="pictofixedwidth"');
772 // socid is for internal users null and not 0 or -1
773 print $formcontract->select_contract($user->socid ?? -1, GETPOSTINT('contactid'), 'contractid', 0, 1, 1, 1);
774 print '</td></tr>';
775 }
776 }
777
778 // Other attributes
779 $parameters = array();
780 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
781 if (empty($reshook)) {
782 if ($mode == 'create') {
783 print $object->showOptionals($extrafields, 'create');
784 } else {
785 print $object->showOptionals($extrafields, 'edit');
786 }
787 }
788
789 // Show line with Captcha
790 $captcha = '';
791 if ($public && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET')) {
792 print '<tr><td class="titlefield"></td><td><br>';
793
794 require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
795 $captcha = getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_HANDLER', 'standard');
796
797 // List of directories where we can find captcha handlers
798 $dirModCaptcha = array_merge(array('main' => '/core/modules/security/captcha/'), is_array($conf->modules_parts['captcha']) ? $conf->modules_parts['captcha'] : array());
799
800 $fullpathclassfile = '';
801 foreach ($dirModCaptcha as $dir) {
802 $fullpathclassfile = dol_buildpath($dir."modCaptcha".ucfirst($captcha).'.class.php', 0, 2);
803 if ($fullpathclassfile) {
804 break;
805 }
806 }
807
808 if ($fullpathclassfile) {
809 include_once $fullpathclassfile;
810 $captchaobj = null;
811
812 // Charging the numbering class
813 $classname = "modCaptcha".ucfirst($captcha);
814 if (class_exists($classname)) {
816 $captchaobj = new $classname($this->db, $conf, $langs, $user);
817 '@phan-var-force ModeleCaptcha $captchaobj';
818
819 if (is_object($captchaobj) && method_exists($captchaobj, 'getCaptchaCodeForForm')) {
820 print $captchaobj->getCaptchaCodeForForm(''); // @phan-suppress-current-line PhanUndeclaredMethod
821 } else {
822 print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method getCaptchaCodeForForm()';
823 }
824 } else {
825 print 'Error, the captcha handler class '.$classname.' was not found after the include';
826 }
827 } else {
828 print 'Error, the captcha handler '.$captcha.' has no class file found modCaptcha'.ucfirst($captcha);
829 }
830
831 print '<br></td></tr>';
832 }
833
834 print '</table>';
835
836 if ($withdolfichehead) {
837 print dol_get_fiche_end();
838 }
839
840 print '<br>';
841
842 if ($mode == 'create') {
843 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "CreateTicket"), ($this->withcancel ? "Cancel" : ""));
844 } else {
845 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "Save"), ($this->withcancel ? "Cancel" : ""));
846 }
847
848 print '<br>';
849
850 /*
851 print '<div class="center">';
852 print '<input type="submit" class="button" name="add" value="'.$langs->trans(($this->withreadid > 0 ? "SendResponse" : "CreateTicket")).'" />';
853 if ($this->withcancel) {
854 print " &nbsp; &nbsp; &nbsp;";
855 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
856 }
857 print '</div>';
858 */
859
860 print '<input type="hidden" name="page_y">'."\n";
861
862 print "</form>\n";
863 print "<!-- End form TICKET -->\n";
864 }
865
880 public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $multiselect = 0)
881 {
882 global $langs, $user;
883
884 $selected = is_array($selected) ? $selected : (!empty($selected) ? explode(',', $selected) : array());
885 $ticketstat = new Ticket($this->db);
886
887 dol_syslog(get_class($this) . "::select_types_tickets " . implode(';', $selected) . ", " . $htmlname . ", " . $filtertype . ", " . $format . ", " . $multiselect, LOG_DEBUG);
888
889 $filterarray = array();
890
891 if ($filtertype != '' && $filtertype != '-1') {
892 $filterarray = explode(',', $filtertype);
893 }
894
895 $ticketstat->loadCacheTypesTickets();
896
897 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.($multiselect ? '[]' : '').'"'.($multiselect ? ' multiple' : '').'>';
898 if ($empty) {
899 print '<option value="">'.((is_numeric($empty) || $empty == 'ifone') ? '&nbsp;' : $empty).'</option>';
900 }
901
902 if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
903 foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
904 // On passe si on a demande de filtrer sur des modes de paiments particuliers
905 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
906 continue;
907 }
908
909 // If 'showempty' is enabled we discard empty line because an empty line has already been output.
910 if ($empty && empty($arraytypes['code'])) {
911 continue;
912 }
913
914 if ($format == 0) {
915 print '<option value="'.$id.'"';
916 }
917
918 if ($format == 1) {
919 print '<option value="'.$arraytypes['code'].'"';
920 }
921
922 if ($format == 2) {
923 print '<option value="'.$arraytypes['code'].'"';
924 }
925
926 if ($format == 3) {
927 print '<option value="'.$id.'"';
928 }
929
930 // If text is selected, we compare with code, otherwise with id
931 if (in_array($arraytypes['code'], $selected)) {
932 print ' selected="selected"';
933 } elseif (in_array($id, $selected)) {
934 print ' selected="selected"';
935 } elseif ($arraytypes['use_default'] == "1" && empty($selected)) {
936 print ' selected="selected"';
937 } elseif (count($ticketstat->cache_types_tickets) == 1 && (!$empty || $empty == 'ifone')) { // If only 1 choice, we autoselect it
938 print ' selected="selected"';
939 }
940
941 print '>';
942
943 $value = '&nbsp;';
944 if ($format == 0) {
945 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
946 } elseif ($format == 1) {
947 $value = $arraytypes['code'];
948 } elseif ($format == 2) {
949 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
950 } elseif ($format == 3) {
951 $value = $arraytypes['code'];
952 }
953
954 print $value ? $value : '&nbsp;';
955 print '</option>';
956 }
957 }
958 print '</select>';
959 if (isset($user->admin) && $user->admin && !$noadmininfo) {
960 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
961 }
962
963 print ajax_combobox('select'.$htmlname);
964 }
965
981 public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0, $outputlangs = null)
982 {
983 global $conf, $langs, $user;
984
985 dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
986
987 if (is_null($outputlangs) || !is_object($outputlangs)) {
988 $outputlangs = $langs;
989 }
990 $outputlangs->load("ticket");
991
992 $publicgroups = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
993
994 $ticketstat = new Ticket($this->db);
995 $ticketstat->loadCacheCategoriesTickets($publicgroups ? 1 : -1); // get list of active ticket groups
996
997 if ($use_multilevel <= 0) { // Only one combo list to select the group of ticket (default)
998 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
999 if ($empty) {
1000 print '<option value="">'.((is_numeric($empty) || $empty == 'ifone') ? '&nbsp;' : $empty).'</option>';
1001 }
1002
1003 if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
1004 foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
1005 // Exclude some record
1006 if ($publicgroups) {
1007 if (empty($arraycategories['public'])) {
1008 continue;
1009 }
1010 }
1011
1012 // We discard empty line if showempty is on because an empty line has already been output.
1013 if ($empty && empty($arraycategories['code'])) {
1014 continue;
1015 }
1016
1017 $label = ($arraycategories['label'] != '-' ? $arraycategories['label'] : '');
1018 if ($outputlangs->trans("TicketCategoryShort".$arraycategories['code']) != "TicketCategoryShort".$arraycategories['code']) {
1019 $label = $outputlangs->trans("TicketCategoryShort".$arraycategories['code']);
1020 } elseif ($outputlangs->trans($arraycategories['code']) != $arraycategories['code']) {
1021 $label = $outputlangs->trans($arraycategories['code']);
1022 }
1023
1024 if ($format == 0) {
1025 print '<option value="'.$id.'"';
1026 }
1027
1028 if ($format == 1) {
1029 print '<option value="'.$arraycategories['code'].'"';
1030 }
1031
1032 if ($format == 2) {
1033 print '<option value="'.$arraycategories['code'].'"';
1034 }
1035
1036 if ($format == 3) {
1037 print '<option value="'.$id.'"';
1038 }
1039
1040 // If selected is text, we compare with code, otherwise with id
1041 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
1042 print ' selected="selected"';
1043 } elseif (isset($selected) && $selected == $id) {
1044 print ' selected="selected"';
1045 } elseif ($arraycategories['use_default'] == "1" && empty($selected)) {
1046 print ' selected="selected"';
1047 } elseif (count($ticketstat->cache_category_tickets) == 1 && (!$empty || $empty == 'ifone')) { // If only 1 choice, we autoselect it
1048 print ' selected="selected"';
1049 }
1050
1051 print '>';
1052
1053 $value = '';
1054 if ($format == 0) {
1055 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
1056 }
1057
1058 if ($format == 1) {
1059 $value = $arraycategories['code'];
1060 }
1061
1062 if ($format == 2) {
1063 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
1064 }
1065
1066 if ($format == 3) {
1067 $value = $arraycategories['code'];
1068 }
1069
1070 print $value ? $value : '&nbsp;';
1071 print '</option>';
1072 }
1073 }
1074 print '</select>';
1075 if (isset($user->admin) && $user->admin && !$noadmininfo) {
1076 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1077 }
1078
1079 print ajax_combobox('select'.$htmlname);
1080 } elseif ($htmlname != '') { // complexe mode using selection of group using a combo for each level (when using a hierarchy of groups).
1081 $selectedgroups = array();
1082 $groupvalue = "";
1083 $groupticket = GETPOST($htmlname, 'aZ09');
1084 $child_id = GETPOST($htmlname.'_child_id', 'aZ09') ? GETPOST($htmlname.'_child_id', 'aZ09') : 0;
1085 if (!empty($groupticket)) {
1086 $tmpgroupticket = $groupticket;
1087 $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code";
1088 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'";
1089 $resql = $this->db->query($sql);
1090 if ($resql) {
1091 $obj = $this->db->fetch_object($resql);
1092 $selectedgroups[] = $obj->code;
1093 while ($obj->fk_parent > 0) {
1094 $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)."'";
1095 $resql = $this->db->query($sql);
1096 if ($resql) {
1097 $obj = $this->db->fetch_object($resql);
1098 $selectedgroups[] = $obj->code;
1099 }
1100 }
1101 }
1102 }
1103
1104 $arrayidused = array();
1105 $arrayidusedconcat = array();
1106 $arraycodenotparent = array();
1107 $arraycodenotparent[] = "";
1108
1109 $stringtoprint = '<span class="supportemailfield bold">'.$langs->trans("GroupOfTicket").'</span> ';
1110 $stringtoprint .= '<select id="'.$htmlname.'" class="minwidth500" child_id="0">';
1111 $stringtoprint .= '<option value="">&nbsp;</option>';
1112
1113 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ";
1114 $sql .= $this->db->ifsql("ctc.rowid NOT IN (SELECT ctcfather.rowid FROM ".MAIN_DB_PREFIX."c_ticket_category as ctcfather JOIN ".MAIN_DB_PREFIX."c_ticket_category as ctcjoin ON ctcfather.rowid = ctcjoin.fk_parent WHERE ctcjoin.active > 0)", "'NOTPARENT'", "'PARENT'")." as isparent";
1115 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1116 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1117 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1118 if ($public) {
1119 $sql .= " AND ctc.public = 1";
1120 }
1121 $sql .= " AND ctc.fk_parent = 0";
1122 $sql .= $this->db->order('ctc.pos', 'ASC');
1123
1124 $resql = $this->db->query($sql);
1125 if ($resql) {
1126 $num_rows_level0 = $this->db->num_rows($resql);
1127 $i = 0;
1128 while ($i < $num_rows_level0) {
1129 $obj = $this->db->fetch_object($resql);
1130 if ($obj) {
1131 $label = ($obj->label != '-' ? $obj->label : '');
1132 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1133 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1134 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1135 $label = $outputlangs->trans($obj->code);
1136 }
1137
1138 $grouprowid = $obj->rowid;
1139 $groupvalue = $obj->code;
1140 $grouplabel = $label;
1141
1142 $isparent = $obj->isparent;
1143 if (is_array($selectedgroups)) {
1144 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1145 } else {
1146 $iselected = $groupticket == $obj->code ? 'selected' : '';
1147 }
1148 $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>';
1149 if ($isparent == 'NOTPARENT') {
1150 $arraycodenotparent[] = $groupvalue;
1151 }
1152 $arrayidused[] = $grouprowid;
1153 $arrayidusedconcat[] = $grouprowid;
1154 }
1155 $i++;
1156 }
1157 } else {
1158 dol_print_error($this->db);
1159 }
1160 if (count($arrayidused) == 1) {
1161 return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
1162 } else {
1163 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400" value="'.GETPOST($htmlname).'">';
1164 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400" '.GETPOST($htmlname).' value="'.GETPOST($htmlname."_child_id").'">';
1165 }
1166 $stringtoprint .= '</select>&nbsp;';
1167
1168 $levelid = 1; // The first combobox
1169 while ($levelid <= $use_multilevel) { // Loop to take the child of the combo
1170 $tabscript = array();
1171 $stringtoprint .= '<select id="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
1172 $stringtoprint .= '<option value="">&nbsp;</option>';
1173
1174 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather";
1175 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1176 $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
1177 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1178 $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(implode(',', $arrayidusedconcat)).")";
1179
1180 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1181 if ($public) {
1182 $sql .= " AND ctc.public = 1";
1183 }
1184 // Add a test to take only record that are direct child
1185 if (!empty($arrayidused)) {
1186 $sql .= " AND ctc.fk_parent IN ( ";
1187 foreach ($arrayidused as $idused) {
1188 $sql .= $idused.", ";
1189 }
1190 $sql = substr($sql, 0, -2);
1191 $sql .= ")";
1192 }
1193 $sql .= $this->db->order('ctc.pos', 'ASC');
1194
1195 $resql = $this->db->query($sql);
1196 if ($resql) {
1197 $num_rows = $this->db->num_rows($resql);
1198 $i = 0;
1199 $arrayidused = array();
1200 while ($i < $num_rows) {
1201 $obj = $this->db->fetch_object($resql);
1202 if ($obj) {
1203 $label = ($obj->label != '-' ? $obj->label : '');
1204 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1205 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1206 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1207 $label = $outputlangs->trans($obj->code);
1208 }
1209
1210 $grouprowid = $obj->rowid;
1211 $groupvalue = $obj->code;
1212 $grouplabel = $label;
1213 $isparent = $obj->isparent;
1214 $fatherid = $obj->fk_parent;
1215 $arrayidused[] = $grouprowid;
1216 $arrayidusedconcat[] = $grouprowid;
1217 $groupcodefather = $obj->codefather;
1218 if ($isparent == 'NOTPARENT') {
1219 $arraycodenotparent[] = $groupvalue;
1220 }
1221 if (is_array($selectedgroups)) {
1222 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1223 } else {
1224 $iselected = $groupticket == $obj->code ? 'selected' : '';
1225 }
1226 $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>';
1227 if (empty($tabscript[$groupcodefather])) {
1228 $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val() == "'.dol_escape_js($groupcodefather).'"){
1229 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").show()
1230 console.log("We show child tickets of '.$groupcodefather.' group ticket")
1231 }else{
1232 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").hide()
1233 console.log("We hide child tickets of '.$groupcodefather.' group ticket")
1234 }';
1235 }
1236 }
1237 $i++;
1238 }
1239 } else {
1240 dol_print_error($this->db);
1241 }
1242 $stringtoprint .= '</select>';
1243
1244 $stringtoprint .= '<script nonce="'.getNonce().'">';
1245 $stringtoprint .= 'arraynotparents = '.json_encode($arraycodenotparent).';'; // when the last visible combo list is number x, this is the array of group
1246 $stringtoprint .= 'if (arraynotparents.includes($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val())){
1247 console.log("'.$htmlname.'_child_'.$levelid.'")
1248 if($("#'.$htmlname.'_child_'.$levelid.'").val() == "" && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")>'.$child_id.')){
1249 $("#'.$htmlname.'_child_'.$levelid.'").hide();
1250 console.log("We hide '.$htmlname.'_child_'.$levelid.' input")
1251 }
1252 if(arraynotparents.includes("'.$groupticket.'") && '.$child_id.' == 0){
1253 $("#ticketcategory_select_child_id").val($("#'.$htmlname.'").attr("child_id"))
1254 $("#ticketcategory_select").val($("#'.$htmlname.'").val()) ;
1255 console.log("We choose '.$htmlname.' input and reload hidden input");
1256 }
1257 }
1258 $("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").change(function() {
1259 child_id = $("#'.$htmlname.($levelid > 1 ? '_child_'.$levelid : '').'").attr("child_id");
1260
1261 /* Change of value to select this value*/
1262 if (arraynotparents.includes($(this).val()) || $(this).attr("child_id") == '.$use_multilevel.') {
1263 $("#ticketcategory_select").val($(this).val());
1264 $("#ticketcategory_select_child_id").val($(this).attr("child_id")) ;
1265 console.log("We choose to select "+ $(this).val());
1266 }else{
1267 if ($("#'.$htmlname.'_child_'.$levelid.' option").length <= 1) {
1268 $("#ticketcategory_select").val($(this).val());
1269 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1270 console.log("We choose to select "+ $(this).val() + " and next combo has no item, so we keep this selection");
1271 } else {
1272 console.log("We choose to select "+ $(this).val() + " but next combo has some item, so we clean selected item");
1273 $("#ticketcategory_select").val("");
1274 $("#ticketcategory_select_child_id").val("");
1275 }
1276 }
1277
1278 console.log("We select a new value into combo child_id="+child_id);
1279
1280 // Hide all selected box that are child of the one modified
1281 $(".groupticketchild").each(function(){
1282 if ($(this).attr("child_id") > child_id) {
1283 console.log("hide child_id="+$(this).attr("child_id"));
1284 $(this).val("");
1285 $(this).hide();
1286 }
1287 })
1288
1289 // Now we enable the next combo
1290 $("#'.$htmlname.'_child_'.$levelid.'").val("");
1291 if (!arraynotparents.includes($(this).val()) && $("#'.$htmlname.'_child_'.$levelid.' option").length > 1) {
1292 console.log($("#'.$htmlname.'_child_'.$levelid.' option").length);
1293 $("#'.$htmlname.'_child_'.$levelid.'").show()
1294 } else {
1295 $("#'.$htmlname.'_child_'.$levelid.'").hide()
1296 }
1297 ';
1298 $levelid++;
1299 foreach ($tabscript as $script) {
1300 $stringtoprint .= $script;
1301 }
1302 $stringtoprint .= '})';
1303 $stringtoprint .= '</script>';
1304 }
1305 $stringtoprint .= '<script nonce="'.getNonce().'">';
1306 $stringtoprint .= '$("#'.$htmlname.'_child_'.$use_multilevel.'").change(function() {
1307 $("#ticketcategory_select").val($(this).val());
1308 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1309 tmpvalselect = $("#ticketcategory_select").val();
1310 if(tmpvalselect == "" && $("#ticketcategory_select_child_id").val() >= 1){
1311 $("#ticketcategory_select_child_id").val($(this).attr("child_id")-1);
1312 }
1313 console.log($("#ticketcategory_select").val());
1314 })';
1315 $stringtoprint .= '</script>';
1316 $stringtoprint .= ajax_combobox($htmlname);
1317
1318 return $stringtoprint;
1319 }
1320 }
1321
1335 public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
1336 {
1337 global $conf, $langs, $user;
1338
1339 $ticketstat = new Ticket($this->db);
1340
1341 dol_syslog(get_class($this)."::selectSeveritiesTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
1342
1343 $filterarray = array();
1344
1345 if ($filtertype != '' && $filtertype != '-1') {
1346 $filterarray = explode(',', $filtertype);
1347 }
1348
1349 $ticketstat->loadCacheSeveritiesTickets();
1350
1351 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
1352 if ($empty) {
1353 print '<option value="">'.((is_numeric($empty) || $empty == 'ifone') ? '&nbsp;' : $empty).'</option>';
1354 }
1355
1356 if (is_array($conf->cache['severity_tickets']) && count($conf->cache['severity_tickets'])) {
1357 foreach ($conf->cache['severity_tickets'] as $id => $arrayseverities) {
1358 // On passe si on a demande de filtrer sur des modes de paiments particuliers
1359 if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
1360 continue;
1361 }
1362
1363 // We discard empty line if showempty is on because an empty line has already been output.
1364 if ($empty && empty($arrayseverities['code'])) {
1365 continue;
1366 }
1367
1368 if ($format == 0) {
1369 print '<option value="'.$id.'"';
1370 }
1371
1372 if ($format == 1) {
1373 print '<option value="'.$arrayseverities['code'].'"';
1374 }
1375
1376 if ($format == 2) {
1377 print '<option value="'.$arrayseverities['code'].'"';
1378 }
1379
1380 if ($format == 3) {
1381 print '<option value="'.$id.'"';
1382 }
1383
1384 // If text is selected, we compare with code, otherwise with id
1385 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
1386 print ' selected="selected"';
1387 } elseif (isset($selected) && $selected == $id) {
1388 print ' selected="selected"';
1389 } elseif ($arrayseverities['use_default'] == "1" && empty($selected)) {
1390 print ' selected="selected"';
1391 } elseif (count($conf->cache['severity_tickets']) == 1 && (!$empty || $empty == 'ifone')) { // If only 1 choice, we autoselect it
1392 print ' selected="selected"';
1393 }
1394
1395 print '>';
1396
1397 $value = '';
1398 if ($format == 0) {
1399 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1400 }
1401
1402 if ($format == 1) {
1403 $value = $arrayseverities['code'];
1404 }
1405
1406 if ($format == 2) {
1407 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1408 }
1409
1410 if ($format == 3) {
1411 $value = $arrayseverities['code'];
1412 }
1413
1414 print $value ? $value : '&nbsp;';
1415 print '</option>';
1416 }
1417 }
1418 print '</select>';
1419 if (isset($user->admin) && $user->admin && !$noadmininfo) {
1420 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1421 }
1422
1423 print ajax_combobox('select'.$htmlname);
1424 }
1425
1426 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1432 public function clear_attached_files()
1433 {
1434 // phpcs:enable
1435 global $conf, $user;
1436 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1437
1438 // Set tmp user directory
1439 $vardir = $conf->user->dir_output."/".$user->id;
1440 $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
1441 if (is_dir($upload_dir)) {
1442 dol_delete_dir_recursive($upload_dir);
1443 }
1444
1445 if (!empty($this->trackid)) { // TODO Always use trackid (ticXXX) instead of track_id (abcd123)
1446 $keytoavoidconflict = '-'.$this->trackid;
1447 } else {
1448 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id;
1449 }
1450 unset($_SESSION["listofpaths".$keytoavoidconflict]);
1451 unset($_SESSION["listofnames".$keytoavoidconflict]);
1452 unset($_SESSION["listofmimes".$keytoavoidconflict]);
1453 }
1454
1461 public function showMessageForm($width = '40%')
1462 {
1463 global $conf, $langs, $user, $hookmanager, $form, $mysoc;
1464
1465 $formmail = new FormMail($this->db);
1466 $addfileaction = 'addfile';
1467
1468 if (!is_object($form)) {
1469 $form = new Form($this->db);
1470 }
1471
1472 // Load translation files required by the page
1473 $langs->loadLangs(array('other', 'mails', 'ticket'));
1474
1475 // Clear temp files. Must be done at beginning, before call of triggers
1476 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1477 $this->clear_attached_files();
1478 }
1479
1480 // Define output language
1481 $outputlangs = $langs;
1482 $newlang = '';
1483 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1484 $newlang = $this->param['langsmodels'];
1485 }
1486 if (!empty($newlang)) {
1487 $outputlangs = new Translate("", $conf);
1488 $outputlangs->setDefaultLang($newlang);
1489 $outputlangs->load('other');
1490 }
1491
1492 // Get message template for $this->param["models"] into c_email_templates
1493 $arraydefaultmessage = -1;
1494 if (isset($this->param['models']) && $this->param['models'] != 'none') {
1495 $model_id = 0;
1496 if (array_key_exists('models_id', $this->param)) {
1497 $model_id = (int) $this->param["models_id"];
1498 }
1499
1500 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
1501 }
1502
1503 // Define list of attached files
1504 $listofpaths = array();
1505 $listofnames = array();
1506 $listofmimes = array();
1507
1508 if (!empty($this->trackid)) {
1509 $keytoavoidconflict = '-'.$this->trackid;
1510 } else {
1511 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1512 }
1513 //var_dump($keytoavoidconflict);
1514 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1515 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
1516 foreach ($this->param['fileinit'] as $path) {
1517 $formmail->add_attached_files($path, basename($path), dol_mimetype($path));
1518 }
1519 }
1520 }
1521 //var_dump($_SESSION);
1522 //var_dump($_SESSION["listofpaths".$keytoavoidconflict]);
1523 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
1524 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
1525 }
1526 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
1527 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
1528 }
1529 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
1530 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
1531 }
1532
1533 // Define output language
1534 $outputlangs = $langs;
1535 $newlang = '';
1536 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1537 $newlang = $this->param['langsmodels'];
1538 }
1539 if (!empty($newlang)) {
1540 $outputlangs = new Translate("", $conf);
1541 $outputlangs->setDefaultLang($newlang);
1542 $outputlangs->load('other');
1543 }
1544
1545 print "\n<!-- Begin message_form TICKET -->\n";
1546
1547 $send_email = GETPOSTINT('send_email') ? GETPOSTINT('send_email') : 0;
1548
1549 // Example 1 : Adding jquery code
1550 print '<script nonce="'.getNonce().'" type="text/javascript">
1551 jQuery(document).ready(function() {
1552 send_email=' . $send_email.';
1553 if (send_email) {
1554 if (!jQuery("#send_msg_email").is(":checked")) {
1555 jQuery("#send_msg_email").prop("checked", true).trigger("change");
1556 }
1557 jQuery(".email_line").show();
1558 } else {
1559 if (!jQuery("#private_message").is(":checked")) {
1560 jQuery("#private_message").prop("checked", true).trigger("change");
1561 }
1562 jQuery(".email_line").hide();
1563 }
1564 ';
1565
1566 // If constant set, allow to send private messages as email
1567 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1568 print 'jQuery("#send_msg_email").click(function() {
1569 console.log("Click send_msg_email");
1570 if(jQuery(this).is(":checked")) {
1571 if (jQuery("#private_message").is(":checked")) {
1572 jQuery("#private_message").prop("checked", false).trigger("change");
1573 }
1574 jQuery(".email_line").show();
1575 }
1576 else {
1577 jQuery(".email_line").hide();
1578 }
1579 });
1580
1581 jQuery("#private_message").click(function() {
1582 console.log("Click private_message");
1583 if (jQuery(this).is(":checked")) {
1584 if (jQuery("#send_msg_email").is(":checked")) {
1585 jQuery("#send_msg_email").prop("checked", false).trigger("change");
1586 }
1587 jQuery(".email_line").hide();
1588 }
1589 });';
1590 }
1591
1592 print '});
1593 </script>';
1594
1595
1596 print '<form method="post" name="ticket" id="ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
1597 print '<input type="hidden" name="token" value="'.newToken().'">';
1598 print '<input type="hidden" name="action" value="'.$this->action.'">';
1599 print '<input type="hidden" name="actionbis" value="add_message">';
1600 print '<input type="hidden" name="backtopage" value="'.$this->backtopage.'">';
1601 if (!empty($this->trackid)) {
1602 print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
1603 } else {
1604 print '<input type="hidden" name="trackid" value="'.(empty($this->track_id) ? '' : $this->track_id).'">';
1605 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1606 }
1607 foreach ($this->param as $key => $value) {
1608 print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
1609 }
1610
1611 // Get message template
1612 $model_id = 0;
1613 if (array_key_exists('models_id', $this->param)) {
1614 $model_id = $this->param["models_id"];
1615 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
1616 }
1617
1618 $result = $formmail->fetchAllEMailTemplate(!empty($this->param["models"]) ? $this->param["models"] : "", $user, $outputlangs);
1619 if ($result < 0) {
1620 setEventMessages($this->error, $this->errors, 'errors');
1621 }
1622 $modelmail_array = array();
1623 foreach ($formmail->lines_model as $line) {
1624 $modelmail_array[$line->id] = $line->label;
1625 }
1626
1627 print '<table class="border" width="'.$width.'">';
1628
1629 // External users can't send message email
1630 if ($user->hasRight("ticket", "write") && !$user->socid) {
1631 $ticketstat = new Ticket($this->db);
1632 $res = $ticketstat->fetch(0, '', $this->track_id);
1633
1634 print '<tr><td></td><td>';
1635 $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : (getDolGlobalInt('TICKETS_MESSAGE_FORCE_MAIL') ? 'checked' : ''));
1636 print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
1637 print '<label for="send_msg_email">'.$langs->trans('SendMessageByEmail').'</label>';
1638 $texttooltip = $langs->trans("TicketMessageSendEmailHelp");
1639 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1640 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2b");
1641 } else {
1642 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2a", '{s1}');
1643 }
1644 $texttooltip = str_replace('{s1}', $langs->trans('MarkMessageAsPrivate'), $texttooltip);
1645 print ' '.$form->textwithpicto('', $texttooltip, 1, 'help');
1646 print '</td></tr>';
1647
1648 // Private message (not visible by customer/external user)
1649 if (!$user->socid) {
1650 print '<tr><td></td><td>';
1651 $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : '');
1652 print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
1653 print '<label for="private_message">'.$langs->trans('MarkMessageAsPrivate').'</label>';
1654 print ' '.$form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
1655 print '</td></tr>';
1656 }
1657
1658 // Zone to select its email template
1659 if (count($modelmail_array) > 0) {
1660 print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
1661 print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, 0, "", 0, 0, 0, '', 'minwidth200');
1662 if ($user->admin) {
1663 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1664 }
1665 print ' &nbsp; ';
1666 print '<input type="submit" class="button" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
1667 print '</div></td>';
1668 }
1669
1670 // From
1671 $from = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM');
1672 print '<tr class="email_line"><td><span class="">'.$langs->trans("MailFrom").'</span></td>';
1673 print '<td><span class="">'.img_picto('', 'email', 'class="pictofixedwidth"').$from.'</span></td></tr>';
1674
1675 // Subject/topic
1676 $topic = "";
1677 foreach ($formmail->lines_model as $line) {
1678 if (!empty($this->substit) && $this->param['models_id'] == $line->id) {
1679 $topic = make_substitutions($line->topic, $this->substit);
1680 break;
1681 }
1682 }
1683 print '<tr class="email_line"><td>'.$langs->trans('Subject').'</td>';
1684 if (empty($topic)) {
1685 print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '. $ticketstat->subject .'" />';
1686 } else {
1687 print '<td><input type="text" class="text minwidth500" name="subject" value="'.make_substitutions($topic, $this->substit).'" />';
1688 }
1689 print '</td></tr>';
1690
1691 // Recipients / adressed-to
1692 print '<tr class="email_line"><td>'.$langs->trans('MailRecipients');
1693 print ' '.$form->textwithpicto('', $langs->trans("TicketMessageRecipientsHelp"), 1, 'help');
1694 print '</td><td>';
1695 if ($res) {
1696 // Retrieve email of all contacts (internal and external)
1697 $contacts = $ticketstat->getInfosTicketInternalContact(1);
1698 $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact(1));
1699
1700 $sendto = array();
1701
1702 // Build array to display recipient list
1703 if (is_array($contacts) && count($contacts) > 0) {
1704 foreach ($contacts as $key => $info_sendto) {
1705 if ($info_sendto['email'] != '') {
1706 $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">").' <small class="opacitymedium">('.dol_escape_htmltag($info_sendto['libelle']).")</small>";
1707 }
1708 }
1709 }
1710
1711 if (!empty($ticketstat->origin_replyto) && !in_array($ticketstat->origin_replyto, $sendto)) {
1712 $sendto[] = dol_escape_htmltag($ticketstat->origin_replyto).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1713 } elseif ($ticketstat->origin_email && !in_array($ticketstat->origin_email, $sendto)) {
1714 $sendto[] = dol_escape_htmltag($ticketstat->origin_email).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1715 }
1716
1717 if ($ticketstat->fk_soc > 0) {
1718 $ticketstat->socid = $ticketstat->fk_soc;
1719 $ticketstat->fetch_thirdparty();
1720
1721 if (!empty($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
1722 $sendto[] = $ticketstat->thirdparty->email.' <small class="opacitymedium">('.$langs->trans('Customer').')</small>';
1723 }
1724 }
1725
1726 if (getDolGlobalInt('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS')) {
1727 $sendto[] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO').' <small class="opacitymedium">(generic email)</small>';
1728 }
1729
1730 // Print recipient list
1731 if (is_array($sendto) && count($sendto) > 0) {
1732 print img_picto('', 'email', 'class="pictofixedwidth"');
1733 print implode(', ', $sendto);
1734 } else {
1735 print '<div class="warning">'.$langs->trans('WarningNoEMailsAdded').' '.$langs->trans('TicketGoIntoContactTab').'</div>';
1736 }
1737 }
1738 print '</td></tr>';
1739 }
1740
1741 $uselocalbrowser = false;
1742
1743 // Intro
1744 // External users can't send message email
1745 /*
1746 if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_INTRO)) {
1747 $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
1748 print '<tr class="email_line"><td><label for="mail_intro">';
1749 print $form->textwithpicto($langs->trans("TicketMessageMailIntro"), $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
1750 print '</label>';
1751
1752 print '</td><td>';
1753 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1754
1755 $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_2, 70);
1756
1757 $doleditor->Create();
1758 print '</td></tr>';
1759 }
1760 */
1761
1762 // Attached files
1763 if (!empty($this->withfile)) {
1764 $out = '<tr>';
1765 $out .= '<td>'.$langs->trans("MailFile").'</td>';
1766 $out .= '<td>';
1767 // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
1768 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
1769 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1770 $out .= 'jQuery(document).ready(function () {';
1771 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1772 $out .= ' jQuery("#addedfile").on("change", function() {';
1773 $out .= ' if (jQuery(this).val().length) {';
1774 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", false);';
1775 $out .= ' } else {';
1776 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1777 $out .= ' }';
1778 $out .= ' });';
1779 $out .= ' jQuery(".removedfile").click(function() {';
1780 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
1781 $out .= ' });';
1782 $out .= '})';
1783 $out .= '</script>'."\n";
1784
1785 if (count($listofpaths)) {
1786 foreach ($listofpaths as $key => $val) {
1787 $out .= '<div id="attachfile_'.$key.'">';
1788 $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
1789 if (!$this->withfilereadonly) {
1790 $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.'" />';
1791 }
1792 $out .= '<br></div>';
1793 }
1794 } else {
1795 //$out .= $langs->trans("NoAttachedFiles").'<br>';
1796 }
1797 if ($this->withfile == 2) { // Can add other files
1798 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
1799 $out .= ' ';
1800 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
1801 }
1802 $out .= "</td></tr>\n";
1803
1804 print $out;
1805 }
1806
1807 // MESSAGE
1808
1809 $defaultmessage = "";
1810 if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
1811 $defaultmessage = $arraydefaultmessage->content;
1812 }
1813 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1814
1815 // Deal with format differences between message and signature (text / HTML)
1816 if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1817 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1818 } elseif (!dol_textishtml($defaultmessage) && isset($this->substit['__USER_SIGNATURE__']) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1819 $defaultmessage = dol_nl2br($defaultmessage);
1820 }
1821 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1822 $defaultmessage = GETPOST('message', 'restricthtml');
1823 } else {
1824 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1825 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1826 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1827 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1828 }
1829
1830 print '<tr><td colspan="2"><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span>';
1831 if ($user->hasRight("ticket", "write") && !$user->socid) {
1832 $texttooltip = $langs->trans("TicketMessageHelp");
1833 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO') || getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1834 $texttooltip .= '<br><br>'.$langs->trans("ForEmailMessageWillBeCompletedWith").'...';
1835 }
1836 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO')) {
1837 $mail_intro = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO'), $this->substit);
1838 print '<input type="hidden" name="mail_intro" value="'.$mail_intro.'">';
1839 $texttooltip .= '<br><u>'.$langs->trans("TicketMessageMailIntro").'</u><br>'.$mail_intro;
1840 }
1841 if (getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1842 $mail_signature = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE'), $this->substit);
1843 print '<input type="hidden" name="mail_signature" value="'.$mail_signature.'">';
1844 $texttooltip .= '<br><br><u>'.$langs->trans("TicketMessageMailFooter").'</u><br>'.$mail_signature;
1845 }
1846 print $form->textwithpicto('', $texttooltip, 1, 'help');
1847 }
1848 print '</label></td></tr>';
1849
1850
1851 print '<tr><td colspan="2">';
1852 //$toolbarname = 'dolibarr_details';
1853 $toolbarname = 'dolibarr_notes';
1854 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1855 $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_5, '90%');
1856 $doleditor->Create();
1857 print '</td></tr>';
1858
1859 // Footer
1860 // External users can't send message email
1861 /*if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_SIGNATURE)) {
1862 $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
1863 print '<tr class="email_line"><td><label for="mail_intro">'.$langs->trans("TicketMessageMailFooter").'</label>';
1864 print $form->textwithpicto('', $langs->trans("TicketMessageMailFooterHelp"), 1, 'help');
1865 print '</td><td>';
1866 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1867 $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_2, 70);
1868 $doleditor->Create();
1869 print '</td></tr>';
1870 }
1871 */
1872
1873 print '</table>';
1874
1875 print '<br><center>';
1876 print '<input type="submit" class="button" name="btn_add_message" value="'.$langs->trans("Add").'"';
1877 // Add a javascript test to avoid to forget to submit file before sending email
1878 if ($this->withfile == 2 && !empty($conf->use_javascript_ajax)) {
1879 print ' onClick="if (document.ticket.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1880 }
1881 print ' />';
1882 if (!empty($this->withcancel)) {
1883 print " &nbsp; &nbsp; ";
1884 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
1885 }
1886 print "</center>\n";
1887
1888 print '<input type="hidden" name="page_y">'."\n";
1889
1890 print "</form><br>\n";
1891
1892 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1893 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1894 print '<script type="text/javascript">';
1895 print 'jQuery(document).ready(function () {';
1896 print ' $(document).on("keypress", \'#ticket\', function (e) { /* Note this is called at every key pressed ! */
1897 var code = e.keyCode || e.which;
1898 if (code == 13) {
1899 console.log("Enter was intercepted and blocked");
1900 e.preventDefault();
1901 return false;
1902 }
1903 });';
1904 print '})';
1905 print '</script>';
1906 }
1907
1908 print "<!-- End form TICKET -->\n";
1909 }
1910}
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
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:459
$object ref
Definition info.php:89
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 for contract module.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
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 analytic codes.
selectSeveritiesTickets($selected='', $htmlname='ticketseverity', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $morecss='')
Return html list of ticket severitys (priorities)
static checkRequiredFields(array $fields, int &$errors)
Check required fields.
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.
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.
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)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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_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.
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
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.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
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...
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
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:149
getMaxFileSizeArray()
Return the max allowed for file upload.