Passed
Pull Request — dev (#8)
by Rafael
58:47
created

FormTicket::selectGroupTickets()   F

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

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