Issues (2811)

public/htdocs/ticket/card.php (2 issues)

1
<?php
2
3
/* Copyright (C) 2013-2016  Jean-François FERRY         <[email protected]>
4
 * Copyright (C) 2016       Christophe Battarel         <[email protected]>
5
 * Copyright (C) 2018       Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2021-2024  Frédéric France		        <[email protected]>
7
 * Copyright (C) 2021       Alexandre Spangaro          <[email protected]>
8
 * Copyright (C) 2022-2023  Charlene Benke              <[email protected]>
9
 * Copyright (C) 2023       Benjamin Falière		    <[email protected]>
10
 * Copyright (C) 2024		MDW							<[email protected]>
11
 * Copyright (C) 2024	    Irvine FLEITH		        <[email protected]>
12
 * Copyright (C) 2024       Rafael San José             <[email protected]>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 3 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26
 */
27
28
use Dolibarr\Code\Categories\Classes\Categorie;
29
use Dolibarr\Code\Contact\Classes\Contact;
30
use Dolibarr\Code\Contrat\Classes\Contrat;
31
use Dolibarr\Code\Core\Classes\ExtraFields;
32
use Dolibarr\Code\Core\Classes\Form;
33
use Dolibarr\Code\Core\Classes\FormActions;
34
use Dolibarr\Code\Core\Classes\FormContract;
35
use Dolibarr\Code\Core\Classes\FormFile;
36
use Dolibarr\Code\Core\Classes\FormProjets;
37
use Dolibarr\Code\Core\Classes\FormTicket;
38
use Dolibarr\Code\Core\Classes\Translate;
39
use Dolibarr\Code\Projet\Classes\Project;
40
use Dolibarr\Code\Societe\Classes\Societe;
41
use Dolibarr\Code\Ticket\Classes\ActionsTicket;
42
use Dolibarr\Code\Ticket\Classes\Ticket;
43
use Dolibarr\Code\User\Classes\User;
44
use Dolibarr\Lib\ViewMain;
45
46
/**
47
 *   \file
48
 * htdocs/ticket/card.php
49
 *   \ingroup    ticket
50
 *   \brief      Page to create/edit/view Tickets
51
 */
52
53
// Load Dolibarr environment
54
require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
55
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/ticket.lib.php';
56
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php';
57
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/company.lib.php';
58
if (isModEnabled('project')) {
59
    include_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
60
    include_once DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
61
}
62
if (isModEnabled('contract')) {
63
    include_once DOL_DOCUMENT_ROOT . '/core/class/html.formcontract.class.php';
64
    include_once DOL_DOCUMENT_ROOT . '/core/lib/contract.lib.php';
65
    include_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
66
}
67
68
// Load translation files required by the page
69
$langs->loadLangs(array("companies", "other", "ticket"));
70
71
// Get parameters
72
$id = GETPOSTINT('id');
73
$ref = GETPOST('ref', 'alpha');
74
$track_id = GETPOST('track_id', 'alpha', 3);
75
$socid = GETPOSTINT('socid');
76
$contactid = GETPOSTINT('contactid');
77
$projectid = GETPOSTINT('projectid');
78
$notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
79
80
$action = GETPOST('action', 'aZ09');
81
$cancel = GETPOST('cancel', 'alpha');
82
$backtopage = GETPOST('backtopage', 'alpha');
83
$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
84
85
$sortfield = GETPOST('sortfield', 'aZ09comma') ? GETPOST('sortfield', 'aZ09comma') : "a.datep";
86
$sortorder = GETPOST('sortorder', 'aZ09comma') ? GETPOST('sortorder', 'aZ09comma') : "desc";
87
$search_rowid = GETPOST('search_rowid');
88
$search_agenda_label = GETPOST('search_agenda_label');
89
90
if (GETPOST('actioncode', 'array')) {
91
    $actioncode = GETPOST('actioncode', 'array', 3);
92
    if (!count($actioncode)) {
93
        $actioncode = '0';
94
    }
95
} else {
96
    $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT'));
97
}
98
99
// Initialize technical object to manage hooks of ticket. Note that conf->hooks_modules contains array array
100
$hookmanager->initHooks(array('ticketcard', 'globalcard'));
101
102
$object = new Ticket($db);
103
$extrafields = new ExtraFields($db);
104
105
// Fetch optionals attributes and labels
106
$extrafields->fetch_name_optionals_label($object->table_element);
107
108
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
109
110
// Initialize array of search criteria
111
$search_all = GETPOST("search_all", 'alpha');
112
$search = array();
113
foreach ($object->fields as $key => $val) {
114
    if (GETPOST('search_' . $key, 'alpha')) {
115
        $search[$key] = GETPOST('search_' . $key, 'alpha');
116
    }
117
}
118
119
if (empty($action) && empty($id) && empty($ref)) {
120
    $action = 'view';
121
}
122
123
// Select mail models is same action as add_message
124
if (GETPOST('modelselected', 'alpha')) {
125
    $action = 'presend';
126
}
127
128
// Load object
129
//include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php';  // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals
130
if ($id || $track_id || $ref) {
131
    $res = $object->fetch($id, $ref, $track_id);
132
    if ($res >= 0) {
133
        $id = $object->id;
134
        $track_id = $object->track_id;
135
    }
136
}
137
138
$now = dol_now();
139
140
$actionobject = new ActionsTicket($db);
141
142
// Store current page url
143
$url_page_current = constant('BASE_URL') . '/ticket/card.php';
144
145
// Security check - Protection if external user
146
if ($user->socid > 0) {
147
    $socid = $user->socid;
148
}
149
$result = restrictedArea($user, 'ticket', $object->id);
150
151
$triggermodname = 'TICKET_MODIFY';
152
153
// Permissions
154
$permissiontoread = $user->hasRight('ticket', 'read');
155
$permissiontoadd = $user->hasRight('ticket', 'write');
156
$permissiontodelete = $user->hasRight('ticket', 'delete');
157
158
$upload_dir = $conf->ticket->dir_output;
159
160
161
/*
162
 * Actions
163
 */
164
165
$parameters = array();
166
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
167
if ($reshook < 0) {
168
    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
169
}
170
171
$error = 0;
172
if (empty($reshook)) {
173
    // Purge search criteria
174
    if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers{
175
        $actioncode = '';
176
        $search_agenda_label = '';
177
    }
178
179
    $backurlforlist = constant('BASE_URL') . '/ticket/list.php';
180
181
    if (empty($backtopage) || ($cancel && empty($id))) {
182
        if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
183
            if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
184
                $backtopage = $backurlforlist;
185
            } else {
186
                $backtopage = '/ticket/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__');
187
            }
188
        }
189
    }
190
191
    if ($cancel) {
192
        if (!empty($backtopageforcancel)) {
193
            header("Location: " . $backtopageforcancel);
194
            exit;
195
        } elseif (!empty($backtopage)) {
196
            header("Location: " . $backtopage);
197
            exit;
198
        }
199
        $action = 'view';
200
    }
201
202
    if (($action == 'add' || ($action == 'update' && $object->status < Ticket::STATUS_CLOSED)) && $permissiontoadd) {
0 ignored issues
show
Consider adding parentheses for clarity. Current Interpretation: ($action == 'add' || $ac...ED) && $permissiontoadd, Probably Intended Meaning: $action == 'add' || ($ac...ED && $permissiontoadd)
Loading history...
203
        $ifErrorAction = $action == 'add' ? 'create' : 'edit';
204
        if ($action == 'add') $object->track_id = null;
205
        $error = 0;
206
207
        $fieldsToCheck = [
208
            'ref' => ['check' => 'alpha', 'langs' => 'Ref'],
209
            'type_code' => ['check' => 'alpha', 'langs' => 'TicketTypeRequest'],
210
            'category_code' => ['check' => 'alpha', 'langs' => 'TicketCategory'],
211
            'severity_code' => ['check' => 'alpha', 'langs' => 'TicketSeverity'],
212
            'subject' => ['check' => 'alphanohtml', 'langs' => 'Subject'],
213
            'message' => ['check' => 'restricthtml', 'langs' => 'Message']
214
        ];
215
216
        FormTicket::checkRequiredFields($fieldsToCheck, $error);
217
218
        if (!empty($error)) {
219
            $action = $ifErrorAction;
220
        }
221
222
        $ret = $extrafields->setOptionalsFromPost(null, $object);
223
        if ($ret < 0) {
224
            $error++;
225
        }
226
        $getRef = GETPOST('ref', 'alpha');
227
228
        if (!empty($getRef)) {
229
            $isExistingRef = $object->checkExistingRef($action, $getRef);
230
        } else {
231
            $isExistingRef = true;
232
        }
233
234
        $style = '';
235
236
        if ($isExistingRef) {
237
            if ($action == 'update') {
238
                $error++;
239
                $action = 'edit';
240
                $style = 'errors';
241
            } elseif ($action == 'add') {
242
                $object->ref = $object->getDefaultRef();
243
                $object->track_id = null;
244
                $style = 'warnings';
245
            }
246
            if (!empty($getRef)) {
247
                setEventMessage($langs->trans('TicketRefAlreadyUsed', $getRef, $object->ref), $style);
248
            }
249
        }
250
        if (!$error) {
251
            $db->begin();
252
253
            $object->type_code = GETPOST('type_code', 'alpha');
254
            $object->category_code = GETPOST('category_code', 'alpha');
255
            $object->severity_code = GETPOST('severity_code', 'alpha');
256
            $object->subject = GETPOST('subject', 'alpha');
257
            $object->message = GETPOST('message', 'restricthtml');
258
            $object->fk_soc = GETPOSTINT('socid');
259
            $fk_user_assign = GETPOSTINT('fk_user_assign');
260
            $object->fk_project = GETPOSTINT('projectid');
261
            $object->fk_contract = GETPOSTINT('fk_contract');
262
263
            if ($fk_user_assign > 0) {
264
                $object->fk_user_assign = $fk_user_assign;
265
                $object->status = $object::STATUS_ASSIGNED;
266
            }
267
268
            if ($action == 'add') {
269
                $object->type_code = GETPOST("type_code", 'alpha');
270
                $object->type_label = $langs->trans($langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'));
271
                $object->category_label = $langs->trans($langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'));
272
                $object->severity_label = $langs->trans($langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'));
273
                $object->fk_user_create = $user->id;
274
                $object->email_from = $user->email;
275
                $object->origin_email = null;
276
                $notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
277
                $object->notify_tiers_at_create = empty($notifyTiers) ? 0 : 1;
278
                $object->context['contact_id'] = GETPOSTINT('contact_id');
279
                $id = $object->create($user);
280
            } else {
281
                $id = $object->update($user);
282
            }
283
284
            if ($id <= 0) {
285
                $error++;
286
                setEventMessages($object->error, $object->errors, 'errors');
287
                $action = $ifErrorAction;
288
            }
289
290
            if (!$error) {
291
                // Category association
292
                $categories = GETPOST('categories', 'array');
293
                $object->setCategories($categories);
294
            }
295
296
            if ($action == 'add') {
297
                if (!$error) {
298
                    // Add contact
299
                    $contactid = GETPOSTINT('contactid');
300
                    $type_contact = GETPOST("type", 'alpha');
301
302
                    if ($contactid > 0 && $type_contact) {
303
                        $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
304
                        $result = $object->add_contact($contactid, $typeid, 'external');
305
                    }
306
307
                    // Link ticket to project
308
                    if (GETPOST('origin', 'alpha') == 'projet') {
309
                        $projectid = GETPOSTINT('originid');
310
                    } else {
311
                        $projectid = GETPOSTINT('projectid');
312
                    }
313
314
                    if ($projectid > 0) {
315
                        $object->setProject($projectid);
316
                    }
317
318
                    // Auto mark as read if created from backend
319
                    if (getDolGlobalString('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND') && $user->hasRight('ticket', 'write')) {
320
                        if (!$object->markAsRead($user) > 0) {
321
                            setEventMessages($object->error, $object->errors, 'errors');
322
                        }
323
                    }
324
325
                    // Auto assign user
326
                    if (getDolGlobalString('TICKET_AUTO_ASSIGN_USER_CREATE')) {
327
                        $result = $object->assignUser($user, $user->id, 1);
328
                        $object->add_contact($user->id, "SUPPORTTEC", 'internal');
329
                    }
330
                }
331
332
                if (!$error) {
333
                    // File transfer
334
                    $object->copyFilesForTicket('');        // trackid is forced to '' because files were uploaded when no id for ticket exists yet and trackid was ''
335
                }
336
            }
337
            if (!$error) {
338
                $db->commit();
339
340
                if (!empty($backtopage)) {
341
                    if (empty($id)) {
342
                        $url = $backtopage;
343
                    } else {
344
                        $url = 'card.php?track_id=' . urlencode($object->track_id);
345
                    }
346
                } else {
347
                    $url = 'card.php?track_id=' . urlencode($object->track_id);
348
                }
349
350
                header("Location: " . $url);
351
                exit;
352
            } else {
353
                $db->rollback();
354
                setEventMessages($object->error, $object->errors, 'errors');
355
            }
356
        } else $action = $ifErrorAction;
357
    }
358
359
    // Mark as Read
360
    if ($action == "set_read" && $permissiontoadd) {
361
        $object->fetch('', '', GETPOST("track_id", 'alpha'));
362
363
        if ($object->markAsRead($user) > 0) {
364
            setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs');
365
366
            header("Location: card.php?track_id=" . $object->track_id);
367
            exit;
368
        } else {
369
            setEventMessages($object->error, $object->errors, 'errors');
370
        }
371
        $action = 'view';
372
    }
373
374
    // Assign to someone
375
    if ($action == "assign_user" && GETPOST('btn_assign_user', 'alpha') && $permissiontoadd) {
376
        $object->fetch('', '', GETPOST("track_id", 'alpha'));
377
        $useroriginassign = $object->fk_user_assign;
378
        $usertoassign = GETPOSTINT('fk_user_assign');
379
380
        /*if (! ($usertoassign > 0)) {
381
         $error++;
382
         array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("AssignedTo")));
383
         $action = 'view';
384
         }*/
385
386
        if (!$error) {
387
            $ret = $object->assignUser($user, $usertoassign);
388
            if ($ret < 0) {
389
                $error++;
390
            }
391
        }
392
393
        if (!$error) {    // Update list of contacts
394
            // If a user has already been assigned, we delete him from the contacts.
395
            if ($useroriginassign > 0) {
396
                $internal_contacts = $object->listeContact(-1, 'internal', 0, 'SUPPORTTEC');
397
                foreach ($internal_contacts as $key => $contact) {
398
                    if ($contact['id'] !== $usertoassign) {
399
                        $result = $object->delete_contact($contact['rowid']);
400
                        if ($result < 0) {
401
                            $error++;
402
                            setEventMessages($object->error, $object->errors, 'errors');
403
                        }
404
                    }
405
                }
406
            }
407
408
            if ($usertoassign > 0 && $usertoassign !== $useroriginassign) {
409
                $result = $object->add_contact($usertoassign, "SUPPORTTEC", 'internal', $notrigger = 0);
410
                if ($result < 0) {
411
                    $error++;
412
                    setEventMessages($object->error, $object->errors, 'errors');
413
                }
414
            }
415
        }
416
417
        if (!$error) {
418
            // Log action in ticket logs table
419
            $object->fetch_user($usertoassign);
420
421
            setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs');
422
            header("Location: card.php?track_id=" . $object->track_id);
423
            exit;
424
        } else {
425
            array_push($object->errors, $object->error);
426
        }
427
        $action = 'view';
428
    }
429
430
    // Action to add a message (private or not, with email or not).
431
    // This may also send an email (concatenated with email_intro and email footer if checkbox was selected)
432
    if ($action == 'add_message' && GETPOSTISSET('btn_add_message') && $permissiontoread) {
433
        $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0), 0);
434
435
        if ($ret > 0) {
436
            if (!empty($backtopage)) {
437
                $url = $backtopage;
438
            } else {
439
                $url = 'card.php?track_id=' . urlencode($object->track_id);
440
            }
441
442
            header("Location: " . $url);
443
            exit;
444
        } else {
445
            setEventMessages($object->error, $object->errors, 'errors');
446
            $action = 'presend';
447
        }
448
    }
449
450
    if (($action == "confirm_close" || $action == "confirm_abandon") && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
451
        $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
452
453
        if ($object->close($user, ($action == "confirm_abandon" ? 1 : 0))) {
454
            setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs');
455
456
            $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
457
            header("Location: " . $url);
458
            exit;
459
        } else {
460
            $action = '';
461
            setEventMessages($object->error, $object->errors, 'errors');
462
        }
463
    }
464
465
    if ($action == "confirm_public_close" && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
466
        $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
467
        if ($_SESSION['email_customer'] == $object->origin_email || $_SESSION['email_customer'] == $object->thirdparty->email) {
468
            $object->context['contact_id'] = GETPOSTINT('contact_id');
469
470
            $object->close($user);
471
472
            setEventMessages('<div class="confirm">' . $langs->trans('TicketMarkedAsClosed') . '</div>', null, 'mesgs');
473
474
            $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
475
            header("Location: " . $url);
476
            exit;
477
        } else {
478
            setEventMessages($object->error, $object->errors, 'errors');
479
            $action = '';
480
        }
481
    }
482
483
    if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $permissiontodelete) {
484
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
485
            if ($object->delete($user) > 0) {
486
                setEventMessages('<div class="confirm">' . $langs->trans('TicketDeletedSuccess') . '</div>', null, 'mesgs');
487
                header("Location: " . constant('BASE_URL') . "/ticket/list.php");
488
                exit;
489
            } else {
490
                $langs->load("errors");
491
                $mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
492
                $action = '';
493
            }
494
        }
495
    }
496
497
    // Set parent company
498
    if ($action == 'set_thirdparty' && $user->hasRight('ticket', 'write')) {
499
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
500
            $result = $object->setCustomer(GETPOSTINT('editcustomer'));
501
            $url = $_SERVER["PHP_SELF"] . '?track_id=' . GETPOST('track_id', 'alpha');
502
            header("Location: " . $url);
503
            exit();
504
        }
505
    }
506
507
    // Set progress status
508
    if ($action == 'set_progression' && $user->hasRight('ticket', 'write')) {
509
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
510
            $result = $object->setProgression(GETPOST('progress', 'alpha'));
511
512
            $url = 'card.php?track_id=' . $object->track_id;
513
            header("Location: " . $url);
514
            exit();
515
        }
516
    }
517
518
    // Set categories
519
    if ($action == 'set_categories' && $user->hasRight('ticket', 'write')) {
520
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
521
            $result = $object->setCategories(GETPOST('categories', 'array'));
522
523
            $url = 'card.php?track_id=' . $object->track_id;
524
            header("Location: " . $url);
525
            exit();
526
        }
527
    }
528
529
    // Set Subject
530
    if ($action == 'setsubject' && $user->hasRight('ticket', 'write')) {
531
        if ($object->fetch(GETPOSTINT('id'))) {
532
            if ($action == 'setsubject') {
533
                $object->subject = GETPOST('subject', 'alphanohtml');
534
            }
535
536
            if ($action == 'setsubject' && empty($object->subject)) {
537
                $error++;
538
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors');
539
            }
540
541
            if (!$error) {
542
                if (!$object->update($user) >= 0) {
543
                    $error++;
544
                    setEventMessages($object->error, $object->errors, 'errors');
545
                }
546
            }
547
548
            header("Location: " . $_SERVER['PHP_SELF'] . "?track_id=" . $object->track_id);
549
            exit;
550
        }
551
    }
552
553
    if ($action == 'confirm_reopen' && $user->hasRight('ticket', 'manage') && !GETPOST('cancel')) {
554
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
555
            // prevent browser refresh from reopening ticket several times
556
            if ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED) {
557
                if ($object->fk_user_assign != null) {
558
                    $res = $object->setStatut(Ticket::STATUS_ASSIGNED);
559
                } else {
560
                    $res = $object->setStatut(Ticket::STATUS_NOT_READ);
561
                }
562
                if ($res) {
563
                    $url = 'card.php?track_id=' . $object->track_id;
564
                    header("Location: " . $url);
565
                    exit();
566
                } else {
567
                    $error++;
568
                    setEventMessages($object->error, $object->errors, 'errors');
569
                }
570
            }
571
        }
572
    } elseif ($action == 'classin' && $permissiontoadd) {
573
        // Categorisation dans projet
574
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
575
            $object->setProject($projectid);
576
            $url = 'card.php?track_id=' . $object->track_id;
577
            header("Location: " . $url);
578
            exit();
579
        }
580
    } elseif ($action == 'setcontract' && $permissiontoadd) {
581
        // Categorisation dans contrat
582
        if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
583
            $object->setContract(GETPOSTINT('contractid'));
584
            $url = 'card.php?track_id=' . $object->track_id;
585
            header("Location: " . $url);
586
            exit();
587
        }
588
    } elseif ($action == "set_message" && $user->hasRight('ticket', 'manage')) {
589
        if (!GETPOST('cancel')) {
590
            $object->fetch('', '', GETPOST('track_id', 'alpha'));
591
            //$oldvalue_message = $object->message;
592
            $fieldtomodify = GETPOST('message_initial', 'restricthtml');
593
594
            $object->message = $fieldtomodify;
595
            $ret = $object->update($user);
596
            if ($ret > 0) {
597
                //include_once DOL_DOCUMENT_ROOT.'/core/class/utils_diff.class.php';
598
                // output the result of comparing two files as plain text
599
                //$log_action .= Diff::toString(Diff::compare(strip_tags($oldvalue_message), strip_tags($object->message)));
600
601
                setEventMessages($langs->trans('TicketMessageSuccesfullyUpdated'), null, 'mesgs');
602
            } else {
603
                $error++;
604
                setEventMessages($object->error, $object->errors, 'errors');
605
            }
606
        }
607
608
        $action = 'view';
609
    } elseif ($action == 'confirm_set_status' && $permissiontoadd && !GETPOST('cancel')) {
610
        // Reopen ticket
611
        if ($object->fetch(GETPOSTINT('id'), GETPOST('track_id', 'alpha')) >= 0) {
612
            $new_status = GETPOSTINT('new_status');
613
            //$old_status = $object->status;
614
            $res = $object->setStatut($new_status);
615
            if ($res) {
616
                $url = 'card.php?track_id=' . $object->track_id;
617
                header("Location: " . $url);
618
                exit();
619
            } else {
620
                $error++;
621
                setEventMessages($object->error, $object->errors, 'errors');
622
            }
623
        }
624
    }
625
626
    // Action to update an extrafield
627
    if ($action == "update_extras" && $permissiontoadd) {
628
        $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
629
630
        $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
631
        if ($ret < 0) {
632
            $error++;
633
        }
634
635
        if (!$error) {
636
            $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user);
637
            if ($result < 0) {
638
                $error++;
639
            }
640
        }
641
642
        if ($error) {
643
            setEventMessages($object->error, $object->errors, 'errors');
644
            $action = 'edit_extras';
645
        } else {
646
            setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
647
            $action = 'view';
648
        }
649
    }
650
651
    if ($action == "change_property" && GETPOST('btn_update_ticket_prop', 'alpha') && $permissiontoadd) {
652
        $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
653
654
        $object->type_code = GETPOST('update_value_type', 'aZ09');
655
        $object->severity_code = GETPOST('update_value_severity', 'aZ09');
656
        $object->category_code = GETPOST('update_value_category', 'aZ09');
657
658
        $ret = $object->update($user);
659
        if ($ret > 0) {
660
            setEventMessages($langs->trans('TicketUpdated'), null, 'mesgs');
661
        } else {
662
            $error++;
663
            setEventMessages($object->error, $object->errors, 'errors');
664
        }
665
        $action = 'view';
666
    }
667
668
669
    $permissiondellink = $user->hasRight('ticket', 'write');
670
    include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be include, not include_once
671
672
    // Actions to build doc
673
    include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
674
675
    // Actions to send emails
676
    $triggersendname = 'TICKET_SENTBYMAIL';
677
    $paramname = 'id';
678
    $autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add
679
    $trackid = 'tic' . $object->id;
680
    include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
681
682
    // Set $action to correct value for the case we used presend action to add a message
683
    if (GETPOSTISSET('actionbis') && $action == 'presend') {
684
        $action = 'presend_addmessage';
685
    }
686
}
687
688
/*
689
 * View
690
 */
691
692
$userstat = new User($db);
693
$form = new Form($db);
694
$formfile = new FormFile($db);
695
$formticket = new FormTicket($db);
696
if (isModEnabled('project')) {
697
    $formproject = new FormProjets($db);
698
}
699
700
$help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket';
701
702
$title = $actionobject->getTitle($action);
703
704
ViewMain::llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-ticket page-card');
705
706
if ($action == 'create' || $action == 'presend') {
707
    if (empty($permissiontoadd)) {
708
        accessforbidden('NotEnoughPermissions', 0, 1);
709
    }
710
711
    $formticket = new FormTicket($db);
712
713
    print load_fiche_titre($langs->trans('NewTicket'), '', 'ticket');
714
715
    $formticket->trackid = '';      // TODO Use a unique key 'tic' to avoid conflict in upload file feature
716
    $formticket->withfromsocid = $socid ? $socid : $user->socid;
717
    $formticket->withfromcontactid = $contactid ? $contactid : '';
718
    $formticket->withtitletopic = 1;
719
    $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
720
    $formticket->withusercreate = 0;
721
    $formticket->withref = 1;
722
    $formticket->fk_user_create = $user->id;
723
    $formticket->withfile = 2;
724
    $formticket->withextrafields = 1;
725
    $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
726
727
    $formticket->withcancel = 1;
728
729
    $formticket->showForm(1, 'create', 0, null, $action, $object);
730
731
    print dol_get_fiche_end();
732
} elseif ($action == 'edit' && $object->status < Ticket::STATUS_CLOSED) {
733
    if (empty($permissiontoadd)) {
734
        accessforbidden('NotEnoughPermissions', 0, 1);
735
    }
736
737
    $formticket = new FormTicket($db);
738
739
    $head = ticket_prepare_head($object);
740
741
    print dol_get_fiche_head($head, 'tabTicket', $langs->trans('Ticket'), -1, 'ticket');
742
743
    $formticket->trackid = $object->track_id;        // TODO Use a unique key 'tic' to avoid conflict in upload file feature
744
    $formticket->withfromsocid = $object->socid;
745
    $formticket->withtitletopic = 1;
746
    //  $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
747
    $formticket->withnotifytiersatcreate = 0;
748
    $formticket->withusercreate = 0;
749
    $formticket->withref = 1;
750
    $formticket->fk_user_create = $user->id;
751
    $formticket->withfile = 0;
752
    $formticket->action = 'update';
753
    $formticket->withextrafields = 1;
754
    $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
755
756
    $formticket->withcancel = 1;
757
758
    $formticket->showForm(0, 'edit', 0, null, $action, $object);
759
760
    print dol_get_fiche_end();
761
} elseif (empty($action) || in_array($action, ['builddoc', 'view', 'addlink', 'dellink', 'presend', 'presend_addmessage', 'close', 'abandon', 'delete', 'editcustomer', 'progression', 'categories', 'reopen', 'edit_contrat', 'editsubject', 'edit_extras', 'update_extras', 'edit_extrafields', 'set_extrafields', 'classify', 'sel_contract', 'edit_message_init', 'set_status', 'dellink'])) {
762
    if (!empty($res) && $res > 0) {
763
        // or for unauthorized internals users
764
        if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->hasRight('ticket', 'manage')) {
765
            accessforbidden('', 0, 1);
766
        }
767
768
769
        // Confirmation close
770
        if ($action == 'close') {
771
            $thirdparty_contacts = $object->getInfosTicketExternalContact(1);
772
            $contacts_select = array(
773
                '-2' => $langs->trans('TicketNotifyAllTiersAtClose'),
774
                '-3' => $langs->trans('TicketNotNotifyTiersAtClose')
775
            );
776
            foreach ($thirdparty_contacts as $thirdparty_contact) {
777
                $contacts_select[$thirdparty_contact['id']] = $thirdparty_contact['civility'] . ' ' . $thirdparty_contact['lastname'] . ' ' . $thirdparty_contact['firstname'];
778
            }
779
780
            // Default select all or no contact
781
            $default = (getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? -2 : -3);
782
            $formquestion = array(
783
                array(
784
                    'name' => 'contactid',
785
                    'type' => 'select',
786
                    'label' => $langs->trans('NotifyThirdpartyOnTicketClosing'),
787
                    'values' => $contacts_select,
788
                    'default' => $default
789
                ),
790
            );
791
792
            print $form->formconfirm($url_page_current . "?track_id=" . $object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", $formquestion, '', 1);
793
        }
794
        // Confirmation abandon
795
        if ($action == 'abandon') {
796
            print $form->formconfirm($url_page_current . "?track_id=" . $object->track_id, $langs->trans("AbandonTicket"), $langs->trans("ConfirmAbandonTicket"), "confirm_abandon", '', '', 1);
797
        }
798
        // Confirmation delete
799
        if ($action == 'delete') {
800
            print $form->formconfirm($url_page_current . "?track_id=" . $object->track_id, $langs->trans("Delete"), $langs->trans("ConfirmDeleteTicket"), "confirm_delete_ticket", '', '', 1);
801
        }
802
        // Confirm reopen
803
        if ($action == 'reopen') {
804
            print $form->formconfirm($url_page_current . '?track_id=' . $object->track_id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenTicket'), 'confirm_reopen', '', '', 1);
805
        }
806
        // Confirmation status change
807
        if ($action == 'set_status') {
808
            $new_status = GETPOST('new_status');
809
            //var_dump($url_page_current . "?track_id=" . $object->track_id);
810
            print $form->formconfirm($url_page_current . "?track_id=" . $object->track_id . "&new_status=" . GETPOST('new_status'), $langs->trans("TicketChangeStatus"), $langs->trans("TicketConfirmChangeStatus", $langs->transnoentities($object->labelStatusShort[$new_status])), "confirm_set_status", '', '', 1);
811
        }
812
813
        // project info
814
        if ($projectid > 0) {
815
            $projectstat = new Project($db);
816
            if ($projectstat->fetch($projectid) > 0) {
817
                $projectstat->fetch_thirdparty();
818
819
                // To verify role of users
820
                //$userAccess = $object->restrictedProjectArea($user,'read');
821
                $userWrite = $projectstat->restrictedProjectArea($user, 'write');
822
                //$userDelete = $object->restrictedProjectArea($user,'delete');
823
                //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
824
825
                $head = project_prepare_head($projectstat);
826
827
                print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), 0, ($projectstat->public ? 'projectpub' : 'project'));
828
829
                print '<table class="border centpercent">';
830
831
                $linkback = '<a href="' . constant('BASE_URL') . '/projet/list.php?restore_lastsearch_values=1">' . $langs->trans("BackToList") . '</a>';
832
833
                // Ref
834
                print '<tr><td width="30%">' . $langs->trans('Ref') . '</td><td colspan="3">';
835
                // Define a complementary filter for search of next/prev ref.
836
                if (!$user->hasRight('projet', 'all', 'lire')) {
837
                    $objectsListId = $projectstat->getProjectsAuthorizedForUser($user, $mine, 0);
838
                    $projectstat->next_prev_filter = "rowid IN (" . $db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0') . ")";
839
                }
840
                print $form->showrefnav($projectstat, 'ref', $linkback, 1, 'ref', 'ref', '');
841
                print '</td></tr>';
842
843
                // Label
844
                print '<tr><td>' . $langs->trans("Label") . '</td><td>' . $projectstat->title . '</td></tr>';
845
846
                // Customer
847
                print "<tr><td>" . $langs->trans("ThirdParty") . "</td>";
848
                print '<td colspan="3">';
849
                if ($projectstat->thirdparty->id > 0) {
850
                    print $projectstat->thirdparty->getNomUrl(1);
0 ignored issues
show
The method getNomUrl() 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

850
                    print $projectstat->thirdparty->/** @scrutinizer ignore-call */ getNomUrl(1);

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...
851
                } else {
852
                    print '&nbsp;';
853
                }
854
855
                print '</td></tr>';
856
857
                // Visibility
858
                print '<tr><td>' . $langs->trans("Visibility") . '</td><td>';
859
                if ($projectstat->public) {
860
                    print $langs->trans('SharedProject');
861
                } else {
862
                    print $langs->trans('PrivateProject');
863
                }
864
865
                print '</td></tr>';
866
867
                // Status
868
                print '<tr><td>' . $langs->trans("Status") . '</td><td>' . $projectstat->getLibStatut(4) . '</td></tr>';
869
870
                print "</table>";
871
872
                print dol_get_fiche_end();
873
            } else {
874
                print "ErrorRecordNotFound";
875
            }
876
        } elseif ($socid > 0) {
877
            $object->fetch_thirdparty();
878
            $head = societe_prepare_head($object->thirdparty);
879
880
            print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company');
881
882
            dol_banner_tab($object->thirdparty, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom');
883
884
            print dol_get_fiche_end();
885
        }
886
887
        if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) {
888
            $object->next_prev_filter = "te.fk_user_assign = " . ((int)$user->id);
889
        } elseif ($user->socid > 0) {
890
            $object->next_prev_filter = "te.fk_soc = " . ((int)$user->socid);
891
        }
892
893
        $head = ticket_prepare_head($object);
894
895
        print dol_get_fiche_head($head, 'tabTicket', $langs->trans("Ticket"), -1, 'ticket');
896
897
        $morehtmlref = '<div class="refidno">';
898
        $morehtmlref .= $object->subject;
899
        // Author
900
        $createdbyshown = 0;
901
        if ($object->fk_user_create > 0) {
902
            $morehtmlref .= '<br>' . $langs->trans("CreatedBy") . ' : ';
903
904
            $fuser = new User($db);
905
            $fuser->fetch($object->fk_user_create);
906
            $morehtmlref .= $fuser->getNomUrl(-1);
907
            $createdbyshown++;
908
        }
909
910
        //var_dump($object);
911
        if (!empty($object->origin_email)) {    // If ticket create from public interface - TODO Add a more robust test to know if created by pubic interface
912
            $htmltooptip = $langs->trans("OriginEmail") . ': ' . $object->origin_email;
913
            $htmltooptip .= '<br>' . $langs->trans("IP") . ': ' . $object->ip;
914
            $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
915
            $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy") . ' : ');
916
            $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
917
            $morehtmlref .= dol_escape_htmltag($object->origin_email) . ' <small class="hideonsmartphone opacitymedium">- ' . $form->textwithpicto($langs->trans("CreatedByPublicPortal"), $htmltooptip, 1, 'help', '', 0, 3, 'tooltip') . '</small>';
918
        } elseif (!empty($object->email_msgid)) {   // If ticket create by emailcollector - TODO Add a more robust test to know if created by email collector (using import ky ?)
919
            $langs->load("mails");
920
            $htmltooltip = $langs->trans("EmailMsgID") . ': ' . $object->email_msgid;
921
            $htmltooltip .= '<br>' . $langs->trans("EmailDate") . ': ' . dol_print_date($object->email_date, 'dayhour');
922
            $htmltooltip .= '<br>' . $langs->trans("MailFrom") . ': ' . $object->email_from;
923
            $htmltooltip .= '<br>' . $langs->trans("MailReply") . ': ' . $object->origin_replyto;
924
            $htmltooltip .= '<br>' . $langs->trans("MailReferences") . ': ' . $object->origin_references;
925
            $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
926
            $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy") . ' : ');
927
            $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
928
            $morehtmlref .= dol_escape_htmltag($object->origin_email) . ' <small class="hideonsmartphone opacitymedium">- ' . $form->textwithpicto($langs->trans("CreatedByEmailCollector"), $htmltooltip, 1, 'help', '', 0, 3, 'tooltip') . '</small>';
929
        }
930
931
        $permissiontoedit = $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write');
932
        //$permissiontoedit = 0;
933
934
        // Thirdparty
935
        if (isModEnabled("societe")) {
936
            $morehtmlref .= '<br>';
937
            $morehtmlref .= img_picto($langs->trans("ThirdParty"), 'company', 'class="pictofixedwidth"');
938
            if ($action != 'editcustomer' && $permissiontoedit) {
939
                $morehtmlref .= '<a class="editfielda" href="' . $url_page_current . '?action=editcustomer&token=' . newToken() . '&track_id=' . $object->track_id . '">' . img_edit($langs->transnoentitiesnoconv('SetThirdParty'), 0) . '</a> ';
940
            }
941
            $morehtmlref .= $form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, $action == 'editcustomer' ? 'editcustomer' : 'none', '', 1, 0, 0, array(), 1);
942
            if (!empty($object->socid)) {
943
                $morehtmlref .= ' - <a href="' . constant('BASE_URL') . '/ticket/list.php?socid=' . $object->socid . '&sortfield=t.datec&sortorder=desc">' . img_picto($langs->trans("Tickets"), 'ticket', 'class="pictofixedwidth"') . ' ' . $langs->trans("TicketHistory") . '</a>';
944
            }
945
        }
946
947
        // Project
948
        if (isModEnabled('project')) {
949
            $langs->load("projects");
950
            $morehtmlref .= '<br>';
951
            if ($permissiontoedit) {
952
                $object->fetch_project();
953
                $morehtmlref .= img_picto($langs->trans("Project"), 'project' . ((is_object($object->project) && $object->project->public) ? 'pub' : ''), 'class="pictofixedwidth"');
954
                if ($action != 'classify') {
955
                    $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> ';
956
                }
957
                $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
958
            } else {
959
                if (!empty($object->fk_project)) {
960
                    $object->fetch_project();
961
                    $morehtmlref .= $object->project->getNomUrl(1);
962
                    if ($object->project->title) {
963
                        $morehtmlref .= '<span class="opacitymedium"> - ' . dol_escape_htmltag($object->project->title) . '</span>';
964
                    }
965
                }
966
            }
967
        }
968
969
        // Contract
970
        if (getDolGlobalString('TICKET_LINK_TO_CONTRACT_WITH_HARDLINK')) {
971
            // Deprecated. Duplicate feature. Ticket can already be linked to contract with the generic "Link to" feature.
972
            if (isModEnabled('contract')) {
973
                $langs->load('contracts');
974
                $morehtmlref .= '<br>';
975
                if ($permissiontoedit) {
976
                    $morehtmlref .= img_picto($langs->trans("Contract"), 'contract', 'class="pictofixedwidth"');
977
                    if ($action == 'edit_contrat') {
978
                        $formcontract = new FormContract($db);
979
                        $morehtmlref .= $formcontract->formSelectContract($_SERVER["PHP_SELF"] . '?id=' . $object->id, $object->socid, $object->fk_contract, 'contratid', 0, 1, 1, 1);
980
                    } else {
981
                        $morehtmlref .= '<a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=edit_contrat&token=' . newToken() . '&id=' . $object->id . '">';
982
                        $morehtmlref .= img_edit($langs->trans('SetContract'));
983
                        $morehtmlref .= '</a>';
984
                    }
985
                } else {
986
                    if (!empty($object->fk_contract)) {
987
                        $contratstatic = new Contrat($db);
988
                        $contratstatic->fetch($object->fk_contract);
989
                        //print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
990
                        $morehtmlref .= $contratstatic->getNomUrl(0, '', 1);
991
                    }
992
                }
993
            }
994
        }
995
996
        $morehtmlref .= '</div>';
997
998
        $linkback = '<a href="' . constant('BASE_URL') . '/ticket/list.php?restore_lastsearch_values=1"><strong>' . $langs->trans("BackToList") . '</strong></a> ';
999
1000
        dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref);
1001
1002
        print '<div class="fichecenter">';
1003
        print '<div class="fichehalfleft">';
1004
        print '<div class="underbanner clearboth"></div>';
1005
1006
        print '<table class="border tableforfield centpercent">';
1007
1008
        // Track ID
1009
        print '<tr><td class="titlefield">' . $langs->trans("TicketTrackId") . '</td><td>';
1010
        if (!empty($object->track_id)) {
1011
            if (empty($object->ref)) {
1012
                $object->ref = $object->id;
1013
                print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'track_id');
1014
            } else {
1015
                print $object->track_id;
1016
            }
1017
        } else {
1018
            print $langs->trans('None');
1019
        }
1020
        print '</td></tr>';
1021
1022
        // Subject
1023
        print '<tr><td>';
1024
        print $form->editfieldkey("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1025
        print '</td><td>';
1026
        print $form->editfieldval("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1027
        print '</td></tr>';
1028
1029
        // Creation date
1030
        print '<tr><td>' . $langs->trans("DateCreation") . '</td><td>';
1031
        print dol_print_date($object->datec, 'dayhour', 'tzuser');
1032
        print '<span class="opacitymedium"> - ' . $langs->trans("TimeElapsedSince") . ': <i>' . convertSecondToTime(roundUpToNextMultiple($now - $object->datec, 60)) . '</i></span>';
1033
        print '</td></tr>';
1034
1035
        // Origin
1036
        /*
1037
        if ($object->email_msgid) {
1038
            $texttoshow = $langs->trans("CreatedByEmailCollector");
1039
        } elseif ($object->origin_email) {
1040
            $texttoshow = $langs->trans("FromPublicEmail");
1041
        }
1042
        if ($texttoshow) {
1043
            print '<tr><td class="titlefield fieldname_email_origin">';
1044
            print $langs->trans("Origin");
1045
            print '</td>';
1046
            print '<td class="valuefield fieldname_email_origin">';
1047
            print $texttoshow;
1048
            print '</td></tr>';
1049
        }
1050
        */
1051
1052
        // Read date
1053
        print '<tr><td>' . $langs->trans("TicketReadOn") . '</td><td>';
1054
        if (!empty($object->date_read)) {
1055
            print dol_print_date($object->date_read, 'dayhour', 'tzuser');
1056
            print '<span class="opacitymedium"> - ' . $langs->trans("TicketTimeElapsedBeforeSince") . ': <i>' . convertSecondToTime(roundUpToNextMultiple($object->date_read - $object->datec, 60)) . '</i>';
1057
            print ' / <i>' . convertSecondToTime(roundUpToNextMultiple($now - $object->date_read, 60)) . '</i></span>';
1058
        }
1059
        print '</td></tr>';
1060
1061
        // Close date
1062
        print '<tr><td>' . $langs->trans("TicketCloseOn") . '</td><td>';
1063
        if (!empty($object->date_close)) {
1064
            print dol_print_date($object->date_close, 'dayhour', 'tzuser');
1065
        }
1066
        print '</td></tr>';
1067
1068
        // User assigned
1069
        print '<tr><td>';
1070
        print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
1071
        print $langs->trans("AssignedTo");
1072
        if (isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set', 'alpha') != "assign_ticket" && $user->hasRight('ticket', 'manage')) {
1073
            print '</td><td class="right"><a class="editfielda" href="' . $url_page_current . '?track_id=' . urlencode($object->track_id) . '&set=assign_ticket">' . img_edit($langs->trans('Modify'), '') . '</a>';
1074
        }
1075
        print '</td></tr></table>';
1076
        print '</td><td>';
1077
        if (GETPOST('set', 'alpha') != "assign_ticket" && $object->fk_user_assign > 0) {
1078
            $userstat->fetch($object->fk_user_assign);
1079
            print $userstat->getNomUrl(-1);
1080
        }
1081
1082
        // Show user list to assignate one if status is "read"
1083
        if (GETPOST('set', 'alpha') == "assign_ticket" && $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write')) {
1084
            print '<form method="post" name="ticket" enctype="multipart/form-data" action="' . $url_page_current . '">';
1085
            print '<input type="hidden" name="token" value="' . newToken() . '">';
1086
            print '<input type="hidden" name="action" value="assign_user">';
1087
            print '<input type="hidden" name="track_id" value="' . $object->track_id . '">';
1088
            //print '<label for="fk_user_assign">'.$langs->trans("AssignUser").'</label> ';
1089
            print $form->select_dolusers(empty($object->fk_user_assign) ? $user->id : $object->fk_user_assign, 'fk_user_assign', 1);
1090
            print ' <input type="submit" class="button small" name="btn_assign_user" value="' . $langs->trans("Validate") . '" />';
1091
            print '</form>';
1092
        }
1093
        print '</td></tr>';
1094
1095
        // Progression
1096
        print '<tr><td>';
1097
        print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1098
        print $langs->trans('Progression') . '</td><td class="left">';
1099
        print '</td>';
1100
        if ($action != 'progression' && isset($object->status) && $object->status < $object::STATUS_CLOSED && !$user->socid) {
1101
            print '<td class="right"><a class="editfielda" href="' . $url_page_current . '?action=progression&token=' . newToken() . '&track_id=' . urlencode($object->track_id) . '">' . img_edit($langs->trans('Modify')) . '</a></td>';
1102
        }
1103
        print '</tr></table>';
1104
        print '</td><td>';
1105
        if ($user->hasRight('ticket', 'write') && $action == 'progression') {
1106
            print '<form action="' . $url_page_current . '" method="post">';
1107
            print '<input type="hidden" name="token" value="' . newToken() . '">';
1108
            print '<input type="hidden" name="track_id" value="' . $track_id . '">';
1109
            print '<input type="hidden" name="action" value="set_progression">';
1110
            print '<input type="text" class="flat width75" name="progress" value="' . $object->progress . '">';
1111
            print ' <input type="submit" class="button button-edit small" value="' . $langs->trans('Modify') . '">';
1112
            print '</form>';
1113
        } else {
1114
            print($object->progress > 0 ? $object->progress : '0') . '%';
1115
        }
1116
        print '</td>';
1117
        print '</tr>';
1118
1119
        // Timing (Duration sum of linked fichinter)
1120
        if (isModEnabled('intervention')) {
1121
            $object->fetchObjectLinked();
1122
            $num = count($object->linkedObjects);
1123
            $timing = 0;
1124
            $foundinter = 0;
1125
            if ($num) {
1126
                foreach ($object->linkedObjects as $objecttype => $objects) {
1127
                    if ($objecttype == "fichinter") {
1128
                        foreach ($objects as $fichinter) {
1129
                            $foundinter++;
1130
                            $timing += $fichinter->duration;
1131
                        }
1132
                    }
1133
                }
1134
            }
1135
            print '<tr><td>';
1136
            print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1);
1137
            print '</td><td>';
1138
            print $foundinter ? convertSecondToTime($timing, 'all', getDolGlobalString('MAIN_DURATION_OF_WORKDAY')) : '';
1139
            print '</td></tr>';
1140
        }
1141
1142
        // Other attributes
1143
        include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1144
1145
        print '</table>';
1146
1147
1148
        // End of left column and beginning of right column
1149
        print '</div><div class="fichehalfright">';
1150
1151
1152
        print '<form method="post" name="formticketproperties" action="' . $url_page_current . '">';
1153
        print '<input type="hidden" name="token" value="' . newToken() . '">';
1154
        print '<input type="hidden" name="action" value="change_property">';
1155
        print '<input type="hidden" name="track_id" value="' . $track_id . '">';
1156
        print '<input type="hidden" name="trackid" value="' . $trackid . '">';
1157
1158
        //print '<div class="underbanner clearboth"></div>';
1159
1160
        // View Original message
1161
        $actionobject->viewTicketOriginalMessage($user, $action, $object);
1162
1163
        // Classification of ticket
1164
        print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
1165
        print '<table class="border tableforfield centpercent margintable">';
1166
        print '<tr class="liste_titre">';
1167
        print '<td>';
1168
        print $langs->trans('TicketProperties');
1169
        print '</td>';
1170
        print '<td>';
1171
        if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1172
            print '<input type="submit" class="button smallpaddingimp" name="btn_update_ticket_prop" value="' . $langs->trans("Modify") . '" />';
1173
        } else {
1174
            // Button to edit Properties
1175
            if (isset($object->status) && ($object->status < $object::STATUS_NEED_MORE_INFO || !getDolGlobalInt('TICKET_DISALLOW_CLASSIFICATION_MODIFICATION_EVEN_IF_CLOSED')) && $user->hasRight('ticket', 'write')) {
1176
                print ' <a class="editfielda" href="card.php?track_id=' . $object->track_id . '&set=properties">' . img_edit($langs->trans('Modify')) . '</a>';
1177
            }
1178
        }
1179
        print '</td>';
1180
        print '</tr>';
1181
1182
        if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1183
            print '<tr>';
1184
            // Type
1185
            print '<td class="titlefield">';
1186
            print $langs->trans('Type');
1187
            print '</td><td>';
1188
            $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2);
1189
            print '</td>';
1190
            print '</tr>';
1191
            // Group
1192
            print '<tr>';
1193
            print '<td>';
1194
            print $langs->trans('TicketCategory');
1195
            print '</td><td>';
1196
            $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2, 0, 0, 0, 'maxwidth500 widthcentpercentminusxx');
1197
            print '</td>';
1198
            print '</tr>';
1199
            // Severity
1200
            print '<tr>';
1201
            print '<td>';
1202
            print $langs->trans('TicketSeverity');
1203
            print '</td><td>';
1204
            $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2);
1205
            print '</td>';
1206
            print '</tr>';
1207
        } else {
1208
            // Type
1209
            print '<tr><td class="titlefield">' . $langs->trans("Type") . '</td><td>';
1210
            if (!empty($object->type_code)) {
1211
                print $langs->getLabelFromKey($db, 'TicketTypeShort' . $object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
1212
            }
1213
            print '</td></tr>';
1214
            // Group
1215
            $s = '';
1216
            if (!empty($object->category_code)) {
1217
                $s = $langs->getLabelFromKey($db, 'TicketCategoryShort' . $object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
1218
            }
1219
            print '<tr><td>' . $langs->trans("TicketCategory") . '</td><td class="tdoverflowmax200" title="' . dol_escape_htmltag($s) . '">';
1220
            print dol_escape_htmltag($s);
1221
            print '</td></tr>';
1222
            // Severity
1223
            print '<tr><td>' . $langs->trans("TicketSeverity") . '</td><td>';
1224
            if (!empty($object->severity_code)) {
1225
                print $langs->getLabelFromKey($db, 'TicketSeverityShort' . $object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
1226
            }
1227
            print '</td></tr>';
1228
        }
1229
        print '</table>'; // End table actions
1230
        print '</div>';
1231
1232
        print '</form>';
1233
1234
        // Tags/Categories
1235
        if (isModEnabled('category')) {
1236
            print '<table class="border centpercent tableforfield">';
1237
            print '<tr>';
1238
            print '<td class="valignmiddle titlefield">';
1239
            print '<table class="nobordernopadding centpercent"><tr><td class="titlefield">';
1240
            print $langs->trans("Categories");
1241
            if ($action != 'categories' && !$user->socid) {
1242
                print '<td class="right"><a class="editfielda" href="' . $url_page_current . '?action=categories&amp;track_id=' . $object->track_id . '">' . img_edit($langs->trans('Modify')) . '</a></td>';
1243
            }
1244
            print '</table>';
1245
            print '</td>';
1246
1247
            if ($user->hasRight('ticket', 'write') && $action == 'categories') {
1248
                $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
1249
                if (is_array($cate_arbo)) {
1250
                    // Categories
1251
                    print '<td colspan="3">';
1252
                    print '<form action="' . $url_page_current . '" method="POST">';
1253
                    print '<input type="hidden" name="token" value="' . newToken() . '">';
1254
                    print '<input type="hidden" name="track_id" value="' . $track_id . '">';
1255
                    print '<input type="hidden" name="action" value="set_categories">';
1256
1257
                    $category = new Categorie($db);
1258
                    $cats = $category->containing($object->id, 'ticket');
1259
                    $arrayselected = array();
1260
                    foreach ($cats as $cat) {
1261
                        $arrayselected[] = $cat->id;
1262
                    }
1263
1264
                    print img_picto('', 'category', 'class="pictofixedwidth"') . $form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'maxwidth500 widthcentpercentminusx', 0, 0);
1265
                    print '<input type="submit" class="button button-edit smallpaddingimp" value="' . $langs->trans('Save') . '">';
1266
                    print '</form>';
1267
                    print "</td>";
1268
                }
1269
            } else {
1270
                print '<td colspan="3">';
1271
                print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1);
1272
                print "</td></tr>";
1273
            }
1274
1275
            print '</table>';
1276
        }
1277
1278
1279
        // Display navbar with links to change ticket status
1280
        print '<!-- navbar with status -->';
1281
        if (!$user->socid && $user->hasRight('ticket', 'write') && isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set') !== 'properties') {
1282
            $actionobject->viewStatusActions($object);
1283
        }
1284
1285
1286
        if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1287
            print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png');
1288
1289
            print '<div class="div-table-responsive-no-min">';
1290
            print '<div class="tagtable centpercent noborder allwidth">';
1291
1292
            print '<div class="tagtr liste_titre">';
1293
            print '<div class="tagtd">' . $langs->trans("Source") . '</div>
1294
			<div class="tagtd">' . $langs->trans("Company") . '</div>
1295
			<div class="tagtd">' . $langs->trans("Contacts") . '</div>
1296
			<div class="tagtd">' . $langs->trans("ContactType") . '</div>
1297
			<div class="tagtd">' . $langs->trans("Phone") . '</div>
1298
			<div class="tagtd center">' . $langs->trans("Status") . '</div>';
1299
            print '</div><!-- tagtr -->';
1300
1301
            // Contact list
1302
            $companystatic = new Societe($db);
1303
            $contactstatic = new Contact($db);
1304
            $userstatic = new User($db);
1305
            $var = false;
1306
            foreach (array('internal', 'external') as $source) {
1307
                $tmpobject = $object;
1308
                $tab = $tmpobject->listeContact(-1, $source);
1309
                '@phan-var-force array<array{source:string,id:int,rowid:int,email:string,civility:string,firstname:string,lastname:string,labeltype:string,libelle:string,socid:int,code:string,status:int,statuscontact:string,fk_c_typecontact:string,phone:string,phone_mobile:string,nom:string}> $tab';
1310
                $num = is_array($tab) ? 0 : count($tab);
1311
                $i = 0;
1312
                foreach (array_keys($tab) as $i) {
1313
                    $var = !$var;
1314
                    print '<div class="tagtr ' . ($var ? 'pair' : 'impair') . '">';
1315
1316
                    print '<div class="tagtd left">';
1317
                    if ($tab[$i]['source'] == 'internal') {
1318
                        echo $langs->trans("User");
1319
                    }
1320
1321
                    if ($tab[$i]['source'] == 'external') {
1322
                        echo $langs->trans("ThirdPartyContact");
1323
                    }
1324
1325
                    print '</div>';
1326
                    print '<div class="tagtd left">';
1327
1328
                    if ($tab[$i]['socid'] > 0) {
1329
                        $companystatic->fetch($tab[$i]['socid']);
1330
                        echo $companystatic->getNomUrl(-1);
1331
                    }
1332
                    if ($tab[$i]['socid'] < 0) {
1333
                        echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
1334
                    }
1335
                    if (!$tab[$i]['socid']) {
1336
                        echo '&nbsp;';
1337
                    }
1338
                    print '</div>';
1339
1340
                    print '<div class="tagtd">';
1341
                    if ($tab[$i]['source'] == 'internal') {
1342
                        if ($userstatic->fetch($tab[$i]['id'])) {
1343
                            print $userstatic->getNomUrl(-1);
1344
                        }
1345
                    }
1346
                    if ($tab[$i]['source'] == 'external') {
1347
                        if ($contactstatic->fetch($tab[$i]['id'])) {
1348
                            print $contactstatic->getNomUrl(-1);
1349
                        }
1350
                    }
1351
                    print ' </div>
1352
					<div class="tagtd">' . $tab[$i]['libelle'] . '</div>';
1353
1354
                    print '<div class="tagtd">';
1355
1356
                    print dol_print_phone($tab[$i]['phone'], '', '', '', 'AC_TEL') . '<br>';
1357
1358
                    if (!empty($tab[$i]['phone_perso'])) {
1359
                        //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' ';
1360
                        print '<br>' . dol_print_phone($tab[$i]['phone_perso'], '', '', '', 'AC_TEL') . '<br>';
1361
                    }
1362
                    if (!empty($tab[$i]['phone_mobile'])) {
1363
                        //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' ';
1364
                        print dol_print_phone($tab[$i]['phone_mobile'], '', '', '', 'AC_TEL') . '<br>';
1365
                    }
1366
                    print '</div>';
1367
1368
                    print '<div class="tagtd center">';
1369
                    if ($object->status >= 0) {
1370
                        echo '<a href="contact.php?track_id=' . $object->track_id . '&amp;action=swapstatut&amp;ligne=' . $tab[$i]['rowid'] . '">';
1371
                    }
1372
1373
                    if ($tab[$i]['source'] == 'internal') {
1374
                        $userstatic->id = $tab[$i]['id'];
1375
                        $userstatic->lastname = $tab[$i]['lastname'];
1376
                        $userstatic->firstname = $tab[$i]['firstname'];
1377
                        echo $userstatic->LibStatut($tab[$i]['statuscontact'], 3);
1378
                    }
1379
                    if ($tab[$i]['source'] == 'external') {
1380
                        $contactstatic->id = $tab[$i]['id'];
1381
                        $contactstatic->lastname = $tab[$i]['lastname'];
1382
                        $contactstatic->firstname = $tab[$i]['firstname'];
1383
                        echo $contactstatic->LibStatut($tab[$i]['statuscontact'], 3);
1384
                    }
1385
                    if ($object->status >= 0) {
1386
                        echo '</a>';
1387
                    }
1388
1389
                    print '</div>';
1390
1391
                    print '</div><!-- tagtr -->';
1392
1393
                    $i++;
1394
                }
1395
            }
1396
1397
            print '</div><!-- contact list -->';
1398
            print '</div>';
1399
        }
1400
1401
        print '</div></div>';
1402
        print '<div class="clearboth"></div>';
1403
1404
        print dol_get_fiche_end();
1405
1406
1407
        // Buttons for actions
1408
        if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') {
1409
            print '<div class="tabsAction">' . "\n";
1410
            $parameters = array();
1411
            $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1412
            if ($reshook < 0) {
1413
                setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1414
            }
1415
1416
            if (empty($reshook)) {
1417
                // Email
1418
                if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1419
                    print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"] . '?action=presend_addmessage&send_email=1&private_message=0&mode=init&token=' . newToken() . '&track_id=' . $object->track_id . '#formmailbeforetitle', '');
1420
                }
1421
1422
                // Show link to add a message (if read and not closed)
1423
                if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1424
                    print dolGetButtonAction('', $langs->trans('TicketAddPrivateMessage'), 'default', $_SERVER["PHP_SELF"] . '?action=presend_addmessage&mode=init&token=' . newToken() . '&track_id=' . $object->track_id . '#formmailbeforetitle', '');
1425
                }
1426
1427
                // Link to create an intervention
1428
                // socid is needed otherwise fichinter ask it and forgot origin after form submit :\
1429
                if (!$object->fk_soc && $user->hasRight("ficheinter", "creer")) {
1430
                    print dolGetButtonAction($langs->trans('UnableToCreateInterIfNoSocid'), $langs->trans('TicketAddIntervention'), 'default', $_SERVER['PHP_SELF'] . '#', '', false);
1431
                }
1432
                if ($object->fk_soc > 0 && isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ficheinter', 'creer')) {
1433
                    print dolGetButtonAction('', $langs->trans('TicketAddIntervention'), 'default', constant('BASE_URL') . '/fichinter/card.php?action=create&token=' . newToken() . '&socid=' . $object->fk_soc . '&origin=ticket_ticket&originid=' . $object->id, '');
1434
                }
1435
1436
                // Close ticket if status is read
1437
                if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1438
                    print dolGetButtonAction('', $langs->trans('CloseTicket'), 'default', $_SERVER["PHP_SELF"] . '?action=close&token=' . newToken() . '&track_id=' . $object->track_id, '');
1439
                }
1440
1441
                // Abandon ticket if status is read
1442
                if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1443
                    print dolGetButtonAction('', $langs->trans('AbandonTicket'), 'default', $_SERVER["PHP_SELF"] . '?action=abandon&token=' . newToken() . '&track_id=' . $object->track_id, '');
1444
                }
1445
1446
                // Re-open ticket
1447
                if (!$user->socid && (isset($object->status) && ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED)) && !$user->socid) {
1448
                    print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"] . '?action=reopen&token=' . newToken() . '&track_id=' . $object->track_id, '');
1449
                }
1450
1451
                // Edit ticket
1452
                if ($permissiontoedit) {
1453
                    print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=edit&token=' . newToken(), '', $permissiontoedit);
1454
                }
1455
1456
                // Delete ticket
1457
                if ($user->hasRight('ticket', 'delete') && !$user->socid) {
1458
                    print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"] . '?action=delete&token=' . newToken() . '&track_id=' . $object->track_id, '');
1459
                }
1460
            }
1461
            print '</div>' . "\n";
1462
        }
1463
1464
        // Select mail models is same action as presend
1465
        if (GETPOST('modelselected')) {
1466
            $action = 'presend';
1467
        }
1468
        // Set $action to correct value for the case we used presend action to add a message
1469
        if (GETPOSTISSET('actionbis') && $action == 'presend') {
1470
            $action = 'presend_addmessage';
1471
        }
1472
1473
        // add a message
1474
        if ($action == 'presend' || $action == 'presend_addmessage') {
1475
            if ($object->fk_soc > 0) {
1476
                $object->fetch_thirdparty();
1477
            }
1478
1479
            $outputlangs = $langs;
1480
            $newlang = '';
1481
            if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1482
                $newlang = GETPOST('lang_id', 'aZ09');
1483
            } elseif (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && is_object($object->thirdparty)) {
1484
                $newlang = $object->thirdparty->default_lang;
1485
            }
1486
            if (!empty($newlang)) {
1487
                $outputlangs = new Translate("", $conf);
1488
                $outputlangs->setDefaultLang($newlang);
1489
            }
1490
1491
            $arrayoffamiliestoexclude = array('objectamount');
1492
1493
            $action = 'add_message'; // action to use to post the message
1494
            $modelmail = 'ticket_send';
1495
1496
            // Substitution array
1497
            $morehtmlright = '';
1498
            $help = "";
1499
            $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object);
1500
            complete_substitutions_array($substitutionarray, $outputlangs, $object);
1501
            $morehtmlright .= $form->textwithpicto('<span class="opacitymedium">' . $langs->trans("TicketMessageSubstitutionReplacedByGenericValues") . '</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution');
1502
1503
            print '<div>';
1504
1505
            print '<div id="formmailbeforetitle" name="formmailbeforetitle"></div>';
1506
1507
            print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket');
1508
1509
            print '<hr>';
1510
1511
            $formticket = new FormTicket($db);
1512
1513
            $formticket->action = $action;
1514
            $formticket->track_id = $object->track_id;
1515
            $formticket->ref = $object->ref;
1516
            $formticket->id = $object->id;
1517
            $formticket->trackid = 'tic' . $object->id;
1518
1519
            $formticket->withfile = 2;
1520
            $formticket->withcancel = 1;
1521
            $formticket->param = array('fk_user_create' => $user->id);
1522
            $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang);
1523
1524
            // Table of additional post parameters
1525
            $formticket->param['models'] = $modelmail;
1526
            $formticket->param['models_id'] = GETPOSTINT('modelmailselected');
1527
            //$formticket->param['socid']=$object->fk_soc;
1528
            $formticket->param['returnurl'] = $_SERVER["PHP_SELF"] . '?track_id=' . $object->track_id;
1529
1530
            $formticket->withsubstit = 1;
1531
            $formticket->substit = $substitutionarray;
1532
            $formticket->backtopage = $backtopage;
1533
1534
            $formticket->showMessageForm('100%');
1535
            print '</div>';
1536
        }
1537
1538
        // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
1539
        if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) {
1540
            $param = '&id=' . $object->id;
1541
            if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1542
                $param .= '&contextpage=' . $contextpage;
1543
            }
1544
            if ($limit > 0 && $limit != $conf->liste_limit) {
1545
                $param .= '&limit=' . $limit;
1546
            }
1547
            if ($actioncode) {
1548
                $param .= '&actioncode=' . urlencode($actioncode);
1549
            }
1550
            if ($search_agenda_label) {
1551
                $param .= '&search_agenda_label=' . urlencode($search_agenda_label);
1552
            }
1553
1554
            $morehtmlright = '';
1555
1556
            $messagingUrl = constant('BASE_URL') . '/ticket/agenda.php?track_id=' . $object->track_id;
1557
            $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 1);
1558
1559
            // Show link to add a message (if read and not closed)
1560
            $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1561
            $url = 'card.php?track_id=' . $object->track_id . '&action=presend_addmessage&mode=init';
1562
            $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fa fa-comment-dots', $url, 'add-new-ticket-title-button', $btnstatus);
1563
1564
            // Show link to add event (if read and not closed)
1565
            $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1566
            $url = dol_buildpath('/comm/action/card.php', 1) . '?action=create&datep=' . date('YmdHi') . '&origin=ticket&originid=' . $object->id . '&projectid=' . $object->fk_project . '&backtopage=' . $_SERVER["PHP_SELF"] . ('?track_id=' . $object->track_id);
1567
            $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus);
1568
1569
            print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
1570
1571
            // List of all actions
1572
            $filters = array();
1573
            $filters['search_agenda_label'] = $search_agenda_label;
1574
            $filters['search_rowid'] = $search_rowid;
1575
1576
            show_actions_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder);
1577
        }
1578
1579
        if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') {
1580
            print '<div class="fichecenter"><div class="fichehalfleft">';
1581
            print '<a name="builddoc"></a>'; // ancre
1582
            /*
1583
             * Generated documents
1584
             */
1585
            $filename = dol_sanitizeFileName($object->ref);
1586
            $filedir = $upload_dir . "/" . dol_sanitizeFileName($object->ref);
1587
            $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id;
1588
            $genallowed = $permissiontoadd;
1589
            $delallowed = $permissiontodelete;
1590
            $codelang = '';
1591
            if ($object->fk_soc > 0) {
1592
                $object->fetch_thirdparty();
1593
                $codelang = $object->thirdparty->default_lang;
1594
            }
1595
1596
            print $formfile->showdocuments('ticket', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $codelang);
1597
1598
            // Show links to link elements
1599
            $linktoelem = $form->showLinkToObjectBlock($object, null, array('ticket'));
1600
            $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1601
1602
            // Show direct link to public interface
1603
            print '<br><!-- Link to public interface -->' . "\n";
1604
            print showDirectPublicLink($object) . '<br>';
1605
            print '</div>';
1606
1607
            if (!getDolGlobalString('MAIN_HIDE_MESSAGES_ON_CARD')) {
1608
                print '<div class="fichehalfright">';
1609
1610
                $MAXEVENT = 10;
1611
1612
                $morehtmlcenter = '<div class="nowraponall">';
1613
                $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', constant('BASE_URL') . '/ticket/messaging.php?id=' . $object->id);
1614
                $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', constant('BASE_URL') . '/ticket/agenda.php?id=' . $object->id);
1615
                $morehtmlcenter .= '</div>';
1616
1617
                // List of actions on element
1618
                $formactions = new FormActions($db);
1619
                $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
1620
1621
                print '</div>';
1622
            }
1623
1624
            print '</div>';
1625
        }
1626
    }
1627
}
1628
1629
// End of page
1630
ViewMain::llxFooter();
1631
$db->close();
1632