dolibarr 21.0.0-alpha
html.formticket.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2015 Jean-François FERRY <hello@librethic.io>
3 * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
4 * Copyright (C) 2019-2024 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2021 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2023 Charlene Benke <charlene.r@patas-monkey.com>
8 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2024 Irvine FLEITH <irvine.fleith@atm-consulting.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 */
24
31require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
32require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
33require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
34
35if (!class_exists('FormCompany')) {
36 include DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
37}
38
48{
52 public $db;
53
57 public $track_id;
58
62 public $trackid;
63
67 public $fk_user_create;
68
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 if ($this->withref) {
247 // Ref
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>';
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');
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');
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);
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';
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')) {
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">'.$langs->trans("Categories").'</td><td>';
515 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
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>'.$langs->trans("MailFile").'</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 } else {
560 $out .= '<span class="opacitymedium">'.$langs->trans("NoAttachedFiles").'</span><br>';
561 }
562 if ($this->withfile == 2) { // Can add other files
563 $maxfilesizearray = getMaxFileSizeArray();
564 $maxmin = $maxfilesizearray['maxmin'];
565 if ($maxmin > 0) {
566 $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
567 }
568 $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="'.$langs->trans("Upload").'" />';
569 $out .= ' ';
570 $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="'.$langs->trans("MailingAddFile").'" />';
571 }
572 $out .= "</td></tr>\n";
573
574 print $out;
575 }
576
577 // User of creation
578 if ($this->withusercreate > 0 && $this->fk_user_create) {
579 print '<tr><td class="titlefield">'.$langs->trans("CreatedBy").'</td><td>';
580 $langs->load("users");
581 $fuser = new User($this->db);
582
583 if ($this->withcreatereadonly) {
584 if ($res = $fuser->fetch($this->fk_user_create)) {
585 print $fuser->getNomUrl(1);
586 }
587 }
588 print ' &nbsp; ';
589 print "</td></tr>\n";
590 }
591
592 // Customer or supplier
593 if ($this->withcompany) {
594 // force company and contact id for external user
595 if (empty($user->socid)) {
596 // Company
597 print '<tr><td class="titlefield">'.$langs->trans("ThirdParty").'</td><td>';
598 $events = array();
599 $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
600 print img_picto('', 'company', 'class="paddingright"');
601 print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, '', $events, 0, 'minwidth200');
602 print '</td></tr>';
603 if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
604 $htmlname = 'socid';
605 print '<script nonce="'.getNonce().'" type="text/javascript">
606 $(document).ready(function () {
607 jQuery("#'.$htmlname.'").change(function () {
608 var obj = '.json_encode($events).';
609 $.each(obj, function(key,values) {
610 if (values.method.length) {
611 runJsCodeForEvent'.$htmlname.'(values);
612 }
613 });
614 });
615
616 function runJsCodeForEvent'.$htmlname.'(obj) {
617 console.log("Run runJsCodeForEvent'.$htmlname.'");
618 var id = $("#'.$htmlname.'").val();
619 var method = obj.method;
620 var url = obj.url;
621 var htmlname = obj.htmlname;
622 var showempty = obj.showempty;
623 $.getJSON(url,
624 {
625 action: method,
626 id: id,
627 htmlname: htmlname,
628 showempty: showempty
629 },
630 function(response) {
631 $.each(obj.params, function(key,action) {
632 if (key.length) {
633 var num = response.num;
634 if (num > 0) {
635 $("#" + key).removeAttr(action);
636 } else {
637 $("#" + key).attr(action, action);
638 }
639 }
640 });
641 $("select#" + htmlname).html(response.value);
642 if (response.num) {
643 var selecthtml_str = response.value;
644 var selecthtml_dom=$.parseHTML(selecthtml_str);
645 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
646 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
647 }
648 } else {
649 $("#inputautocomplete"+htmlname).val("");
650 }
651 $("select#" + htmlname).change(); /* Trigger event change */
652 }
653 );
654 }
655 });
656 </script>';
657 }
658 if ($mode == 'create') {
659 // Contact and type
660 print '<tr><td>'.$langs->trans("Contact").'</td><td>';
661 // If no socid, set to -1 to avoid full contacts list
662 $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
663 print img_picto('', 'contact', 'class="paddingright"');
664 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
665 print $form->select_contact($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 1, 'maxwidth300 widthcentpercentminusx', true);
666
667 print ' ';
668 $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
669 print '</td></tr>';
670 }
671 } else {
672 print '<tr><td class="titlefield"><input type="hidden" name="socid" value="'.$user->socid.'"/></td>';
673 print '<td><input type="hidden" name="contactid" value="'.$user->contact_id.'"/></td>';
674 print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
675 }
676
677 // Notify thirdparty at creation
678 if (empty($this->ispublic) && $action == 'create') {
679 print '<tr><td><label for="notify_tiers_at_create">'.$langs->trans("TicketNotifyTiersAtCreation").'</label></td><td>';
680 print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate ? ' checked="checked"' : '').'>';
681 print '</td></tr>';
682 }
683
684 // User assigned
685 print '<tr><td>';
686 print $langs->trans("AssignedTo");
687 print '</td><td>';
688 print img_picto('', 'user', 'class="pictofixedwidth"');
689 print $form->select_dolusers($user_assign, 'fk_user_assign', 1);
690 print '</td>';
691 print '</tr>';
692 }
693
694 if ($subelement != 'project') {
695 if (isModEnabled('project') && !$this->ispublic) {
696 $formproject = new FormProjets($this->db);
697 print '<tr><td><label for="project"><span class="">'.$langs->trans("Project").'</span></label></td><td>';
698 print img_picto('', 'project').$formproject->select_projects(-1, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
699 print '</td></tr>';
700 }
701 }
702
703 if ($subelement != 'contract') {
704 if (isModEnabled('contract') && !$this->ispublic) {
705 $langs->load('contracts');
706 $formcontract = new FormContract($this->db);
707 print '<tr><td><label for="contract"><span class="">'.$langs->trans("Contract").'</span></label></td><td>';
708 print img_picto('', 'contract');
709 print $formcontract->select_contract(-1, GETPOSTINT('contactid'), 'contractid', 0, 1, 1, 1);
710 print '</td></tr>';
711 }
712 }
713
714 // Other attributes
715 $parameters = array();
716 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
717 if (empty($reshook)) {
718 if ($mode == 'create') {
719 print $object->showOptionals($extrafields, 'create');
720 } else {
721 print $object->showOptionals($extrafields, 'edit');
722 }
723 }
724
725 print '</table>';
726
727 if ($withdolfichehead) {
728 print dol_get_fiche_end();
729 }
730
731 print '<br><br>';
732
733 if ($mode == 'create') {
734 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "CreateTicket"), ($this->withcancel ? "Cancel" : ""));
735 } else {
736 print $form->buttonsSaveCancel(((isset($this->withreadid) && $this->withreadid > 0) ? "SendResponse" : "Save"), ($this->withcancel ? "Cancel" : ""));
737 }
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" && !$selected && !$empty) {
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" && !$selected && !$empty) {
933 print ' selected="selected"';
934 } elseif (count($ticketstat->cache_category_tickets) == 1) {
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 if ($filtertype == 'public=1') {
1005 $sql .= " AND ctc.public = 1";
1006 }
1007 $sql .= " AND ctc.fk_parent = 0";
1008 $sql .= $this->db->order('ctc.pos', 'ASC');
1009
1010 $resql = $this->db->query($sql);
1011 if ($resql) {
1012 $num_rows_level0 = $this->db->num_rows($resql);
1013 $i = 0;
1014 while ($i < $num_rows_level0) {
1015 $obj = $this->db->fetch_object($resql);
1016 if ($obj) {
1017 $label = ($obj->label != '-' ? $obj->label : '');
1018 if ($outputlangs->trans("TicketCategoryShort".$obj->code) != "TicketCategoryShort".$obj->code) {
1019 $label = $outputlangs->trans("TicketCategoryShort".$obj->code);
1020 } elseif ($outputlangs->trans($obj->code) != $obj->code) {
1021 $label = $outputlangs->trans($obj->code);
1022 }
1023
1024 $grouprowid = $obj->rowid;
1025 $groupvalue = $obj->code;
1026 $grouplabel = $label;
1027
1028 $isparent = $obj->isparent;
1029 if (is_array($selectedgroups)) {
1030 $iselected = in_array($obj->code, $selectedgroups) ? 'selected' : '';
1031 } else {
1032 $iselected = $groupticket == $obj->code ? 'selected' : '';
1033 }
1034 $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>';
1035 if ($isparent == 'NOTPARENT') {
1036 $arraycodenotparent[] = $groupvalue;
1037 }
1038 $arrayidused[] = $grouprowid;
1039 $arrayidusedconcat[] = $grouprowid;
1040 }
1041 $i++;
1042 }
1043 } else {
1044 dol_print_error($this->db);
1045 }
1046 if (count($arrayidused) == 1) {
1047 return '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.dol_escape_htmltag($groupvalue).'">';
1048 } else {
1049 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'_select" class="maxwidth500 minwidth400" value="'.GETPOST($htmlname).'">';
1050 $stringtoprint .= '<input type="hidden" name="'.$htmlname.'_child_id" id="'.$htmlname.'_select_child_id" class="maxwidth500 minwidth400" '.GETPOST($htmlname).' value="'.GETPOST($htmlname."_child_id").'">';
1051 }
1052 $stringtoprint .= '</select>&nbsp;';
1053
1054 $levelid = 1; // The first combobox
1055 while ($levelid <= $use_multilevel) { // Loop to take the child of the combo
1056 $tabscript = array();
1057 $stringtoprint .= '<select id="'.$htmlname.'_child_'.$levelid.'" class="maxwidth500 minwidth400 groupticketchild" child_id="'.$levelid.'">';
1058 $stringtoprint .= '<option value="">&nbsp;</option>';
1059
1060 $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctc.public, ctcjoin.code as codefather";
1061 $sql .= " FROM ".$this->db->prefix()."c_ticket_category as ctc";
1062 $sql .= " JOIN ".$this->db->prefix()."c_ticket_category as ctcjoin ON ctc.fk_parent = ctcjoin.rowid";
1063 $sql .= " WHERE ctc.active > 0 AND ctc.entity = ".((int) $conf->entity);
1064 $sql .= " AND ctc.rowid NOT IN (".$this->db->sanitize(implode(',', $arrayidusedconcat)).")";
1065
1066 if ($filtertype == 'public=1') {
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" && !$selected && !$empty) {
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 ($this->param['models_id'] == $line->id) {
1562 $topic = $line->topic;
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="'.make_substitutions($topic, $this->substit).'" />';
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.
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.