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