FormTicket::selectGroupTickets()   F
last analyzed

Complexity

Conditions 79
Paths 12548

Size

Total Lines 336
Code Lines 211

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 79
eloc 211
nc 12548
nop 10
dl 0
loc 336
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2013-2015  Jean-François FERRY         <[email protected]>
4
 * Copyright (C) 2016       Christophe Battarel         <[email protected]>
5
 * Copyright (C) 2019-2024  Frédéric France             <[email protected]>
6
 * Copyright (C) 2021       Juanjo Menent               <[email protected]>
7
 * Copyright (C) 2021       Alexandre Spangaro          <[email protected]>
8
 * Copyright (C) 2023       Charlene Benke	            <[email protected]>
9
 * Copyright (C) 2024		MDW							<[email protected]>
10
 * Copyright (C) 2024	    Irvine FLEITH		        <[email protected]>
11
 * Copyright (C) 2024       Rafael San José             <[email protected]>
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 3 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25
 */
26
27
namespace Dolibarr\Code\Core\Classes;
28
29
use Dolibarr\Code\Categories\Classes\Categorie;
30
use Dolibarr\Code\Contact\Classes\Contact;
31
use Dolibarr\Code\Societe\Classes\Societe;
32
use Dolibarr\Code\Ticket\Classes\Ticket;
33
use Dolibarr\Code\User\Classes\User;
34
use DoliDB;
35
36
/**
37
 *    \file       htdocs/core/class/html.formticket.class.php
38
 *    \ingroup    ticket
39
 *    \brief      File of class to generate the form for creating a new ticket.
40
 */
41
42
if (!class_exists('FormCompany')) {
43
    include DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php';
44
}
45
46
/**
47
 * Class to generate the form for creating a new ticket.
48
 * Usage:   $formticket = new FormTicket($db)
49
 *          $formticket->proprietes = 1 or string or array of values
50
 *          $formticket->show_form()  shows the form
51
 *
52
 * @package Ticket
53
 */
54
class FormTicket
55
{
56
    /**
57
     * @var DoliDB Database handler.
58
     */
59
    public $db;
60
61
    /**
62
     * @var string      A hash value of the ticket. Duplicate of ref but for public purposes.
63
     */
64
    public $track_id;
65
66
    /**
67
     * @var string      Email $trackid. Used also for the $keytoavoidconflict to name session vars to upload files.
68
     */
69
    public $trackid;
70
71
    /**
72
     * @var int ID
73
     */
74
    public $fk_user_create;
75
76
    public $message;
77
    public $topic_title;
78
79
    public $action;
80
81
    public $withtopic;
82
    public $withemail;
83
84
    /**
85
     * @var int $withsubstit Show substitution array
86
     */
87
    public $withsubstit;
88
89
    public $withfile;
90
    public $withfilereadonly;
91
92
    public $backtopage;
93
94
    public $ispublic;  // to show information or not into public form
95
96
    public $withtitletopic;
97
    public $withtopicreadonly;
98
    public $withreadid;
99
100
    public $withcompany;  // to show company drop-down list
101
    public $withfromsocid;
102
    public $withfromcontactid;
103
    public $withnotifytiersatcreate;
104
    public $withusercreate;  // to show name of creating user in form
105
    public $withcreatereadonly;
106
107
    /**
108
     * @var int withextrafields
109
     */
110
    public $withextrafields;
111
112
    public $withref;  // to show ref field
113
    public $withcancel;
114
115
    public $type_code;
116
    public $category_code;
117
    public $severity_code;
118
119
120
    /**
121
     *
122
     * @var array $substit Substitutions
123
     */
124
    public $substit = array();
125
    public $param = array();
126
127
    /**
128
     * @var string Error code (or message)
129
     */
130
    public $error;
131
    public $errors = array();
132
133
134
    /**
135
     * Constructor
136
     *
137
     * @param DoliDB $db Database handler
138
     */
139
    public function __construct($db)
140
    {
141
        global $conf;
142
143
        $this->db = $db;
144
145
        $this->action = 'add';
146
147
        $this->withcompany = !getDolGlobalInt("TICKETS_NO_COMPANY_ON_FORM") && isModEnabled("societe");
148
        $this->withfromsocid = 0;
149
        $this->withfromcontactid = 0;
150
        $this->withreadid = 0;
151
        //$this->withtitletopic='';
152
        $this->withnotifytiersatcreate = 0;
153
        $this->withusercreate = 1;
154
        $this->withcreatereadonly = 1;
155
        $this->withemail = 0;
156
        $this->withref = 0;
157
        $this->withextrafields = 0;  // to show extrafields or not
158
        //$this->withtopicreadonly=0;
159
    }
160
161
    /**
162
     *
163
     * Check required fields
164
     *
165
     * @param array<string, array<string, string>> $fields Array of fields to check
166
     * @param int $errors Reference of errors variable
167
     * @return void
168
     */
169
    public static function checkRequiredFields(array $fields, int &$errors)
170
    {
171
        global $langs;
172
173
        foreach ($fields as $field => $type) {
174
            if (!GETPOST($field, $type['check'])) {
175
                $errors++;
176
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities($type['langs'])), null, 'errors');
177
            }
178
        }
179
    }
180
181
    /**
182
     * Show the form to input ticket
183
     *
184
     * @param   int             $withdolfichehead       With dol_get_fiche_head() and dol_get_fiche_end()
185
     * @param   string          $mode                   Mode ('create' or 'edit')
186
     * @param   int             $public                 1=If we show the form for the public interface
187
     * @param   Contact|null    $with_contact           [=NULL] Contact to link to this ticket if it exists
188
     * @param   string          $action                 [=''] Action in card
189
     * @param   ?Ticket         $object                 [=NULL] Ticket object
190
     * @return  void
191
     */
192
    public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0, Contact $with_contact = null, $action = '', Ticket $object = null)
193
    {
194
        global $conf, $langs, $user, $hookmanager;
195
196
        // Load translation files required by the page
197
        $langs->loadLangs(array('other', 'mails', 'ticket'));
198
199
        if ($mode == 'create') {
200
            $ref = GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : '';
201
            $type_code = GETPOSTISSET('type_code') ? GETPOST('type_code', 'alpha') : '';
202
            $category_code = GETPOSTISSET('category_code') ? GETPOST('category_code', 'alpha') : '';
203
            $severity_code = GETPOSTISSET('severity_code') ? GETPOST('severity_code', 'alpha') : '';
204
            $subject = GETPOSTISSET('subject') ? GETPOST('subject', 'alpha') : '';
205
            $email = GETPOSTISSET('email') ? GETPOST('email', 'alpha') : '';
206
            $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : '';
207
            $projectid = GETPOSTISSET('projectid') ? GETPOST('projectid', 'int') : '';
208
            $user_assign = GETPOSTISSET('fk_user_assign') ? GETPOSTINT('fk_user_assign') : $this->fk_user_create;
209
        } else {
210
            $ref = GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $object->ref;
211
            $type_code = GETPOSTISSET('type_code') ? GETPOST('type_code', 'alpha') : $object->type_code;
212
            $category_code = GETPOSTISSET('category_code') ? GETPOST('category_code', 'alpha') : $object->category_code;
213
            $severity_code = GETPOSTISSET('severity_code') ? GETPOST('severity_code', 'alpha') : $object->severity_code;
214
            $subject = GETPOSTISSET('subject') ? GETPOST('subject', 'alpha') : $object->subject;
215
            $email = GETPOSTISSET('email') ? GETPOST('email', 'alpha') : $object->email_from;
216
            $msg = GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : $object->message;
217
            $projectid = GETPOSTISSET('projectid') ? GETPOST('projectid', 'int') : $object->fk_project;
218
            $user_assign = GETPOSTISSET('fk_user_assign') ? GETPOSTINT('fk_user_assign') : $object->fk_user_assign;
219
        }
220
221
        $form = new Form($this->db);
222
        $formcompany = new FormCompany($this->db);
223
        $ticketstatic = new Ticket($this->db);
224
225
        $soc = new Societe($this->db);
226
        if (!empty($this->withfromsocid) && $this->withfromsocid > 0) {
227
            $soc->fetch($this->withfromsocid);
228
        }
229
230
        $ticketstat = new Ticket($this->db);
231
232
        $extrafields = new ExtraFields($this->db);
233
        $extrafields->fetch_name_optionals_label($ticketstat->table_element);
234
235
        print "\n<!-- Begin form TICKET -->\n";
236
237
        if ($withdolfichehead) {
238
            print dol_get_fiche_head(null, 'card', '', 0, '');
239
        }
240
241
        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']) . '">';
242
        print '<input type="hidden" name="token" value="' . newToken() . '">';
243
        print '<input type="hidden" name="action" value="' . $this->action . '">';
244
        if (!empty($object->id)) print '<input type="hidden" name="id" value="' . $object->id . '">';
245
        print '<input type="hidden" name="trackid" value="' . $this->trackid . '">';
246
        foreach ($this->param as $key => $value) {
247
            print '<input type="hidden" name="' . $key . '" value="' . $value . '">';
248
        }
249
        print '<input type="hidden" name="fk_user_create" value="' . $this->fk_user_create . '">';
250
251
        print '<table class="border centpercent">';
252
253
        if ($this->withref) {
254
            // Ref
255
            $defaultref = $ticketstat->getDefaultRef();
256
257
            if ($mode == 'edit') {
258
                $defaultref = $object->ref;
259
            }
260
            print '<tr><td class="titlefieldcreate"><span class="fieldrequired">' . $langs->trans("Ref") . '</span></td><td>';
261
            print '<input type="text" name="ref" value="' . dol_escape_htmltag($defaultref) . '">';
262
            print '</td></tr>';
263
        }
264
265
        // TITLE
266
        if ($this->withemail) {
267
            print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">' . $langs->trans("Email") . '</span></label></td><td>';
268
            print '<input class="text minwidth200" id="email" name="email" value="' . $email . '" autofocus>';
269
            print '</td></tr>';
270
271
            if ($with_contact) {
272
                // contact search and result
273
                $html_contact_search = '';
274
                $html_contact_search .= '<tr id="contact_search_line">';
275
                $html_contact_search .= '<td class="titlefield">';
276
                $html_contact_search .= '<label for="contact"><span class="fieldrequired">' . $langs->trans('Contact') . '</span></label>';
277
                $html_contact_search .= '<input type="hidden" id="contact_id" name="contact_id" value="" />';
278
                $html_contact_search .= '</td>';
279
                $html_contact_search .= '<td id="contact_search_result"></td>';
280
                $html_contact_search .= '</tr>';
281
                print $html_contact_search;
282
                // contact lastname
283
                $html_contact_lastname = '';
284
                $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>';
285
                $html_contact_lastname .= '<input type="text" id="contact_lastname" name="contact_lastname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_lastname') ? GETPOST('contact_lastname', 'alphanohtml') : '') . '" />';
286
                $html_contact_lastname .= '</td></tr>';
287
                print $html_contact_lastname;
288
                // contact firstname
289
                $html_contact_firstname = '';
290
                $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>';
291
                $html_contact_firstname .= '<input type="text" id="contact_firstname" name="contact_firstname" value="' . dol_escape_htmltag(GETPOSTISSET('contact_firstname') ? GETPOST('contact_firstname', 'alphanohtml') : '') . '" />';
292
                $html_contact_firstname .= '</td></tr>';
293
                print $html_contact_firstname;
294
                // company name
295
                $html_company_name = '';
296
                $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>';
297
                $html_company_name .= '<input type="text" id="company_name" name="company_name" value="' . dol_escape_htmltag(GETPOSTISSET('company_name') ? GETPOST('company_name', 'alphanohtml') : '') . '" />';
298
                $html_company_name .= '</td></tr>';
299
                print $html_company_name;
300
                // contact phone
301
                $html_contact_phone = '';
302
                $html_contact_phone .= '<tr id="contact_phone_line" class="contact_field"><td><label for="contact_phone"><span>' . $langs->trans('Phone') . '</span></label></td><td>';
303
                $html_contact_phone .= '<input type="text" id="contact_phone" name="contact_phone" value="' . dol_escape_htmltag(GETPOSTISSET('contact_phone') ? GETPOST('contact_phone', 'alphanohtml') : '') . '" />';
304
                $html_contact_phone .= '</td></tr>';
305
                print $html_contact_phone;
306
307
                // search contact form email
308
                $langs->load('errors');
309
                print '<script nonce="' . getNonce() . '" type="text/javascript">
310
                    jQuery(document).ready(function() {
311
                        var contact = jQuery.parseJSON("' . dol_escape_js(json_encode($with_contact), 2) . '");
312
                        jQuery("#contact_search_line").hide();
313
                        if (contact) {
314
                        	if (contact.id > 0) {
315
                        		jQuery("#contact_search_line").show();
316
                        		jQuery("#contact_id").val(contact.id);
317
								jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
318
								jQuery(".contact_field").hide();
319
                        	} else {
320
                        		jQuery(".contact_field").show();
321
                        	}
322
                        }
323
324
                    	jQuery("#email").change(function() {
325
                            jQuery("#contact_search_line").show();
326
                            jQuery("#contact_search_result").html("' . dol_escape_js($langs->trans('Select2SearchInProgress')) . '");
327
                            jQuery("#contact_id").val("");
328
                            jQuery("#contact_lastname").val("");
329
                            jQuery("#contact_firstname").val("");
330
                            jQuery("#company_name").val("");
331
                            jQuery("#contact_phone").val("");
332
333
                            jQuery.getJSON(
334
                                "' . dol_escape_js(dol_buildpath('/public/ticket/ajax/ajax.php', 1)) . '",
335
								{
336
									action: "getContacts",
337
									email: jQuery("#email").val()
338
								},
339
								function(response) {
340
									if (response.error) {
341
                                        jQuery("#contact_search_result").html("<span class=\"error\">"+response.error+"</span>");
342
									} else {
343
                                        var contact_list = response.contacts;
344
										if (contact_list.length == 1) {
345
                                            var contact = contact_list[0];
346
											jQuery("#contact_id").val(contact.id);
347
											jQuery("#contact_search_result").html(contact.firstname+" "+contact.lastname);
348
                                            jQuery(".contact_field").hide();
349
										} else if (contact_list.length <= 0) {
350
                                            jQuery("#contact_search_line").hide();
351
                                            jQuery(".contact_field").show();
352
										}
353
									}
354
								}
355
                            ).fail(function(jqxhr, textStatus, error) {
356
    							var error_msg = "' . dol_escape_js($langs->trans('ErrorAjaxRequestFailed')) . '"+" ["+textStatus+"] : "+error;
357
                                jQuery("#contact_search_result").html("<span class=\"error\">"+error_msg+"</span>");
358
                            });
359
                        });
360
                    });
361
                    </script>';
362
            }
363
        }
364
365
        // If ticket created from another object
366
        $subelement = '';
367
        if (isset($this->param['origin']) && $this->param['originid'] > 0) {
368
            // Parse element/subelement (ex: project_task)
369
            $element = $subelement = $this->param['origin'];
370
            $regs = array();
371
            if (preg_match('/^([^_]+)_([^_]+)/i', $this->param['origin'], $regs)) {
372
                $element = $regs[1];
373
                $subelement = $regs[2];
374
            }
375
376
            dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
377
            $classname = ucfirst($subelement);
378
            $objectsrc = new $classname($this->db);
379
            $objectsrc->fetch(GETPOSTINT('originid'));
380
381
            if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
382
                $objectsrc->fetch_lines();
383
            }
384
385
            $objectsrc->fetch_thirdparty();
386
            $newclassname = $classname;
387
            print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2"><input name="' . $subelement . 'id" value="' . GETPOST('originid') . '" type="hidden" />' . $objectsrc->getNomUrl(1) . '</td></tr>';
388
        }
389
390
        // Type of Ticket
391
        print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">' . $langs->trans("TicketTypeRequest") . '</span></label></td><td>';
392
        $this->selectTypesTickets($type_code, 'type_code', '', 2, 1, 0, 0, 'minwidth200');
393
        print '</td></tr>';
394
395
        // Group => Category
396
        print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">' . $langs->trans("TicketCategory") . '</span></label></td><td>';
397
        $filter = '';
398
        if ($public) {
399
            $filter = 'public=1';
400
        }
401
        $this->selectGroupTickets($category_code, 'category_code', $filter, 2, 1, 0, 0, 'minwidth200');
402
        print '</td></tr>';
403
404
        // Severity => Priority
405
        print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">' . $langs->trans("TicketSeverity") . '</span></label></td><td>';
406
        $this->selectSeveritiesTickets($severity_code, 'severity_code', '', 2, 1);
407
        print '</td></tr>';
408
409
        if (isModEnabled('knowledgemanagement')) {
410
            // KM Articles
411
            print '<tr id="KWwithajax" class="hidden"><td></td></tr>';
412
            print '<!-- Script to manage change of ticket group -->
413
			<script nonce="' . getNonce() . '">
414
			jQuery(document).ready(function() {
415
				function groupticketchange() {
416
					console.log("We called groupticketchange, so we try to load list KM linked to event");
417
					$("#KWwithajax").html("");
418
					idgroupticket = $("#selectcategory_code").val();
419
420
					console.log("We have selected id="+idgroupticket);
421
422
					if (idgroupticket != "") {
423
						$.ajax({ url: \'' . constant('BASE_URL') . '/core/ajax/fetchKnowledgeRecord.php\',
424
							 data: { action: \'getKnowledgeRecord\', idticketgroup: idgroupticket, token: \'' . newToken() . '\', lang:\'' . $langs->defaultlang . '\', public:' . ($public) . ' },
425
							 type: \'GET\',
426
							 success: function(response) {
427
								var urllist = \'\';
428
								console.log("We received response "+response);
429
								if (typeof response == "object") {
430
									console.log("response is already type object, no need to parse it");
431
								} else {
432
									console.log("response is type "+(typeof response));
433
									response = JSON.parse(response);
434
								}
435
								for (key in response) {
436
									answer = response[key].answer;
437
									urllist += \'<li><a href="#" title="\'+response[key].title+\'" class="button_KMpopup" data-html="\'+answer+\'">\' +response[key].title+\'</a></li>\';
438
								}
439
								if (urllist != "") {
440
									$("#KWwithajax").html(\'<td>' . $langs->trans("KMFoundForTicketGroup") . '</td><td><ul>\'+urllist+\'</ul></td>\');
441
									$("#KWwithajax").show();
442
									$(".button_KMpopup").on("click",function(){
443
										console.log("Open popup with jQuery(...).dialog() with KM article")
444
										var $dialog = $("<div></div>").html($(this).attr("data-html"))
445
											.dialog({
446
												autoOpen: false,
447
												modal: true,
448
												height: (window.innerHeight - 150),
449
												width: "80%",
450
												title: $(this).attr("title"),
451
											});
452
										$dialog.dialog("open");
453
										console.log($dialog);
454
									})
455
								}
456
							 },
457
							 error : function(output) {
458
								console.error("Error on Fetch of KM articles");
459
							 },
460
						});
461
					}
462
				};
463
				$("#selectcategory_code").on("change",function() { groupticketchange(); });
464
				if ($("#selectcategory_code").val() != "") {
465
					groupticketchange();
466
				}
467
			});
468
			</script>' . "\n";
469
        }
470
471
        // Subject
472
        if ($this->withtitletopic) {
473
            print '<tr><td><label for="subject"><span class="fieldrequired">' . $langs->trans("Subject") . '</span></label></td><td>';
474
            // Answer to a ticket : display of the thread title in readonly
475
            if ($this->withtopicreadonly) {
476
                print $langs->trans('SubjectAnswerToTicket') . ' ' . $this->topic_title;
477
            } else {
478
                if (isset($this->withreadid) && $this->withreadid > 0) {
479
                    $subject = $langs->trans('SubjectAnswerToTicket') . ' ' . $this->withreadid . ' : ' . $this->topic_title;
480
                }
481
                print '<input class="text minwidth500" id="subject" name="subject" value="' . $subject . '"' . (empty($this->withemail) ? ' autofocus' : '') . ' />';
482
            }
483
            print '</td></tr>';
484
        }
485
486
        // MESSAGE
487
        print '<tr><td><label for="message"><span class="fieldrequired">' . $langs->trans("Message") . '</span></label></td><td>';
488
489
        // If public form, display more information
490
        $toolbarname = 'dolibarr_notes';
491
        if ($this->ispublic) {
492
            $toolbarname = 'dolibarr_details';
493
            print '<div class="warning hideonsmartphone">' . (getDolGlobalString("TICKET_PUBLIC_TEXT_HELP_MESSAGE", $langs->trans('TicketPublicPleaseBeAccuratelyDescribe'))) . '</div>';
494
        }
495
        $uselocalbrowser = true;
496
        $doleditor = new DolEditor('message', $msg, '100%', 230, $toolbarname, 'In', true, $uselocalbrowser, getDolGlobalInt('FCKEDITOR_ENABLE_TICKET'), ROWS_8, '90%');
497
        $doleditor->Create();
498
        print '</td></tr>';
499
500
        if ($public && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET')) {
501
            require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/security2.lib.php';
502
            print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">' . $langs->trans("SecurityCode") . '</span></label></td><td>';
503
            print '<span class="span-icon-security inline-block">';
504
            print '<input id="securitycode" placeholder="' . $langs->trans("SecurityCode") . '" class="flat input-icon-security width125" type="text" maxlength="5" name="code" tabindex="3" />';
505
            print '</span>';
506
            print '<span class="nowrap inline-block">';
507
            print '<img class="inline-block valignmiddle" src="' . constant('BASE_URL') . '/core/antispamimage.php" border="0" width="80" height="32" id="img_securitycode" />';
508
            print '<a class="inline-block valignmiddle" href="" tabindex="4" data-role="button">' . img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"') . '</a>';
509
            print '</span>';
510
            print '</td></tr>';
511
        }
512
513
        // Categories
514
        if (isModEnabled('category')) {
515
            $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
516
517
            if (count($cate_arbo)) {
518
                // Categories
519
                print '<tr><td class="wordbreak">' . $langs->trans("Categories") . '</td><td>';
520
                print img_picto('', 'category', 'class="pictofixedwidth"') . $form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
521
                print "</td></tr>";
522
            }
523
        }
524
525
        // Attached files
526
        if (!empty($this->withfile)) {
527
            // Define list of attached files
528
            $listofpaths = array();
529
            $listofnames = array();
530
            $listofmimes = array();
531
            if (!empty($_SESSION["listofpaths"])) {
532
                $listofpaths = explode(';', $_SESSION["listofpaths"]);
533
            }
534
535
            if (!empty($_SESSION["listofnames"])) {
536
                $listofnames = explode(';', $_SESSION["listofnames"]);
537
            }
538
539
            if (!empty($_SESSION["listofmimes"])) {
540
                $listofmimes = explode(';', $_SESSION["listofmimes"]);
541
            }
542
543
            $out = '<tr>';
544
            $out .= '<td>' . $langs->trans("MailFile") . '</td>';
545
            $out .= '<td>';
546
            // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
547
            $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">' . "\n";
548
            $out .= '<script nonce="' . getNonce() . '" type="text/javascript">';
549
            $out .= 'jQuery(document).ready(function () {';
550
            $out .= '    jQuery(".removedfile").click(function() {';
551
            $out .= '        jQuery(".removedfilehidden").val(jQuery(this).val());';
552
            $out .= '    });';
553
            $out .= '})';
554
            $out .= '</script>' . "\n";
555
            if (count($listofpaths)) {
556
                foreach ($listofpaths as $key => $val) {
557
                    $out .= '<div id="attachfile_' . $key . '">';
558
                    $out .= img_mime($listofnames[$key]) . ' ' . $listofnames[$key];
559
                    if (!$this->withfilereadonly) {
560
                        $out .= ' <input type="image" style="border: 0px;" src="' . constant('DOL_URL_ROOT') . '/theme/' . $conf->theme . '/img/delete.png" value="' . ($key + 1) . '" class="removedfile" id="removedfile_' . $key . '" name="removedfile_' . $key . '" />';
561
                    }
562
                    $out .= '<br></div>';
563
                }
564
            } else {
565
                $out .= '<span class="opacitymedium">' . $langs->trans("NoAttachedFiles") . '</span><br>';
566
            }
567
            if ($this->withfile == 2) { // Can add other files
568
                $maxfilesizearray = getMaxFileSizeArray();
569
                $maxmin = $maxfilesizearray['maxmin'];
570
                if ($maxmin > 0) {
571
                    $out .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">';  // MAX_FILE_SIZE must precede the field type=file
572
                }
573
                $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="' . $langs->trans("Upload") . '" />';
574
                $out .= ' ';
575
                $out .= '<input type="submit" class="button smallpaddingimp reposition" id="addfile" name="addfile" value="' . $langs->trans("MailingAddFile") . '" />';
576
            }
577
            $out .= "</td></tr>\n";
578
579
            print $out;
580
        }
581
582
        // User of creation
583
        if ($this->withusercreate > 0 && $this->fk_user_create) {
584
            print '<tr><td class="titlefield">' . $langs->trans("CreatedBy") . '</td><td>';
585
            $langs->load("users");
586
            $fuser = new User($this->db);
587
588
            if ($this->withcreatereadonly) {
589
                if ($res = $fuser->fetch($this->fk_user_create)) {
590
                    print $fuser->getNomUrl(1);
591
                }
592
            }
593
            print ' &nbsp; ';
594
            print "</td></tr>\n";
595
        }
596
597
        // Customer or supplier
598
        if ($this->withcompany) {
599
            // force company and contact id for external user
600
            if (empty($user->socid)) {
601
                // Company
602
                print '<tr><td class="titlefield">' . $langs->trans("ThirdParty") . '</td><td>';
603
                $events = array();
604
                $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
605
                print img_picto('', 'company', 'class="paddingright"');
606
                print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, '', $events, 0, 'minwidth200');
607
                print '</td></tr>';
608
                if (!empty($conf->use_javascript_ajax) && getDolGlobalString('COMPANY_USE_SEARCH_TO_SELECT')) {
609
                    $htmlname = 'socid';
610
                    print '<script nonce="' . getNonce() . '" type="text/javascript">
611
                    $(document).ready(function () {
612
                        jQuery("#' . $htmlname . '").change(function () {
613
                            var obj = ' . json_encode($events) . ';
614
                            $.each(obj, function(key,values) {
615
                                if (values.method.length) {
616
                                    runJsCodeForEvent' . $htmlname . '(values);
617
                                }
618
                            });
619
                        });
620
621
                        function runJsCodeForEvent' . $htmlname . '(obj) {
622
                            console.log("Run runJsCodeForEvent' . $htmlname . '");
623
                            var id = $("#' . $htmlname . '").val();
624
                            var method = obj.method;
625
                            var url = obj.url;
626
                            var htmlname = obj.htmlname;
627
                            var showempty = obj.showempty;
628
                            $.getJSON(url,
629
                                    {
630
                                        action: method,
631
                                        id: id,
632
                                        htmlname: htmlname,
633
                                        showempty: showempty
634
                                    },
635
                                    function(response) {
636
                                        $.each(obj.params, function(key,action) {
637
                                            if (key.length) {
638
                                                var num = response.num;
639
                                                if (num > 0) {
640
                                                    $("#" + key).removeAttr(action);
641
                                                } else {
642
                                                    $("#" + key).attr(action, action);
643
                                                }
644
                                            }
645
                                        });
646
                                        $("select#" + htmlname).html(response.value);
647
                                        if (response.num) {
648
                                            var selecthtml_str = response.value;
649
                                            var selecthtml_dom=$.parseHTML(selecthtml_str);
650
											if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
651
                                            	$("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
652
											}
653
                                        } else {
654
                                            $("#inputautocomplete"+htmlname).val("");
655
                                        }
656
                                        $("select#" + htmlname).change();	/* Trigger event change */
657
                                    }
658
                            );
659
                        }
660
                    });
661
                    </script>';
662
                }
663
                if ($mode == 'create') {
664
                    // Contact and type
665
                    print '<tr><td>' . $langs->trans("Contact") . '</td><td>';
666
                    // If no socid, set to -1 to avoid full contacts list
667
                    $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
668
                    print img_picto('', 'contact', 'class="paddingright"');
669
                    // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
670
                    print $form->select_contact($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 1, 'maxwidth300 widthcentpercentminusx', true);
671
672
                    print ' ';
673
                    $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
674
                    print '</td></tr>';
675
                }
676
            } else {
677
                print '<tr><td class="titlefield"><input type="hidden" name="socid" value="' . $user->socid . '"/></td>';
678
                print '<td><input type="hidden" name="contactid" value="' . $user->contact_id . '"/></td>';
679
                print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
680
            }
681
682
            // Notify thirdparty at creation
683
            if (empty($this->ispublic) && $action == 'create') {
684
                print '<tr><td><label for="notify_tiers_at_create">' . $langs->trans("TicketNotifyTiersAtCreation") . '</label></td><td>';
685
                print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"' . ($this->withnotifytiersatcreate ? ' checked="checked"' : '') . '>';
686
                print '</td></tr>';
687
            }
688
689
            // User assigned
690
            print '<tr><td>';
691
            print $langs->trans("AssignedTo");
692
            print '</td><td>';
693
            print img_picto('', 'user', 'class="pictofixedwidth"');
694
            print $form->select_dolusers($user_assign, 'fk_user_assign', 1);
695
            print '</td>';
696
            print '</tr>';
697
        }
698
699
        if ($subelement != 'project') {
700
            if (isModEnabled('project') && !$this->ispublic) {
701
                $formproject = new FormProjets($this->db);
702
                print '<tr><td><label for="project"><span class="">' . $langs->trans("Project") . '</span></label></td><td>';
703
                print img_picto('', 'project') . $formproject->select_projects(-1, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
704
                print '</td></tr>';
705
            }
706
        }
707
708
        if ($subelement != 'contract') {
709
            if (isModEnabled('contract') && !$this->ispublic) {
710
                $langs->load('contracts');
711
                $formcontract = new FormContract($this->db);
712
                print '<tr><td><label for="contract"><span class="">' . $langs->trans("Contract") . '</span></label></td><td>';
713
                print img_picto('', 'contract');
714
                print $formcontract->select_contract(-1, GETPOSTINT('contactid'), 'contractid', 0, 1, 1, 1);
715
                print '</td></tr>';
716
            }
717
        }
718
719
        // Other attributes
720
        $parameters = array();
721
        $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
722
        if (empty($reshook)) {
723
            if ($mode == 'create') {
724
                print $object->showOptionals($extrafields, 'create');
0 ignored issues
show
Bug introduced by
The method showOptionals() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

724
                print $object->/** @scrutinizer ignore-call */ showOptionals($extrafields, 'create');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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