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', 'class="pictofixedwidth"').$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', 'class="pictofixedwidth"');
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>';
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 print '<br>';
738
739 /*
740 print '<div class="center">';
741 print '<input type="submit" class="button" name="add" value="'.$langs->trans(($this->withreadid > 0 ? "SendResponse" : "CreateTicket")).'" />';
742 if ($this->withcancel) {
743 print " &nbsp; &nbsp; &nbsp;";
744 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
745 }
746 print '</div>';
747 */
748
749 print '<input type="hidden" name="page_y">'."\n";
750
751 print "</form>\n";
752 print "<!-- End form TICKET -->\n";
753 }
754
769 public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $multiselect = 0)
770 {
771 global $langs, $user;
772
773 $selected = is_array($selected) ? $selected : (!empty($selected) ? explode(',', $selected) : array());
774 $ticketstat = new Ticket($this->db);
775
776 dol_syslog(get_class($this) . "::select_types_tickets " . implode(';', $selected) . ", " . $htmlname . ", " . $filtertype . ", " . $format . ", " . $multiselect, LOG_DEBUG);
777
778 $filterarray = array();
779
780 if ($filtertype != '' && $filtertype != '-1') {
781 $filterarray = explode(',', $filtertype);
782 }
783
784 $ticketstat->loadCacheTypesTickets();
785
786 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.($multiselect ? '[]' : '').'"'.($multiselect ? ' multiple' : '').'>';
787 if ($empty) {
788 print '<option value="">&nbsp;</option>';
789 }
790
791 if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
792 foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
793 // On passe si on a demande de filtrer sur des modes de paiments particuliers
794 if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
795 continue;
796 }
797
798 // If 'showempty' is enabled we discard empty line because an empty line has already been output.
799 if ($empty && empty($arraytypes['code'])) {
800 continue;
801 }
802
803 if ($format == 0) {
804 print '<option value="'.$id.'"';
805 }
806
807 if ($format == 1) {
808 print '<option value="'.$arraytypes['code'].'"';
809 }
810
811 if ($format == 2) {
812 print '<option value="'.$arraytypes['code'].'"';
813 }
814
815 if ($format == 3) {
816 print '<option value="'.$id.'"';
817 }
818
819 // If text is selected, we compare with code, otherwise with id
820 if (in_array($arraytypes['code'], $selected)) {
821 print ' selected="selected"';
822 } elseif (in_array($id, $selected)) {
823 print ' selected="selected"';
824 } elseif ($arraytypes['use_default'] == "1" && empty($selected)) {
825 print ' selected="selected"';
826 }
827
828 print '>';
829
830 $value = '&nbsp;';
831 if ($format == 0) {
832 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
833 } elseif ($format == 1) {
834 $value = $arraytypes['code'];
835 } elseif ($format == 2) {
836 $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
837 } elseif ($format == 3) {
838 $value = $arraytypes['code'];
839 }
840
841 print $value ? $value : '&nbsp;';
842 print '</option>';
843 }
844 }
845 print '</select>';
846 if (isset($user->admin) && $user->admin && !$noadmininfo) {
847 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
848 }
849
850 print ajax_combobox('select'.$htmlname);
851 }
852
868 public function selectGroupTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '', $use_multilevel = 0, $outputlangs = null)
869 {
870 global $conf, $langs, $user;
871
872 dol_syslog(get_class($this)."::selectCategoryTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
873
874 if (is_null($outputlangs) || !is_object($outputlangs)) {
875 $outputlangs = $langs;
876 }
877 $outputlangs->load("ticket");
878
879 $publicgroups = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
880
881 $ticketstat = new Ticket($this->db);
882 $ticketstat->loadCacheCategoriesTickets($publicgroups ? 1 : -1); // get list of active ticket groups
883
884 if ($use_multilevel <= 0) {
885 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
886 if ($empty) {
887 print '<option value="">&nbsp;</option>';
888 }
889
890 if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
891 foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
892 // Exclude some record
893 if ($publicgroups) {
894 if (empty($arraycategories['public'])) {
895 continue;
896 }
897 }
898
899 // We discard empty line if showempty is on because an empty line has already been output.
900 if ($empty && empty($arraycategories['code'])) {
901 continue;
902 }
903
904 $label = ($arraycategories['label'] != '-' ? $arraycategories['label'] : '');
905 if ($outputlangs->trans("TicketCategoryShort".$arraycategories['code']) != "TicketCategoryShort".$arraycategories['code']) {
906 $label = $outputlangs->trans("TicketCategoryShort".$arraycategories['code']);
907 } elseif ($outputlangs->trans($arraycategories['code']) != $arraycategories['code']) {
908 $label = $outputlangs->trans($arraycategories['code']);
909 }
910
911 if ($format == 0) {
912 print '<option value="'.$id.'"';
913 }
914
915 if ($format == 1) {
916 print '<option value="'.$arraycategories['code'].'"';
917 }
918
919 if ($format == 2) {
920 print '<option value="'.$arraycategories['code'].'"';
921 }
922
923 if ($format == 3) {
924 print '<option value="'.$id.'"';
925 }
926
927 // If selected is text, we compare with code, otherwise with id
928 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
929 print ' selected="selected"';
930 } elseif (isset($selected) && $selected == $id) {
931 print ' selected="selected"';
932 } elseif ($arraycategories['use_default'] == "1" && empty($selected)) {
933 print ' selected="selected"';
934 } elseif (count($ticketstat->cache_category_tickets) == 1) { // If only 1 choice, we autoselect it
935 print ' selected="selected"';
936 }
937
938 print '>';
939
940 $value = '';
941 if ($format == 0) {
942 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
943 }
944
945 if ($format == 1) {
946 $value = $arraycategories['code'];
947 }
948
949 if ($format == 2) {
950 $value = ($maxlength ? dol_trunc($label, $maxlength) : $label);
951 }
952
953 if ($format == 3) {
954 $value = $arraycategories['code'];
955 }
956
957 print $value ? $value : '&nbsp;';
958 print '</option>';
959 }
960 }
961 print '</select>';
962 if (isset($user->admin) && $user->admin && !$noadmininfo) {
963 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
964 }
965
966 print ajax_combobox('select'.$htmlname);
967 } elseif ($htmlname != '') {
968 $selectedgroups = array();
969 $groupvalue = "";
970 $groupticket = GETPOST($htmlname, 'aZ09');
971 $child_id = GETPOST($htmlname.'_child_id', 'aZ09') ? GETPOST($htmlname.'_child_id', 'aZ09') : 0;
972 if (!empty($groupticket)) {
973 $tmpgroupticket = $groupticket;
974 $sql = "SELECT ctc.rowid, ctc.fk_parent, ctc.code";
975 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc WHERE ctc.code = '".$this->db->escape($tmpgroupticket)."'";
976 $resql = $this->db->query($sql);
977 if ($resql) {
978 $obj = $this->db->fetch_object($resql);
979 $selectedgroups[] = $obj->code;
980 while ($obj->fk_parent > 0) {
981 $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)."'";
982 $resql = $this->db->query($sql);
983 if ($resql) {
984 $obj = $this->db->fetch_object($resql);
985 $selectedgroups[] = $obj->code;
986 }
987 }
988 }
989 }
990
991 $arrayidused = array();
992 $arrayidusedconcat = array();
993 $arraycodenotparent = array();
994 $arraycodenotparent[] = "";
995
996 $stringtoprint = '<span class="supportemailfield bold">'.$langs->trans("GroupOfTicket").'</span> ';
997 $stringtoprint .= '<select id="'.$htmlname.'" class="minwidth500" child_id="0">';
998 $stringtoprint .= '<option value="">&nbsp;</option>';
999
1000 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ";
1001 $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";
1002 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1003 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1004 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1005 if ($public) {
1006 $sql .= " AND ctc.public = 1";
1007 }
1008 $sql .= " AND ctc.fk_parent = 0";
1009 $sql .= $this->db->order('ctc.pos', 'ASC');
1010
1011 $resql = $this->db->query($sql);
1012 if ($resql) {
1013 $num_rows_level0 = $this->db->num_rows($resql);
1014 $i = 0;
1015 while ($i < $num_rows_level0) {
1016 $obj = $this->db->fetch_object($resql);
1017 if ($obj) {
1018 $label = ($obj->label != '-' ? $obj->label : '');
1019 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1020 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1021 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1022 $label = $outputlangs->trans($obj->code);
1023 }
1024
1025 $grouprowid = $obj->rowid;
1026 $groupvalue = $obj->code;
1027 $grouplabel = $label;
1028
1029 $isparent = $obj->isparent;
1030 if (is_array($selectedgroups)) {
1031 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1032 } else {
1033 $iselected = $groupticket == $obj->code ? 'selected' : '';
1034 }
1035 $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>';
1036 if ($isparent == 'NOTPARENT') {
1037 $arraycodenotparent[] = $groupvalue;
1038 }
1039 $arrayidused[] = $grouprowid;
1040 $arrayidusedconcat[] = $grouprowid;
1041 }
1042 $i++;
1043 }
1044 } else {
1045 dol_print_error($this->db);
1046 }
1047 if (count($arrayidused) == 1) {
1048 return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
1049 } else {
1050 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400" value="'.GETPOST($htmlname).'">';
1051 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400" '.GETPOST($htmlname).' value="'.GETPOST($htmlname."_child_id").'">';
1052 }
1053 $stringtoprint .= '</select>&nbsp;';
1054
1055 $levelid = 1; // The first combobox
1056 while ($levelid <= $use_multilevel) { // Loop to take the child of the combo
1057 $tabscript = array();
1058 $stringtoprint .= '<select id="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
1059 $stringtoprint .= '<option value="">&nbsp;</option>';
1060
1061 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather";
1062 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1063 $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
1064 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1065 $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(implode(',', $arrayidusedconcat)).")";
1066
1067 $public = ($filtertype == 'public=1' || $filtertype == '(public:=:1)');
1068 if ($public) {
1069 $sql .= " AND ctc.public = 1";
1070 }
1071 // Add a test to take only record that are direct child
1072 if (!empty($arrayidused)) {
1073 $sql .= " AND ctc.fk_parent IN ( ";
1074 foreach ($arrayidused as $idused) {
1075 $sql .= $idused.", ";
1076 }
1077 $sql = substr($sql, 0, -2);
1078 $sql .= ")";
1079 }
1080 $sql .= $this->db->order('ctc.pos', 'ASC');
1081
1082 $resql = $this->db->query($sql);
1083 if ($resql) {
1084 $num_rows = $this->db->num_rows($resql);
1085 $i = 0;
1086 $arrayidused = array();
1087 while ($i < $num_rows) {
1088 $obj = $this->db->fetch_object($resql);
1089 if ($obj) {
1090 $label = ($obj->label != '-' ? $obj->label : '');
1091 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1092 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1093 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1094 $label = $outputlangs->trans($obj->code);
1095 }
1096
1097 $grouprowid = $obj->rowid;
1098 $groupvalue = $obj->code;
1099 $grouplabel = $label;
1100 $isparent = $obj->isparent;
1101 $fatherid = $obj->fk_parent;
1102 $arrayidused[] = $grouprowid;
1103 $arrayidusedconcat[] = $grouprowid;
1104 $groupcodefather = $obj->codefather;
1105 if ($isparent == 'NOTPARENT') {
1106 $arraycodenotparent[] = $groupvalue;
1107 }
1108 if (is_array($selectedgroups)) {
1109 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1110 } else {
1111 $iselected = $groupticket == $obj->code ? 'selected' : '';
1112 }
1113 $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>';
1114 if (empty($tabscript[$groupcodefather])) {
1115 $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val() == "'.dol_escape_js($groupcodefather).'"){
1116 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").show()
1117 console.log("We show child tickets of '.$groupcodefather.' group ticket")
1118 }else{
1119 $(".'.$htmlname.'_'.dol_escape_htmltag($fatherid).'_child_'.$levelid.'").hide()
1120 console.log("We hide child tickets of '.$groupcodefather.' group ticket")
1121 }';
1122 }
1123 }
1124 $i++;
1125 }
1126 } else {
1127 dol_print_error($this->db);
1128 }
1129 $stringtoprint .= '</select>';
1130
1131 $stringtoprint .= '<script nonce="'.getNonce().'">';
1132 $stringtoprint .= 'arraynotparents = '.json_encode($arraycodenotparent).';'; // when the last visible combo list is number x, this is the array of group
1133 $stringtoprint .= 'if (arraynotparents.includes($("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").val())){
1134 console.log("'.$htmlname.'_child_'.$levelid.'")
1135 if($("#'.$htmlname.'_child_'.$levelid.'").val() == "" && ($("#'.$htmlname.'_child_'.$levelid.'").attr("child_id")>'.$child_id.')){
1136 $("#'.$htmlname.'_child_'.$levelid.'").hide();
1137 console.log("We hide '.$htmlname.'_child_'.$levelid.' input")
1138 }
1139 if(arraynotparents.includes("'.$groupticket.'") && '.$child_id.' == 0){
1140 $("#ticketcategory_select_child_id").val($("#'.$htmlname.'").attr("child_id"))
1141 $("#ticketcategory_select").val($("#'.$htmlname.'").val()) ;
1142 console.log("We choose '.$htmlname.' input and reload hidden input");
1143 }
1144 }
1145 $("#'.$htmlname.($levelid > 1 ? '_child_'.($levelid - 1) : '').'").change(function() {
1146 child_id = $("#'.$htmlname.($levelid > 1 ? '_child_'.$levelid : '').'").attr("child_id");
1147
1148 /* Change of value to select this value*/
1149 if (arraynotparents.includes($(this).val()) || $(this).attr("child_id") == '.$use_multilevel.') {
1150 $("#ticketcategory_select").val($(this).val());
1151 $("#ticketcategory_select_child_id").val($(this).attr("child_id")) ;
1152 console.log("We choose to select "+ $(this).val());
1153 }else{
1154 if ($("#'.$htmlname.'_child_'.$levelid.' option").length <= 1) {
1155 $("#ticketcategory_select").val($(this).val());
1156 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1157 console.log("We choose to select "+ $(this).val() + " and next combo has no item, so we keep this selection");
1158 } else {
1159 console.log("We choose to select "+ $(this).val() + " but next combo has some item, so we clean selected item");
1160 $("#ticketcategory_select").val("");
1161 $("#ticketcategory_select_child_id").val("");
1162 }
1163 }
1164
1165 console.log("We select a new value into combo child_id="+child_id);
1166
1167 // Hide all selected box that are child of the one modified
1168 $(".groupticketchild").each(function(){
1169 if ($(this).attr("child_id") > child_id) {
1170 console.log("hide child_id="+$(this).attr("child_id"));
1171 $(this).val("");
1172 $(this).hide();
1173 }
1174 })
1175
1176 // Now we enable the next combo
1177 $("#'.$htmlname.'_child_'.$levelid.'").val("");
1178 if (!arraynotparents.includes($(this).val()) && $("#'.$htmlname.'_child_'.$levelid.' option").length > 1) {
1179 console.log($("#'.$htmlname.'_child_'.$levelid.' option").length);
1180 $("#'.$htmlname.'_child_'.$levelid.'").show()
1181 } else {
1182 $("#'.$htmlname.'_child_'.$levelid.'").hide()
1183 }
1184 ';
1185 $levelid++;
1186 foreach ($tabscript as $script) {
1187 $stringtoprint .= $script;
1188 }
1189 $stringtoprint .= '})';
1190 $stringtoprint .= '</script>';
1191 }
1192 $stringtoprint .= '<script nonce="'.getNonce().'">';
1193 $stringtoprint .= '$("#'.$htmlname.'_child_'.$use_multilevel.'").change(function() {
1194 $("#ticketcategory_select").val($(this).val());
1195 $("#ticketcategory_select_child_id").val($(this).attr("child_id"));
1196 tmpvalselect = $("#ticketcategory_select").val();
1197 if(tmpvalselect == "" && $("#ticketcategory_select_child_id").val() >= 1){
1198 $("#ticketcategory_select_child_id").val($(this).attr("child_id")-1);
1199 }
1200 console.log($("#ticketcategory_select").val());
1201 })';
1202 $stringtoprint .= '</script>';
1203 $stringtoprint .= ajax_combobox($htmlname);
1204
1205 return $stringtoprint;
1206 }
1207 }
1208
1222 public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss = '')
1223 {
1224 global $conf, $langs, $user;
1225
1226 $ticketstat = new Ticket($this->db);
1227
1228 dol_syslog(get_class($this)."::selectSeveritiesTickets ".$selected.", ".$htmlname.", ".$filtertype.", ".$format, LOG_DEBUG);
1229
1230 $filterarray = array();
1231
1232 if ($filtertype != '' && $filtertype != '-1') {
1233 $filterarray = explode(',', $filtertype);
1234 }
1235
1236 $ticketstat->loadCacheSeveritiesTickets();
1237
1238 print '<select id="select'.$htmlname.'" class="flat minwidth100'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'">';
1239 if ($empty) {
1240 print '<option value="">&nbsp;</option>';
1241 }
1242
1243 if (is_array($conf->cache['severity_tickets']) && count($conf->cache['severity_tickets'])) {
1244 foreach ($conf->cache['severity_tickets'] as $id => $arrayseverities) {
1245 // On passe si on a demande de filtrer sur des modes de paiments particuliers
1246 if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
1247 continue;
1248 }
1249
1250 // We discard empty line if showempty is on because an empty line has already been output.
1251 if ($empty && empty($arrayseverities['code'])) {
1252 continue;
1253 }
1254
1255 if ($format == 0) {
1256 print '<option value="'.$id.'"';
1257 }
1258
1259 if ($format == 1) {
1260 print '<option value="'.$arrayseverities['code'].'"';
1261 }
1262
1263 if ($format == 2) {
1264 print '<option value="'.$arrayseverities['code'].'"';
1265 }
1266
1267 if ($format == 3) {
1268 print '<option value="'.$id.'"';
1269 }
1270
1271 // If text is selected, we compare with code, otherwise with id
1272 if (isset($selected) && preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
1273 print ' selected="selected"';
1274 } elseif (isset($selected) && $selected == $id) {
1275 print ' selected="selected"';
1276 } elseif ($arrayseverities['use_default'] == "1" && empty($selected)) {
1277 print ' selected="selected"';
1278 }
1279
1280 print '>';
1281
1282 $value = '';
1283 if ($format == 0) {
1284 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1285 }
1286
1287 if ($format == 1) {
1288 $value = $arrayseverities['code'];
1289 }
1290
1291 if ($format == 2) {
1292 $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
1293 }
1294
1295 if ($format == 3) {
1296 $value = $arrayseverities['code'];
1297 }
1298
1299 print $value ? $value : '&nbsp;';
1300 print '</option>';
1301 }
1302 }
1303 print '</select>';
1304 if (isset($user->admin) && $user->admin && !$noadmininfo) {
1305 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1306 }
1307
1308 print ajax_combobox('select'.$htmlname);
1309 }
1310
1311 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1317 public function clear_attached_files()
1318 {
1319 // phpcs:enable
1320 global $conf, $user;
1321 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1322
1323 // Set tmp user directory
1324 $vardir = $conf->user->dir_output."/".$user->id;
1325 $upload_dir = $vardir.'/temp/'; // TODO Add $keytoavoidconflict in upload_dir path
1326 if (is_dir($upload_dir)) {
1327 dol_delete_dir_recursive($upload_dir);
1328 }
1329
1330 if (!empty($this->trackid)) { // TODO Always use trackid (ticXXX) instead of track_id (abcd123)
1331 $keytoavoidconflict = '-'.$this->trackid;
1332 } else {
1333 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id;
1334 }
1335 unset($_SESSION["listofpaths".$keytoavoidconflict]);
1336 unset($_SESSION["listofnames".$keytoavoidconflict]);
1337 unset($_SESSION["listofmimes".$keytoavoidconflict]);
1338 }
1339
1346 public function showMessageForm($width = '40%')
1347 {
1348 global $conf, $langs, $user, $hookmanager, $form, $mysoc;
1349
1350 $formmail = new FormMail($this->db);
1351 $addfileaction = 'addfile';
1352
1353 if (!is_object($form)) {
1354 $form = new Form($this->db);
1355 }
1356
1357 // Load translation files required by the page
1358 $langs->loadLangs(array('other', 'mails', 'ticket'));
1359
1360 // Clear temp files. Must be done at beginning, before call of triggers
1361 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1362 $this->clear_attached_files();
1363 }
1364
1365 // Define output language
1366 $outputlangs = $langs;
1367 $newlang = '';
1368 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1369 $newlang = $this->param['langsmodels'];
1370 }
1371 if (!empty($newlang)) {
1372 $outputlangs = new Translate("", $conf);
1373 $outputlangs->setDefaultLang($newlang);
1374 $outputlangs->load('other');
1375 }
1376
1377 // Get message template for $this->param["models"] into c_email_templates
1378 $arraydefaultmessage = -1;
1379 if (isset($this->param['models']) && $this->param['models'] != 'none') {
1380 $model_id = 0;
1381 if (array_key_exists('models_id', $this->param)) {
1382 $model_id = (int) $this->param["models_id"];
1383 }
1384
1385 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id); // If $model_id is empty, preselect the first one
1386 }
1387
1388 // Define list of attached files
1389 $listofpaths = array();
1390 $listofnames = array();
1391 $listofmimes = array();
1392
1393 if (!empty($this->trackid)) {
1394 $keytoavoidconflict = '-'.$this->trackid;
1395 } else {
1396 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1397 }
1398 //var_dump($keytoavoidconflict);
1399 if (GETPOST('mode', 'alpha') == 'init' || (GETPOST('modelselected') && GETPOST('modelmailselected', 'alpha') && GETPOST('modelmailselected', 'alpha') != '-1')) {
1400 if (!empty($arraydefaultmessage->joinfiles) && !empty($this->param['fileinit']) && is_array($this->param['fileinit'])) {
1401 foreach ($this->param['fileinit'] as $path) {
1402 $formmail->add_attached_files($path, basename($path), dol_mimetype($path));
1403 }
1404 }
1405 }
1406 //var_dump($_SESSION);
1407 //var_dump($_SESSION["listofpaths".$keytoavoidconflict]);
1408 if (!empty($_SESSION["listofpaths".$keytoavoidconflict])) {
1409 $listofpaths = explode(';', $_SESSION["listofpaths".$keytoavoidconflict]);
1410 }
1411 if (!empty($_SESSION["listofnames".$keytoavoidconflict])) {
1412 $listofnames = explode(';', $_SESSION["listofnames".$keytoavoidconflict]);
1413 }
1414 if (!empty($_SESSION["listofmimes".$keytoavoidconflict])) {
1415 $listofmimes = explode(';', $_SESSION["listofmimes".$keytoavoidconflict]);
1416 }
1417
1418 // Define output language
1419 $outputlangs = $langs;
1420 $newlang = '';
1421 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && isset($this->param['langsmodels'])) {
1422 $newlang = $this->param['langsmodels'];
1423 }
1424 if (!empty($newlang)) {
1425 $outputlangs = new Translate("", $conf);
1426 $outputlangs->setDefaultLang($newlang);
1427 $outputlangs->load('other');
1428 }
1429
1430 print "\n<!-- Begin message_form TICKET -->\n";
1431
1432 $send_email = GETPOSTINT('send_email') ? GETPOSTINT('send_email') : 0;
1433
1434 // Example 1 : Adding jquery code
1435 print '<script nonce="'.getNonce().'" type="text/javascript">
1436 jQuery(document).ready(function() {
1437 send_email=' . $send_email.';
1438 if (send_email) {
1439 if (!jQuery("#send_msg_email").is(":checked")) {
1440 jQuery("#send_msg_email").prop("checked", true).trigger("change");
1441 }
1442 jQuery(".email_line").show();
1443 } else {
1444 if (!jQuery("#private_message").is(":checked")) {
1445 jQuery("#private_message").prop("checked", true).trigger("change");
1446 }
1447 jQuery(".email_line").hide();
1448 }
1449 ';
1450
1451 // If constant set, allow to send private messages as email
1452 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1453 print 'jQuery("#send_msg_email").click(function() {
1454 console.log("Click send_msg_email");
1455 if(jQuery(this).is(":checked")) {
1456 if (jQuery("#private_message").is(":checked")) {
1457 jQuery("#private_message").prop("checked", false).trigger("change");
1458 }
1459 jQuery(".email_line").show();
1460 }
1461 else {
1462 jQuery(".email_line").hide();
1463 }
1464 });
1465
1466 jQuery("#private_message").click(function() {
1467 console.log("Click private_message");
1468 if (jQuery(this).is(":checked")) {
1469 if (jQuery("#send_msg_email").is(":checked")) {
1470 jQuery("#send_msg_email").prop("checked", false).trigger("change");
1471 }
1472 jQuery(".email_line").hide();
1473 }
1474 });';
1475 }
1476
1477 print '});
1478 </script>';
1479
1480
1481 print '<form method="post" name="ticket" id="ticket" enctype="multipart/form-data" action="'.$this->param["returnurl"].'">';
1482 print '<input type="hidden" name="token" value="'.newToken().'">';
1483 print '<input type="hidden" name="action" value="'.$this->action.'">';
1484 print '<input type="hidden" name="actionbis" value="add_message">';
1485 print '<input type="hidden" name="backtopage" value="'.$this->backtopage.'">';
1486 if (!empty($this->trackid)) {
1487 print '<input type="hidden" name="trackid" value="'.$this->trackid.'">';
1488 } else {
1489 print '<input type="hidden" name="trackid" value="'.(empty($this->track_id) ? '' : $this->track_id).'">';
1490 $keytoavoidconflict = empty($this->track_id) ? '' : '-'.$this->track_id; // track_id instead of trackid
1491 }
1492 foreach ($this->param as $key => $value) {
1493 print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
1494 }
1495
1496 // Get message template
1497 $model_id = 0;
1498 if (array_key_exists('models_id', $this->param)) {
1499 $model_id = $this->param["models_id"];
1500 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
1501 }
1502
1503 $result = $formmail->fetchAllEMailTemplate(!empty($this->param["models"]) ? $this->param["models"] : "", $user, $outputlangs);
1504 if ($result < 0) {
1505 setEventMessages($this->error, $this->errors, 'errors');
1506 }
1507 $modelmail_array = array();
1508 foreach ($formmail->lines_model as $line) {
1509 $modelmail_array[$line->id] = $line->label;
1510 }
1511
1512 print '<table class="border" width="'.$width.'">';
1513
1514 // External users can't send message email
1515 if ($user->hasRight("ticket", "write") && !$user->socid) {
1516 $ticketstat = new Ticket($this->db);
1517 $res = $ticketstat->fetch('', '', $this->track_id);
1518
1519 print '<tr><td></td><td>';
1520 $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : (getDolGlobalInt('TICKETS_MESSAGE_FORCE_MAIL') ? 'checked' : ''));
1521 print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
1522 print '<label for="send_msg_email">'.$langs->trans('SendMessageByEmail').'</label>';
1523 $texttooltip = $langs->trans("TicketMessageSendEmailHelp");
1524 if (!getDolGlobalString('TICKET_SEND_PRIVATE_EMAIL')) {
1525 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2b");
1526 } else {
1527 $texttooltip .= ' '.$langs->trans("TicketMessageSendEmailHelp2a", '{s1}');
1528 }
1529 $texttooltip = str_replace('{s1}', $langs->trans('MarkMessageAsPrivate'), $texttooltip);
1530 print ' '.$form->textwithpicto('', $texttooltip, 1, 'help');
1531 print '</td></tr>';
1532
1533 // Private message (not visible by customer/external user)
1534 if (!$user->socid) {
1535 print '<tr><td></td><td>';
1536 $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : '');
1537 print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
1538 print '<label for="private_message">'.$langs->trans('MarkMessageAsPrivate').'</label>';
1539 print ' '.$form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
1540 print '</td></tr>';
1541 }
1542
1543 // Zone to select its email template
1544 if (count($modelmail_array) > 0) {
1545 print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
1546 print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1, 0, "", "", 0, 0, 0, '', 'minwidth200');
1547 if ($user->admin) {
1548 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1549 }
1550 print ' &nbsp; ';
1551 print '<input type="submit" class="button" value="'.$langs->trans('Apply').'" name="modelselected" id="modelselected">';
1552 print '</div></td>';
1553 }
1554
1555 // From
1556 $from = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_FROM');
1557 print '<tr class="email_line"><td><span class="">'.$langs->trans("MailFrom").'</span></td>';
1558 print '<td><span class="">'.img_picto('', 'email', 'class="pictofixedwidth"').$from.'</span></td></tr>';
1559
1560 // Subject/topic
1561 $topic = "";
1562 foreach ($formmail->lines_model as $line) {
1563 if (!empty($this->substit) && $this->param['models_id'] == $line->id) {
1564 $topic = make_substitutions($line->topic, $this->substit);
1565 break;
1566 }
1567 }
1568 print '<tr class="email_line"><td>'.$langs->trans('Subject').'</td>';
1569 if (empty($topic)) {
1570 print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '. $ticketstat->subject .'" />';
1571 } else {
1572 print '<td><input type="text" class="text minwidth500" name="subject" value="['.getDolGlobalString('MAIN_INFO_SOCIETE_NOM').' - '.$langs->trans("Ticket").' '.$ticketstat->ref.'] '.$topic.'" />';
1573 }
1574 print '</td></tr>';
1575
1576 // Recipients / adressed-to
1577 print '<tr class="email_line"><td>'.$langs->trans('MailRecipients');
1578 print ' '.$form->textwithpicto('', $langs->trans("TicketMessageRecipientsHelp"), 1, 'help');
1579 print '</td><td>';
1580 if ($res) {
1581 // Retrieve email of all contacts (internal and external)
1582 $contacts = $ticketstat->getInfosTicketInternalContact(1);
1583 $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact(1));
1584
1585 $sendto = array();
1586
1587 // Build array to display recipient list
1588 if (is_array($contacts) && count($contacts) > 0) {
1589 foreach ($contacts as $key => $info_sendto) {
1590 if ($info_sendto['email'] != '') {
1591 $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">").' <small class="opacitymedium">('.dol_escape_htmltag($info_sendto['libelle']).")</small>";
1592 }
1593 }
1594 }
1595
1596 if (!empty($ticketstat->origin_replyto) && !in_array($ticketstat->origin_replyto, $sendto)) {
1597 $sendto[] = dol_escape_htmltag($ticketstat->origin_replyto).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1598 } elseif ($ticketstat->origin_email && !in_array($ticketstat->origin_email, $sendto)) {
1599 $sendto[] = dol_escape_htmltag($ticketstat->origin_email).' <small class="opacitymedium">('.$langs->trans("TicketEmailOriginIssuer").")</small>";
1600 }
1601
1602 if ($ticketstat->fk_soc > 0) {
1603 $ticketstat->socid = $ticketstat->fk_soc;
1604 $ticketstat->fetch_thirdparty();
1605
1606 if (!empty($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
1607 $sendto[] = $ticketstat->thirdparty->email.' <small class="opacitymedium">('.$langs->trans('Customer').')</small>';
1608 }
1609 }
1610
1611 if (getDolGlobalInt('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS')) {
1612 $sendto[] = getDolGlobalString('TICKET_NOTIFICATION_EMAIL_TO').' <small class="opacitymedium">(generic email)</small>';
1613 }
1614
1615 // Print recipient list
1616 if (is_array($sendto) && count($sendto) > 0) {
1617 print img_picto('', 'email', 'class="pictofixedwidth"');
1618 print implode(', ', $sendto);
1619 } else {
1620 print '<div class="warning">'.$langs->trans('WarningNoEMailsAdded').' '.$langs->trans('TicketGoIntoContactTab').'</div>';
1621 }
1622 }
1623 print '</td></tr>';
1624 }
1625
1626 $uselocalbrowser = false;
1627
1628 // Intro
1629 // External users can't send message email
1630 /*
1631 if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_INTRO)) {
1632 $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
1633 print '<tr class="email_line"><td><label for="mail_intro">';
1634 print $form->textwithpicto($langs->trans("TicketMessageMailIntro"), $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
1635 print '</label>';
1636
1637 print '</td><td>';
1638 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1639
1640 $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_2, 70);
1641
1642 $doleditor->Create();
1643 print '</td></tr>';
1644 }
1645 */
1646
1647 // Attached files
1648 if (!empty($this->withfile)) {
1649 $out = '<tr>';
1650 $out .= '<td>'.$langs->trans("MailFile").'</td>';
1651 $out .= '<td>';
1652 // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
1653 $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">'."\n";
1654 $out .= '<script nonce="'.getNonce().'" type="text/javascript">';
1655 $out .= 'jQuery(document).ready(function () {';
1656 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1657 $out .= ' jQuery("#addedfile").on("change", function() {';
1658 $out .= ' if (jQuery(this).val().length) {';
1659 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", false);';
1660 $out .= ' } else {';
1661 $out .= ' jQuery("#'.$addfileaction.'").prop("disabled", true);';
1662 $out .= ' }';
1663 $out .= ' });';
1664 $out .= ' jQuery(".removedfile").click(function() {';
1665 $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
1666 $out .= ' });';
1667 $out .= '})';
1668 $out .= '</script>'."\n";
1669
1670 if (count($listofpaths)) {
1671 foreach ($listofpaths as $key => $val) {
1672 $out .= '<div id="attachfile_'.$key.'">';
1673 $out .= img_mime($listofnames[$key]).' '.$listofnames[$key];
1674 if (!$this->withfilereadonly) {
1675 $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.'" />';
1676 }
1677 $out .= '<br></div>';
1678 }
1679 } else {
1680 //$out .= $langs->trans("NoAttachedFiles").'<br>';
1681 }
1682 if ($this->withfile == 2) { // Can add other files
1683 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
1684 $out .= ' ';
1685 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="'.$addfileaction.'" name="'.$addfileaction.'" value="'.$langs->trans("MailingAddFile").'" />';
1686 }
1687 $out .= "</td></tr>\n";
1688
1689 print $out;
1690 }
1691
1692 // MESSAGE
1693
1694 $defaultmessage = "";
1695 if (is_object($arraydefaultmessage) && $arraydefaultmessage->content) {
1696 $defaultmessage = $arraydefaultmessage->content;
1697 }
1698 $defaultmessage = str_replace('\n', "\n", $defaultmessage);
1699
1700 // Deal with format differences between message and signature (text / HTML)
1701 if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1702 $this->substit['__USER_SIGNATURE__'] = dol_nl2br($this->substit['__USER_SIGNATURE__']);
1703 } elseif (!dol_textishtml($defaultmessage) && isset($this->substit['__USER_SIGNATURE__']) && dol_textishtml($this->substit['__USER_SIGNATURE__'])) {
1704 $defaultmessage = dol_nl2br($defaultmessage);
1705 }
1706 if (GETPOSTISSET("message") && !GETPOST('modelselected')) {
1707 $defaultmessage = GETPOST('message', 'restricthtml');
1708 } else {
1709 $defaultmessage = make_substitutions($defaultmessage, $this->substit);
1710 // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
1711 $defaultmessage = preg_replace("/^(<br>)+/", "", $defaultmessage);
1712 $defaultmessage = preg_replace("/^\n+/", "", $defaultmessage);
1713 }
1714
1715 print '<tr><td colspan="2"><label for="message"><span class="fieldrequired">'.$langs->trans("Message").'</span>';
1716 if ($user->hasRight("ticket", "write") && !$user->socid) {
1717 $texttooltip = $langs->trans("TicketMessageHelp");
1718 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO') || getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1719 $texttooltip .= '<br><br>'.$langs->trans("ForEmailMessageWillBeCompletedWith").'...';
1720 }
1721 if (getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO')) {
1722 $mail_intro = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO'), $this->substit);
1723 print '<input type="hidden" name="mail_intro" value="'.$mail_intro.'">';
1724 $texttooltip .= '<br><u>'.$langs->trans("TicketMessageMailIntro").'</u><br>'.$mail_intro;
1725 }
1726 if (getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE')) {
1727 $mail_signature = make_substitutions(getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE'), $this->substit);
1728 print '<input type="hidden" name="mail_signature" value="'.$mail_signature.'">';
1729 $texttooltip .= '<br><br><u>'.$langs->trans("TicketMessageMailFooter").'</u><br>'.$mail_signature;
1730 }
1731 print $form->textwithpicto('', $texttooltip, 1, 'help');
1732 }
1733 print '</label></td></tr>';
1734
1735
1736 print '<tr><td colspan="2">';
1737 //$toolbarname = 'dolibarr_details';
1738 $toolbarname = 'dolibarr_notes';
1739 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1740 $doleditor = new DolEditor('message', $defaultmessage, '100%', 200, $toolbarname, '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_5, '90%');
1741 $doleditor->Create();
1742 print '</td></tr>';
1743
1744 // Footer
1745 // External users can't send message email
1746 /*if ($user->rights->ticket->write && !$user->socid && !empty($conf->global->TICKET_MESSAGE_MAIL_SIGNATURE)) {
1747 $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
1748 print '<tr class="email_line"><td><label for="mail_intro">'.$langs->trans("TicketMessageMailFooter").'</label>';
1749 print $form->textwithpicto('', $langs->trans("TicketMessageMailFooterHelp"), 1, 'help');
1750 print '</td><td>';
1751 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
1752 $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 90, 'dolibarr_details', '', false, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), ROWS_2, 70);
1753 $doleditor->Create();
1754 print '</td></tr>';
1755 }
1756 */
1757
1758 print '</table>';
1759
1760 print '<br><center>';
1761 print '<input type="submit" class="button" name="btn_add_message" value="'.$langs->trans("Add").'"';
1762 // Add a javascript test to avoid to forget to submit file before sending email
1763 if ($this->withfile == 2 && !empty($conf->use_javascript_ajax)) {
1764 print ' onClick="if (document.ticket.addedfile.value != \'\') { alert(\''.dol_escape_js($langs->trans("FileWasNotUploaded")).'\'); return false; } else { return true; }"';
1765 }
1766 print ' />';
1767 if (!empty($this->withcancel)) {
1768 print " &nbsp; &nbsp; ";
1769 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
1770 }
1771 print "</center>\n";
1772
1773 print '<input type="hidden" name="page_y">'."\n";
1774
1775 print "</form><br>\n";
1776
1777 // Disable enter key if option MAIN_MAILFORM_DISABLE_ENTERKEY is set
1778 if (getDolGlobalString('MAIN_MAILFORM_DISABLE_ENTERKEY')) {
1779 print '<script type="text/javascript">';
1780 print 'jQuery(document).ready(function () {';
1781 print ' $(document).on("keypress", \'#ticket\', function (e) { /* Note this is called at every key pressed ! */
1782 var code = e.keyCode || e.which;
1783 if (code == 13) {
1784 console.log("Enter was intercepted and blocked");
1785 e.preventDefault();
1786 return false;
1787 }
1788 });';
1789 print '})';
1790 print '</script>';
1791 }
1792
1793 print "<!-- End form TICKET -->\n";
1794 }
1795}
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:137
getMaxFileSizeArray()
Return the max allowed for file upload.