dolibarr 21.0.0-alpha
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, 1, 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, 1, 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, 1, 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 if ($public && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET')) {
573 require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
574 print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">'.$langs->trans("SecurityCode").'</span></label></td><td>';
575 print '<span class="span-icon-security inline-block">';
576 print '<input id="securitycode" placeholder="'.$langs->trans("SecurityCode").'" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" />';
577 print '</span>';
578 print '<span class="nowrap inline-block">';
579 print '<img class="inline-block valignmiddle" src="'.DOL_URL_ROOT.'/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />';
580 print '<a class="inline-block valignmiddle" href="" tabindex="4" data-role="button">'.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'</a>';
581 print '</span>';
582 print '</td></tr>';
583 }
584
585 // Categories
586 if (isModEnabled('category') && !$public) {
587 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
588 $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
589
590 if (count($cate_arbo)) {
591 // Categories
592 print '<tr><td class="wordbreak"></td><td>';
593 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0, '', '', $langs->transnoentitiesnoconv("Categories"));
594 print "</td></tr>";
595 }
596 }
597
598 // Attached files
599 if (!empty($this->withfile)) {
600 // Define list of attached files
601 $listofpaths = array();
602 $listofnames = array();
603 $listofmimes = array();
604 if (!empty($_SESSION["listofpaths"])) {
605 $listofpaths = explode(';', $_SESSION["listofpaths"]);
606 }
607
608 if (!empty($_SESSION["listofnames"])) {
609 $listofnames = explode(';', $_SESSION["listofnames"]);
610 }
611
612 if (!empty($_SESSION["listofmimes"])) {
613 $listofmimes = explode(';', $_SESSION["listofmimes"]);
614 }
615
616 $out = '<tr>';
617 $out .= '<td></td>';
618 $out .= '<td>';
619 // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
620 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
621 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
622 $out .= 'jQuery(document).ready(function () {';
623 $out .= ' jQuery(".removedfile").click(function() {';
624 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
625 $out .= ' });';
626 $out .= '})';
627 $out .= '</script>'."\n";
628 if (count($listofpaths)) {
629 foreach ($listofpaths as $key => $val) {
630 $out .= '<div id="attachfile_'.$key.'">';
631 $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
632 if (!$this->withfilereadonly) {
633 $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.'" />';
634 }
635 $out .= '<br></div>';
636 }
637 }
638 if ($this->withfile == 2) { // Can add other files
639 $maxfilesizearray = getMaxFileSizeArray();
640 $maxmin = $maxfilesizearray['maxmin'];
641 if ($maxmin > 0) {
642 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
643 }
644 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
645 $out .= ' ';
646 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="'.$langs->trans("MailingAddFile").'" />';
647 }
648 $out .= "</td></tr>\n";
649
650 print $out;
651 }
652
653 // User of creation
654 if ($this->withusercreate > 0 && $this->fk_user_create) {
655 print '<tr><td class="titlefield">'.$langs->trans("CreatedBy").'</td><td>';
656 $langs->load("users");
657 $fuser = new User($this->db);
658
659 if ($this->withcreatereadonly) {
660 if ($res = $fuser->fetch($this->fk_user_create)) {
661 print $fuser->getNomUrl(1);
662 }
663 }
664 print ' &nbsp; ';
665 print "</td></tr>\n";
666 }
667
668 // Customer or supplier
669 if ($this->withcompany) {
670 // force company and contact id for external user
671 if (empty($user->socid)) {
672 // Company
673 print '<tr><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
674 $events = array();
675 $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
676 print img_picto('', 'company', 'class="paddingright"');
677 print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, 0, $events, 0, 'minwidth200');
678 print '</td></tr>';
679 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
680 $htmlname = 'socid';
681 print '<script nonce="'.getNonce().'" type="text/javascript">
682 $(document).ready(function () {
683 jQuery("#'.$htmlname.'").change(function () {
684 var obj = '.json_encode($events).';
685 $.each(obj, function(key,values) {
686 if (values.method.length) {
687 runJsCodeForEvent'.$htmlname.'(values);
688 }
689 });
690 });
691
692 function runJsCodeForEvent'.$htmlname.'(obj) {
693 console.log("Run runJsCodeForEvent'.$htmlname.'");
694 var id = $("#'.$htmlname.'").val();
695 var method = obj.method;
696 var url = obj.url;
697 var htmlname = obj.htmlname;
698 var showempty = obj.showempty;
699 $.getJSON(url,
700 {
701 action: method,
702 id: id,
703 htmlname: htmlname,
704 showempty: showempty
705 },
706 function(response) {
707 $.each(obj.params, function(key,action) {
708 if (key.length) {
709 var num = response.num;
710 if (num > 0) {
711 $("#" + key).removeAttr(action);
712 } else {
713 $("#" + key).attr(action, action);
714 }
715 }
716 });
717 $("select#" + htmlname).html(response.value);
718 if (response.num) {
719 var selecthtml_str = response.value;
720 var selecthtml_dom=$.parseHTML(selecthtml_str);
721 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
722 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
723 }
724 } else {
725 $("#inputautocomplete"+htmlname).val("");
726 }
727 $("select#" + htmlname).change(); /* Trigger event change */
728 }
729 );
730 }
731 });
732 </script>';
733 }
734 if ($mode == 'create') {
735 // Contact and type
736 print '<tr><td>'.$langs->trans("Contact").'</td><td>';
737 // If no socid, set to -1 to avoid full contacts list
738 $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
739 print img_picto('', 'contact', 'class="paddingright"');
740 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
741 print $form->select_contact($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 1, 'maxwidth300 widthcentpercentminusx', true);
742
743 print ' ';
744 $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
745 print '</td></tr>';
746 }
747 } else {
748 print '<tr><td class="titlefield"><input type="hidden" name="socid" value="'.$user->socid.'"/></td>';
749 print '<td><input type="hidden" name="contactid" value="'.$user->contact_id.'"/></td>';
750 print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
751 }
752
753 // Notify thirdparty at creation
754 if (empty($this->ispublic) && $action == 'create') {
755 print '<tr><td><label for="notify_tiers_at_create">'.$langs->trans("TicketNotifyTiersAtCreation").'</label></td><td>';
756 print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate ? ' checked="checked"' : '').'>';
757 print '</td></tr>';
758 }
759
760 // User assigned
761 print '<tr><td>';
762 print $langs->trans("AssignedTo");
763 print '</td><td>';
764 print img_picto('', 'user', 'class="pictofixedwidth"');
765 print $form->select_dolusers($user_assign, 'fk_user_assign', 1);
766 print '</td>';
767 print '</tr>';
768 }
769
770 if ($subelement != 'project') {
771 if (isModEnabled('project') && !$this->ispublic) {
772 $formproject = new FormProjets($this->db);
773 print '<tr><td><label for="project"><span class="">'.$langs->trans("Project").'</span></label></td><td>';
774 print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects(-1, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
775 print '</td></tr>';
776 }
777 }
778
779 if ($subelement != 'contract' && $subelement != 'contrat') {
780 if (isModEnabled('contract') && !$this->ispublic) {
781 $langs->load('contracts');
782 $formcontract = new FormContract($this->db);
783 print '<tr><td><label for="contract"><span class="">'.$langs->trans("Contract").'</span></label></td><td>';
784 print img_picto('', 'contract', 'class="pictofixedwidth"');
785 print $formcontract->select_contract(-1, GETPOSTINT('contactid'), 'contractid', 0, 1, 1, 1);
786 print '</td></tr>';
787 }
788 }
789
790 // Other attributes
791 $parameters = array();
792 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
793 if (empty($reshook)) {
794 if ($mode == 'create') {
795 print $object->showOptionals($extrafields, 'create');
796 } else {
797 print $object->showOptionals($extrafields, 'edit');
798 }
799 }
800
801 print '</table>';
802
803 if ($withdolfichehead) {
804 print dol_get_fiche_end();
805 }
806
807 if ($mode == 'create') {
808 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "CreateTicket"), ($this->withcancel ? "Cancel" : ""));
809 } else {
810 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "Save"), ($this->withcancel ? "Cancel" : ""));
811 }
812
813 print '<br>';
814
815 /*
816 print '<div class="center">';
817 print '<input type="submit" class="button" name="add" value="'.$langs->trans(($this->withreadid > 0 ? "SendResponse" : "CreateTicket")).'" />';
818 if ($this->withcancel) {
819 print " &nbsp; &nbsp; &nbsp;";
820 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
821 }
822 print '</div>';
823 */
824
825 print '<input type="hidden" name="page_y">'."\n";
826
827 print "</form>\n";
828 print "<!-- End form TICKET -->\n";
829 }
830
845 public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $multiselect = 0)
846 {
847 global $langs, $user;
848
849 $selected = is_array($selected) ? $selected : (!empty($selected) ? explode(',', $selected) : array());
850 $ticketstat = new Ticket($this->db);
851
852 dol_syslog(get_class($this) . "::select_types_tickets " . implode(';', $selected) . ", " . $htmlname . ", " . $filtertype . ", " . $format . ", " . $multiselect, LOG_DEBUG);
853
854 $filterarray = array();
855
856 if ($filtertype != '' && $filtertype != '-1') {
857 $filterarray = explode(',', $filtertype);
858 }
859
860 $ticketstat->loadCacheTypesTickets();
861
862 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.($multiselect ? '[]' : '').'"'.($multiselect ? ' multiple' : '').'>';
863 if ($empty) {
864 print '<option value="">&nbsp;</option>';
865 }
866
867 if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
868 foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
869 // On passe si on a demande de filtrer sur des modes de paiments particuliers
870 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
871 continue;
872 }
873
874 // If 'showempty' is enabled we discard empty line because an empty line has already been output.
875 if ($empty && empty($arraytypes['code'])) {
876 continue;
877 }
878
879 if ($format == 0) {
880 print '<option value="'.$id.'"';
881 }
882
883 if ($format == 1) {
884 print '<option value="'.$arraytypes['code'].'"';
885 }
886
887 if ($format == 2) {
888 print '<option value="'.$arraytypes['code'].'"';
889 }
890
891 if ($format == 3) {
892 print '<option value="'.$id.'"';
893 }
894
895 // If text is selected, we compare with code, otherwise with id
896 if (in_array($arraytypes['code'], $selected)) {
897 print ' selected="selected"';
898 } elseif (in_array($id, $selected)) {
899 print ' selected="selected"';
900 } elseif ($arraytypes['use_default'] == "1" && empty($selected)) {
901 print ' selected="selected"';
902 }
903
904 print '>';
905
906 $value = '&nbsp;';
907 if ($format == 0) {
908 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
909 } elseif ($format == 1) {
910 $value = $arraytypes['code'];
911 } elseif ($format == 2) {
912 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
913 } elseif ($format == 3) {
914 $value = $arraytypes['code'];
915 }
916
917 print $value ? $value : '&nbsp;';
918 print '</option>';
919 }
920 }
921 print '</select>';
922 if (isset($user->admin) && $user->admin && !$noadmininfo) {
923 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
924 }
925
926 print ajax_combobox('select'.$htmlname);
927 }
928
944 public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0, $outputlangs = null)
945 {
946 global $conf, $langs, $user;
947
948 dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
949
950 if (is_null($outputlangs) || !is_object($outputlangs)) {
951 $outputlangs = $langs;
952 }
953 $outputlangs->load("ticket");
954
955 $publicgroups = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
956
957 $ticketstat = new Ticket($this->db);
958 $ticketstat->loadCacheCategoriesTickets($publicgroups ? 1 : -1); // get list of active ticket groups
959
960 if ($use_multilevel <= 0) {
961 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
962 if ($empty) {
963 print '<option value="">&nbsp;</option>';
964 }
965
966 if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
967 foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
968 // Exclude some record
969 if ($publicgroups) {
970 if (empty($arraycategories['public'])) {
971 continue;
972 }
973 }
974
975 // We discard empty line if showempty is on because an empty line has already been output.
976 if ($empty && empty($arraycategories['code'])) {
977 continue;
978 }
979
980 $label = ($arraycategories['label'] != '-' ? $arraycategories['label'] : '');
981 if ($outputlangs->trans("TicketCategoryShort".$arraycategories['code']) != "TicketCategoryShort".$arraycategories['code']) {
982 $label = $outputlangs->trans("TicketCategoryShort".$arraycategories['code']);
983 } elseif ($outputlangs->trans($arraycategories['code']) != $arraycategories['code']) {
984 $label = $outputlangs->trans($arraycategories['code']);
985 }
986
987 if ($format == 0) {
988 print '<option value="'.$id.'"';
989 }
990
991 if ($format == 1) {
992 print '<option value="'.$arraycategories['code'].'"';
993 }
994
995 if ($format == 2) {
996 print '<option value="'.$arraycategories['code'].'"';
997 }
998
999 if ($format == 3) {
1000 print '<option value="'.$id.'"';
1001 }
1002
1003 // If selected is text, we compare with code, otherwise with id
1004 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
1005 print ' selected="selected"';
1006 } elseif (isset($selected) && $selected == $id) {
1007 print ' selected="selected"';
1008 } elseif ($arraycategories['use_default'] == "1" && empty($selected)) {
1009 print ' selected="selected"';
1010 } elseif (count($ticketstat->cache_category_tickets) == 1) { // If only 1 choice, we autoselect it
1011 print ' selected="selected"';
1012 }
1013
1014 print '>';
1015
1016 $value = '';
1017 if ($format == 0) {
1018 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
1019 }
1020
1021 if ($format == 1) {
1022 $value = $arraycategories['code'];
1023 }
1024
1025 if ($format == 2) {
1026 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
1027 }
1028
1029 if ($format == 3) {
1030 $value = $arraycategories['code'];
1031 }
1032
1033 print $value ? $value : '&nbsp;';
1034 print '</option>';
1035 }
1036 }
1037 print '</select>';
1038 if (isset($user->admin) && $user->admin && !$noadmininfo) {
1039 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1040 }
1041
1042 print ajax_combobox('select'.$htmlname);
1043 } elseif ($htmlname != '') {
1044 $selectedgroups = array();
1045 $groupvalue = "";
1046 $groupticket = GETPOST($htmlname, 'aZ09');
1047 $child_id = GETPOST($htmlname.'_child_id', 'aZ09') ? GETPOST($htmlname.'_child_id', 'aZ09') : 0;
1048 if (!empty($groupticket)) {
1049 $tmpgroupticket = $groupticket;
1050 $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code";
1051 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'";
1052 $resql = $this->db->query($sql);
1053 if ($resql) {
1054 $obj = $this->db->fetch_object($resql);
1055 $selectedgroups[] = $obj->code;
1056 while ($obj->fk_parent > 0) {
1057 $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)."'";
1058 $resql = $this->db->query($sql);
1059 if ($resql) {
1060 $obj = $this->db->fetch_object($resql);
1061 $selectedgroups[] = $obj->code;
1062 }
1063 }
1064 }
1065 }
1066
1067 $arrayidused = array();
1068 $arrayidusedconcat = array();
1069 $arraycodenotparent = array();
1070 $arraycodenotparent[] = "";
1071
1072 $stringtoprint = '<span class="supportemailfield bold">'.$langs->trans("GroupOfTicket").'</span> ';
1073 $stringtoprint .= '<select id="'.$htmlname.'" class="minwidth500" child_id="0">';
1074 $stringtoprint .= '<option value="">&nbsp;</option>';
1075
1076 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ";
1077 $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";
1078 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1079 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1080 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1081 if ($public) {
1082 $sql .= " AND ctc.public = 1";
1083 }
1084 $sql .= " AND ctc.fk_parent = 0";
1085 $sql .= $this->db->order('ctc.pos', 'ASC');
1086
1087 $resql = $this->db->query($sql);
1088 if ($resql) {
1089 $num_rows_level0 = $this->db->num_rows($resql);
1090 $i = 0;
1091 while ($i < $num_rows_level0) {
1092 $obj = $this->db->fetch_object($resql);
1093 if ($obj) {
1094 $label = ($obj->label != '-' ? $obj->label : '');
1095 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1096 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1097 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1098 $label = $outputlangs->trans($obj->code);
1099 }
1100
1101 $grouprowid = $obj->rowid;
1102 $groupvalue = $obj->code;
1103 $grouplabel = $label;
1104
1105 $isparent = $obj->isparent;
1106 if (is_array($selectedgroups)) {
1107 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1108 } else {
1109 $iselected = $groupticket == $obj->code ? 'selected' : '';
1110 }
1111 $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>';
1112 if ($isparent == 'NOTPARENT') {
1113 $arraycodenotparent[] = $groupvalue;
1114 }
1115 $arrayidused[] = $grouprowid;
1116 $arrayidusedconcat[] = $grouprowid;
1117 }
1118 $i++;
1119 }
1120 } else {
1121 dol_print_error($this->db);
1122 }
1123 if (count($arrayidused) == 1) {
1124 return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
1125 } else {
1126 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400" value="'.GETPOST($htmlname).'">';
1127 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400" '.GETPOST($htmlname).' value="'.GETPOST($htmlname."_child_id").'">';
1128 }
1129 $stringtoprint .= '</select>&nbsp;';
1130
1131 $levelid = 1; // The first combobox
1132 while ($levelid <= $use_multilevel) { // Loop to take the child of the combo
1133 $tabscript = array();
1134 $stringtoprint .= '<select id="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
1135 $stringtoprint .= '<option value="">&nbsp;</option>';
1136
1137 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather";
1138 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1139 $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
1140 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1141 $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(implode(',', $arrayidusedconcat)).")";
1142
1143 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1144 if ($public) {
1145 $sql .= " AND ctc.public = 1";
1146 }
1147 // Add a test to take only record that are direct child
1148 if (!empty($arrayidused)) {
1149 $sql .= " AND ctc.fk_parent IN ( ";
1150 foreach ($arrayidused as $idused) {
1151 $sql .= $idused.", ";
1152 }
1153 $sql = substr($sql, 0, -2);
1154 $sql .= ")";
1155 }
1156 $sql .= $this->db->order('ctc.pos', 'ASC');
1157
1158 $resql = $this->db->query($sql);
1159 if ($resql) {
1160 $num_rows = $this->db->num_rows($resql);
1161 $i = 0;
1162 $arrayidused = array();
1163 while ($i < $num_rows) {
1164 $obj = $this->db->fetch_object($resql);
1165 if ($obj) {
1166 $label = ($obj->label != '-' ? $obj->label : '');
1167 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1168 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1169 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1170 $label = $outputlangs->trans($obj->code);
1171 }
1172
1173 $grouprowid = $obj->rowid;
1174 $groupvalue = $obj->code;
1175 $grouplabel = $label;
1176 $isparent = $obj->isparent;
1177 $fatherid = $obj->fk_parent;
1178 $arrayidused[] = $grouprowid;
1179 $arrayidusedconcat[] = $grouprowid;
1180 $groupcodefather = $obj->codefather;
1181 if ($isparent == 'NOTPARENT') {
1182 $arraycodenotparent[] = $groupvalue;
1183 }
1184 if (is_array($selectedgroups)) {
1185 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1186 } else {
1187 $iselected = $groupticket == $obj->code ? 'selected' : '';
1188 }
1189 $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>';
1190 if (empty($tabscript[$groupcodefather])) {
1191 $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val() == "'.dol_escape_js($groupcodefather).'"){
1192 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").show()
1193 console.log("We show child tickets of '.$groupcodefather.' group ticket")
1194 }else{
1195 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").hide()
1196 console.log("We hide child tickets of '.$groupcodefather.' group ticket")
1197 }';
1198 }
1199 }
1200 $i++;
1201 }
1202 } else {
1203 dol_print_error($this->db);
1204 }
1205 $stringtoprint .= '</select>';
1206
1207 $stringtoprint .= '<script nonce="'.getNonce().'">';
1208 $stringtoprint .= 'arraynotparents = '.json_encode($arraycodenotparent).';'; // when the last visible combo list is number x, this is the array of group
1209 $stringtoprint .= 'if (arraynotparents.includes($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val())){
1210 console.log("'.$htmlname.'_child_'.$levelid.'")
1211 if($("#'.$htmlname.'_child_'.$levelid.'").val() == "" && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")>'.$child_id.')){
1212 $("#'.$htmlname.'_child_'.$levelid.'").hide();
1213 console.log("We hide '.$htmlname.'_child_'.$levelid.' input")
1214 }
1215 if(arraynotparents.includes("'.$groupticket.'") && '.$child_id.' == 0){
1216 $("#ticketcategory_select_child_id").val($("#'.$htmlname.'").attr("child_id"))
1217 $("#ticketcategory_select").val($("#'.$htmlname.'").val()) ;
1218 console.log("We choose '.$htmlname.' input and reload hidden input");
1219 }
1220 }
1221 $("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").change(function() {
1222 child_id = $("#'.$htmlname.($levelid > 1 ? '_child_'.$levelid : '').'").attr("child_id");
1223
1224 /* Change of value to select this value*/
1225 if (arraynotparents.includes($(this).val()) || $(this).attr("child_id") == '.$use_multilevel.') {
1226 $("#ticketcategory_select").val($(this).val());
1227 $("#ticketcategory_select_child_id").val($(this).attr("child_id")) ;
1228 console.log("We choose to select "+ $(this).val());
1229 }else{
1230 if ($("#'.$htmlname.'_child_'.$levelid.' option").length <= 1) {
1231 $("#ticketcategory_select").val($(this).val());
1232 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1233 console.log("We choose to select "+ $(this).val() + " and next combo has no item, so we keep this selection");
1234 } else {
1235 console.log("We choose to select "+ $(this).val() + " but next combo has some item, so we clean selected item");
1236 $("#ticketcategory_select").val("");
1237 $("#ticketcategory_select_child_id").val("");
1238 }
1239 }
1240
1241 console.log("We select a new value into combo child_id="+child_id);
1242
1243 // Hide all selected box that are child of the one modified
1244 $(".groupticketchild").each(function(){
1245 if ($(this).attr("child_id") > child_id) {
1246 console.log("hide child_id="+$(this).attr("child_id"));
1247 $(this).val("");
1248 $(this).hide();
1249 }
1250 })
1251
1252 // Now we enable the next combo
1253 $("#'.$htmlname.'_child_'.$levelid.'").val("");
1254 if (!arraynotparents.includes($(this).val()) && $("#'.$htmlname.'_child_'.$levelid.' option").length > 1) {
1255 console.log($("#'.$htmlname.'_child_'.$levelid.' option").length);
1256 $("#'.$htmlname.'_child_'.$levelid.'").show()
1257 } else {
1258 $("#'.$htmlname.'_child_'.$levelid.'").hide()
1259 }
1260 ';
1261 $levelid++;
1262 foreach ($tabscript as $script) {
1263 $stringtoprint .= $script;
1264 }
1265 $stringtoprint .= '})';
1266 $stringtoprint .= '</script>';
1267 }
1268 $stringtoprint .= '<script nonce="'.getNonce().'">';
1269 $stringtoprint .= '$("#'.$htmlname.'_child_'.$use_multilevel.'").change(function() {
1270 $("#ticketcategory_select").val($(this).val());
1271 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1272 tmpvalselect = $("#ticketcategory_select").val();
1273 if(tmpvalselect == "" && $("#ticketcategory_select_child_id").val() >= 1){
1274 $("#ticketcategory_select_child_id").val($(this).attr("child_id")-1);
1275 }
1276 console.log($("#ticketcategory_select").val());
1277 })';
1278 $stringtoprint .= '</script>';
1279 $stringtoprint .= ajax_combobox($htmlname);
1280
1281 return $stringtoprint;
1282 }
1283 }
1284
1298 public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
1299 {
1300 global $conf, $langs, $user;
1301
1302 $ticketstat = new Ticket($this->db);
1303
1304 dol_syslog(get_class($this)."::selectSeveritiesTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
1305
1306 $filterarray = array();
1307
1308 if ($filtertype != '' && $filtertype != '-1') {
1309 $filterarray = explode(',', $filtertype);
1310 }
1311
1312 $ticketstat->loadCacheSeveritiesTickets();
1313
1314 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
1315 if ($empty) {
1316 print '<option value="">&nbsp;</option>';
1317 }
1318
1319 if (is_array($conf->cache['severity_tickets']) && count($conf->cache['severity_tickets'])) {
1320 foreach ($conf->cache['severity_tickets'] as $id => $arrayseverities) {
1321 // On passe si on a demande de filtrer sur des modes de paiments particuliers
1322 if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
1323 continue;
1324 }
1325
1326 // We discard empty line if showempty is on because an empty line has already been output.
1327 if ($empty && empty($arrayseverities['code'])) {
1328 continue;
1329 }
1330
1331 if ($format == 0) {
1332 print '<option value="'.$id.'"';
1333 }
1334
1335 if ($format == 1) {
1336 print '<option value="'.$arrayseverities['code'].'"';
1337 }
1338
1339 if ($format == 2) {
1340 print '<option value="'.$arrayseverities['code'].'"';
1341 }
1342
1343 if ($format == 3) {
1344 print '<option value="'.$id.'"';
1345 }
1346
1347 // If text is selected, we compare with code, otherwise with id
1348 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
1349 print ' selected="selected"';
1350 } elseif (isset($selected) && $selected == $id) {
1351 print ' selected="selected"';
1352 } elseif ($arrayseverities['use_default'] == "1" && empty($selected)) {
1353 print ' selected="selected"';
1354 }
1355
1356 print '>';
1357
1358 $value = '';
1359 if ($format == 0) {
1360 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1361 }
1362
1363 if ($format == 1) {
1364 $value = $arrayseverities['code'];
1365 }
1366
1367 if ($format == 2) {
1368 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1369 }
1370
1371 if ($format == 3) {
1372 $value = $arrayseverities['code'];
1373 }
1374
1375 print $value ? $value : '&nbsp;';
1376 print '</option>';
1377 }
1378 }
1379 print '</select>';
1380 if (isset($user->admin) && $user->admin && !$noadmininfo) {
1381 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1382 }
1383
1384 print ajax_combobox('select'.$htmlname);
1385 }
1386
1387 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1393 public function clear_attached_files()
1394 {
1395 // phpcs:enable
1396 global $conf, $user;
1397 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1398
1399 // Set tmp user directory
1400 $vardir = $conf->user->dir_output."/".$user->id;
1401 $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
1402 if (is_dir($upload_dir)) {
1403 dol_delete_dir_recursive($upload_dir);
1404 }
1405
1406 if (!empty($this->trackid)) { // TODO Always use trackid (ticXXX) instead of track_id (abcd123)
1407 $keytoavoidconflict = '-'.$this->trackid;
1408 } else {
1409 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id;
1410 }
1411 unset($_SESSION["listofpaths".$keytoavoidconflict]);
1412 unset($_SESSION["listofnames".$keytoavoidconflict]);
1413 unset($_SESSION["listofmimes".$keytoavoidconflict]);
1414 }
1415
1422 public function showMessageForm($width = '40%')
1423 {
1424 global $conf, $langs, $user, $hookmanager, $form, $mysoc;
1425
1426 $formmail = new FormMail($this->db);
1427 $addfileaction = 'addfile';
1428
1429 if (!is_object($form)) {
1430 $form = new Form($this->db);
1431 }
1432
1433 // Load translation files required by the page
1434 $langs->loadLangs(array('other', 'mails', 'ticket'));
1435
1436 // Clear temp files. Must be done at beginning, before call of triggers
1437 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1438 $this->clear_attached_files();
1439 }
1440
1441 // Define output language
1442 $outputlangs = $langs;
1443 $newlang = '';
1444 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1445 $newlang = $this->param['langsmodels'];
1446 }
1447 if (!empty($newlang)) {
1448 $outputlangs = new Translate("", $conf);
1449 $outputlangs->setDefaultLang($newlang);
1450 $outputlangs->load('other');
1451 }
1452
1453 // Get message template for $this->param["models"] into c_email_templates
1454 $arraydefaultmessage = -1;
1455 if (isset($this->param['models']) && $this->param['models'] != 'none') {
1456 $model_id = 0;
1457 if (array_key_exists('models_id', $this->param)) {
1458 $model_id = (int) $this->param["models_id"];
1459 }
1460
1461 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
1462 }
1463
1464 // Define list of attached files
1465 $listofpaths = array();
1466 $listofnames = array();
1467 $listofmimes = array();
1468
1469 if (!empty($this->trackid)) {
1470 $keytoavoidconflict = '-'.$this->trackid;
1471 } else {
1472 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1473 }
1474 //var_dump($keytoavoidconflict);
1475 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1476 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
1477 foreach ($this->param['fileinit'] as $path) {
1478 $formmail->add_attached_files($path, basename($path), dol_mimetype($path));
1479 }
1480 }
1481 }
1482 //var_dump($_SESSION);
1483 //var_dump($_SESSION["listofpaths".$keytoavoidconflict]);
1484 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
1485 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
1486 }
1487 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
1488 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
1489 }
1490 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
1491 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
1492 }
1493
1494 // Define output language
1495 $outputlangs = $langs;
1496 $newlang = '';
1497 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1498 $newlang = $this->param['langsmodels'];
1499 }
1500 if (!empty($newlang)) {
1501 $outputlangs = new Translate("", $conf);
1502 $outputlangs->setDefaultLang($newlang);
1503 $outputlangs->load('other');
1504 }
1505
1506 print "\n<!-- Begin message_form TICKET -->\n";
1507
1508 $send_email = GETPOSTINT('send_email') ? GETPOSTINT('send_email') : 0;
1509
1510 // Example 1 : Adding jquery code
1511 print '<script nonce="'.getNonce().'" type="text/javascript">
1512 jQuery(document).ready(function() {
1513 send_email=' . $send_email.';
1514 if (send_email) {
1515 if (!jQuery("#send_msg_email").is(":checked")) {
1516 jQuery("#send_msg_email").prop("checked", true).trigger("change");
1517 }
1518 jQuery(".email_line").show();
1519 } else {
1520 if (!jQuery("#private_message").is(":checked")) {
1521 jQuery("#private_message").prop("checked", true).trigger("change");
1522 }
1523 jQuery(".email_line").hide();
1524 }
1525 ';
1526
1527 // If constant set, allow to send private messages as email
1528 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1529 print 'jQuery("#send_msg_email").click(function() {
1530 console.log("Click send_msg_email");
1531 if(jQuery(this).is(":checked")) {
1532 if (jQuery("#private_message").is(":checked")) {
1533 jQuery("#private_message").prop("checked", false).trigger("change");
1534 }
1535 jQuery(".email_line").show();
1536 }
1537 else {
1538 jQuery(".email_line").hide();
1539 }
1540 });
1541
1542 jQuery("#private_message").click(function() {
1543 console.log("Click private_message");
1544 if (jQuery(this).is(":checked")) {
1545 if (jQuery("#send_msg_email").is(":checked")) {
1546 jQuery("#send_msg_email").prop("checked", false).trigger("change");
1547 }
1548 jQuery(".email_line").hide();
1549 }
1550 });';
1551 }
1552
1553 print '});
1554 </script>';
1555
1556
1557 print '<form method="post" name="ticket" id="ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
1558 print '<input type="hidden" name="token" value="'.newToken().'">';
1559 print '<input type="hidden" name="action" value="'.$this->action.'">';
1560 print '<input type="hidden" name="actionbis" value="add_message">';
1561 print '<input type="hidden" name="backtopage" value="'.$this->backtopage.'">';
1562 if (!empty($this->trackid)) {
1563 print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
1564 } else {
1565 print '<input type="hidden" name="trackid" value="'.(empty($this->track_id) ? '' : $this->track_id).'">';
1566 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1567 }
1568 foreach ($this->param as $key => $value) {
1569 print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
1570 }
1571
1572 // Get message template
1573 $model_id = 0;
1574 if (array_key_exists('models_id', $this->param)) {
1575 $model_id = $this->param["models_id"];
1576 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
1577 }
1578
1579 $result = $formmail->fetchAllEMailTemplate(!empty($this->param["models"]) ? $this->param["models"] : "", $user, $outputlangs);
1580 if ($result < 0) {
1581 setEventMessages($this->error, $this->errors, 'errors');
1582 }
1583 $modelmail_array = array();
1584 foreach ($formmail->lines_model as $line) {
1585 $modelmail_array[$line->id] = $line->label;
1586 }
1587
1588 print '<table class="border" width="'.$width.'">';
1589
1590 // External users can't send message email
1591 if ($user->hasRight("ticket", "write") && !$user->socid) {
1592 $ticketstat = new Ticket($this->db);
1593 $res = $ticketstat->fetch(0, '', $this->track_id);
1594
1595 print '<tr><td></td><td>';
1596 $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : (getDolGlobalInt('TICKETS_MESSAGE_FORCE_MAIL') ? 'checked' : ''));
1597 print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
1598 print '<label for="send_msg_email">'.$langs->trans('SendMessageByEmail').'</label>';
1599 $texttooltip = $langs->trans("TicketMessageSendEmailHelp");
1600 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1601 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2b");
1602 } else {
1603 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2a", '{s1}');
1604 }
1605 $texttooltip = str_replace('{s1}', $langs->trans('MarkMessageAsPrivate'), $texttooltip);
1606 print ' '.$form->textwithpicto('', $texttooltip, 1, 'help');
1607 print '</td></tr>';
1608
1609 // Private message (not visible by customer/external user)
1610 if (!$user->socid) {
1611 print '<tr><td></td><td>';
1612 $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : '');
1613 print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
1614 print '<label for="private_message">'.$langs->trans('MarkMessageAsPrivate').'</label>';
1615 print ' '.$form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
1616 print '</td></tr>';
1617 }
1618
1619 // Zone to select its email template
1620 if (count($modelmail_array) > 0) {
1621 print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
1622 print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, 0, "", 0, 0, 0, '', 'minwidth200');
1623 if ($user->admin) {
1624 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1625 }
1626 print ' &nbsp; ';
1627 print '<input type="submit" class="button" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
1628 print '</div></td>';
1629 }
1630
1631 // From
1632 $from = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM');
1633 print '<tr class="email_line"><td><span class="">'.$langs->trans("MailFrom").'</span></td>';
1634 print '<td><span class="">'.img_picto('', 'email', 'class="pictofixedwidth"').$from.'</span></td></tr>';
1635
1636 // Subject/topic
1637 $topic = "";
1638 foreach ($formmail->lines_model as $line) {
1639 if (!empty($this->substit) && $this->param['models_id'] == $line->id) {
1640 $topic = make_substitutions($line->topic, $this->substit);
1641 break;
1642 }
1643 }
1644 print '<tr class="email_line"><td>'.$langs->trans('Subject').'</td>';
1645 if (empty($topic)) {
1646 print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '. $ticketstat->subject .'" />';
1647 } else {
1648 print '<td><input type="text" class="text minwidth500" name="subject" value="'.make_substitutions($topic, $this->substit).'" />';
1649 }
1650 print '</td></tr>';
1651
1652 // Recipients / adressed-to
1653 print '<tr class="email_line"><td>'.$langs->trans('MailRecipients');
1654 print ' '.$form->textwithpicto('', $langs->trans("TicketMessageRecipientsHelp"), 1, 'help');
1655 print '</td><td>';
1656 if ($res) {
1657 // Retrieve email of all contacts (internal and external)
1658 $contacts = $ticketstat->getInfosTicketInternalContact(1);
1659 $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact(1));
1660
1661 $sendto = array();
1662
1663 // Build array to display recipient list
1664 if (is_array($contacts) && count($contacts) > 0) {
1665 foreach ($contacts as $key => $info_sendto) {
1666 if ($info_sendto['email'] != '') {
1667 $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">").' <small class="opacitymedium">('.dol_escape_htmltag($info_sendto['libelle']).")</small>";
1668 }
1669 }
1670 }
1671
1672 if (!empty($ticketstat->origin_replyto) && !in_array($ticketstat->origin_replyto, $sendto)) {
1673 $sendto[] = dol_escape_htmltag($ticketstat->origin_replyto).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1674 } elseif ($ticketstat->origin_email && !in_array($ticketstat->origin_email, $sendto)) {
1675 $sendto[] = dol_escape_htmltag($ticketstat->origin_email).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1676 }
1677
1678 if ($ticketstat->fk_soc > 0) {
1679 $ticketstat->socid = $ticketstat->fk_soc;
1680 $ticketstat->fetch_thirdparty();
1681
1682 if (!empty($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
1683 $sendto[] = $ticketstat->thirdparty->email.' <small class="opacitymedium">('.$langs->trans('Customer').')</small>';
1684 }
1685 }
1686
1687 if (getDolGlobalInt('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS')) {
1688 $sendto[] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO').' <small class="opacitymedium">(generic email)</small>';
1689 }
1690
1691 // Print recipient list
1692 if (is_array($sendto) && count($sendto) > 0) {
1693 print img_picto('', 'email', 'class="pictofixedwidth"');
1694 print implode(', ', $sendto);
1695 } else {
1696 print '<div class="warning">'.$langs->trans('WarningNoEMailsAdded').' '.$langs->trans('TicketGoIntoContactTab').'</div>';
1697 }
1698 }
1699 print '</td></tr>';
1700 }
1701
1702 $uselocalbrowser = false;
1703
1704 // Intro
1705 // External users can't send message email
1706 /*
1707 if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_INTRO)) {
1708 $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
1709 print '<tr class="email_line"><td><label for="mail_intro">';
1710 print $form->textwithpicto($langs->trans("TicketMessageMailIntro"), $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
1711 print '</label>';
1712
1713 print '</td><td>';
1714 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1715
1716 $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_2, 70);
1717
1718 $doleditor->Create();
1719 print '</td></tr>';
1720 }
1721 */
1722
1723 // Attached files
1724 if (!empty($this->withfile)) {
1725 $out = '<tr>';
1726 $out .= '<td>'.$langs->trans("MailFile").'</td>';
1727 $out .= '<td>';
1728 // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
1729 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
1730 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1731 $out .= 'jQuery(document).ready(function () {';
1732 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1733 $out .= ' jQuery("#addedfile").on("change", function() {';
1734 $out .= ' if (jQuery(this).val().length) {';
1735 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", false);';
1736 $out .= ' } else {';
1737 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1738 $out .= ' }';
1739 $out .= ' });';
1740 $out .= ' jQuery(".removedfile").click(function() {';
1741 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
1742 $out .= ' });';
1743 $out .= '})';
1744 $out .= '</script>'."\n";
1745
1746 if (count($listofpaths)) {
1747 foreach ($listofpaths as $key => $val) {
1748 $out .= '<div id="attachfile_'.$key.'">';
1749 $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
1750 if (!$this->withfilereadonly) {
1751 $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.'" />';
1752 }
1753 $out .= '<br></div>';
1754 }
1755 } else {
1756 //$out .= $langs->trans("NoAttachedFiles").'<br>';
1757 }
1758 if ($this->withfile == 2) { // Can add other files
1759 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
1760 $out .= ' ';
1761 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
1762 }
1763 $out .= "</td></tr>\n";
1764
1765 print $out;
1766 }
1767
1768 // MESSAGE
1769
1770 $defaultmessage = "";
1771 if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
1772 $defaultmessage = $arraydefaultmessage->content;
1773 }
1774 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1775
1776 // Deal with format differences between message and signature (text / HTML)
1777 if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1778 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1779 } elseif (!dol_textishtml($defaultmessage) && isset($this->substit['__USER_SIGNATURE__']) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1780 $defaultmessage = dol_nl2br($defaultmessage);
1781 }
1782 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1783 $defaultmessage = GETPOST('message', 'restricthtml');
1784 } else {
1785 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1786 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1787 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1788 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1789 }
1790
1791 print '<tr><td colspan="2"><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span>';
1792 if ($user->hasRight("ticket", "write") && !$user->socid) {
1793 $texttooltip = $langs->trans("TicketMessageHelp");
1794 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO') || getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1795 $texttooltip .= '<br><br>'.$langs->trans("ForEmailMessageWillBeCompletedWith").'...';
1796 }
1797 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO')) {
1798 $mail_intro = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO'), $this->substit);
1799 print '<input type="hidden" name="mail_intro" value="'.$mail_intro.'">';
1800 $texttooltip .= '<br><u>'.$langs->trans("TicketMessageMailIntro").'</u><br>'.$mail_intro;
1801 }
1802 if (getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1803 $mail_signature = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE'), $this->substit);
1804 print '<input type="hidden" name="mail_signature" value="'.$mail_signature.'">';
1805 $texttooltip .= '<br><br><u>'.$langs->trans("TicketMessageMailFooter").'</u><br>'.$mail_signature;
1806 }
1807 print $form->textwithpicto('', $texttooltip, 1, 'help');
1808 }
1809 print '</label></td></tr>';
1810
1811
1812 print '<tr><td colspan="2">';
1813 //$toolbarname = 'dolibarr_details';
1814 $toolbarname = 'dolibarr_notes';
1815 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1816 $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_5, '90%');
1817 $doleditor->Create();
1818 print '</td></tr>';
1819
1820 // Footer
1821 // External users can't send message email
1822 /*if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_SIGNATURE)) {
1823 $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
1824 print '<tr class="email_line"><td><label for="mail_intro">'.$langs->trans("TicketMessageMailFooter").'</label>';
1825 print $form->textwithpicto('', $langs->trans("TicketMessageMailFooterHelp"), 1, 'help');
1826 print '</td><td>';
1827 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1828 $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_2, 70);
1829 $doleditor->Create();
1830 print '</td></tr>';
1831 }
1832 */
1833
1834 print '</table>';
1835
1836 print '<br><center>';
1837 print '<input type="submit" class="button" name="btn_add_message" value="'.$langs->trans("Add").'"';
1838 // Add a javascript test to avoid to forget to submit file before sending email
1839 if ($this->withfile == 2 && !empty($conf->use_javascript_ajax)) {
1840 print ' onClick="if (document.ticket.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1841 }
1842 print ' />';
1843 if (!empty($this->withcancel)) {
1844 print " &nbsp; &nbsp; ";
1845 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
1846 }
1847 print "</center>\n";
1848
1849 print '<input type="hidden" name="page_y">'."\n";
1850
1851 print "</form><br>\n";
1852
1853 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1854 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1855 print '<script type="text/javascript">';
1856 print 'jQuery(document).ready(function () {';
1857 print ' $(document).on("keypress", \'#ticket\', function (e) { /* Note this is called at every key pressed ! */
1858 var code = e.keyCode || e.which;
1859 if (code == 13) {
1860 console.log("Enter was intercepted and blocked");
1861 e.preventDefault();
1862 return false;
1863 }
1864 });';
1865 print '})';
1866 print '</script>';
1867 }
1868
1869 print "<!-- End form TICKET -->\n";
1870 }
1871}
$id
Definition account.php:39
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
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:457
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.
showForm($withdolfichehead=0, $mode='edit', $public=0, $with_contact=null, $action='', $object=null)
Show the form to input ticket.
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
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:137
getMaxFileSizeArray()
Return the max allowed for file upload.