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