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