dolibarr 21.0.0-alpha
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2016 Jean-François FERRY <hello@librethic.io>
3 * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
4 * Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2021-2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2022-2023 Charlene Benke <charlene@patas-monkey.com>
8 * Copyright (C) 2023 Benjamin Falière <benjamin.faliere@altairis.fr>
9 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 Irvine FLEITH <irvine.fleith@atm-consulting.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
32// Load Dolibarr environment
33require '../main.inc.php';
34require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/class/html.formticket.class.php';
36require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
42require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
43
44if (isModEnabled('project')) {
45 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
46 include_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
47 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
48}
49if (isModEnabled('contract')) {
50 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcontract.class.php';
51 include_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php';
52 include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
53}
54
55// Load translation files required by the page
56$langs->loadLangs(array("companies", "other", "ticket"));
57
58// Get parameters
59$id = GETPOSTINT('id');
60$ref = GETPOST('ref', 'alpha');
61$track_id = GETPOST('track_id', 'alpha', 3);
62$socid = GETPOSTINT('socid');
63$contactid = GETPOSTINT('contactid');
64$projectid = GETPOSTINT('projectid');
65$notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
66
67$action = GETPOST('action', 'aZ09');
68$cancel = GETPOST('cancel', 'alpha');
69$backtopage = GETPOST('backtopage', 'alpha');
70$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
71
72$sortfield = GETPOST('sortfield', 'aZ09comma') ? GETPOST('sortfield', 'aZ09comma') : "a.datep";
73$sortorder = GETPOST('sortorder', 'aZ09comma') ? GETPOST('sortorder', 'aZ09comma') : "desc";
74$search_rowid = GETPOST('search_rowid');
75$search_agenda_label = GETPOST('search_agenda_label');
76
77if (GETPOST('actioncode', 'array')) {
78 $actioncode = GETPOST('actioncode', 'array', 3);
79 if (!count($actioncode)) {
80 $actioncode = '0';
81 }
82} else {
83 $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT'));
84}
85
86
87// Initialize a technical object to manage hooks of ticket. Note that conf->hooks_modules contains array array
88$hookmanager->initHooks(array('ticketcard', 'globalcard'));
89
90$object = new Ticket($db);
91$extrafields = new ExtraFields($db);
92
93// Fetch optionals attributes and labels
94$extrafields->fetch_name_optionals_label($object->table_element);
95
96$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
97
98// Initialize array of search criteria
99$search_all = GETPOST("search_all", 'alpha');
100$search = array();
101foreach ($object->fields as $key => $val) {
102 if (GETPOST('search_'.$key, 'alpha')) {
103 $search[$key] = GETPOST('search_'.$key, 'alpha');
104 }
105}
106
107if (empty($action) && empty($id) && empty($ref)) {
108 $action = 'view';
109}
110
111// Select mail models is same action as add_message
112if (GETPOST('modelselected', 'alpha')) {
113 $action = 'presend';
114}
115
116// Load object
117//include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'. Include fetch and fetch_thirdparty but not fetch_optionals
118if ($id || $track_id || $ref) {
119 $res = $object->fetch($id, $ref, $track_id);
120 if ($res >= 0) {
121 $id = $object->id;
122 $track_id = $object->track_id;
123 }
124}
125
126$now = dol_now();
127
128$actionobject = new ActionsTicket($db);
129
130// Store current page url
131$url_page_current = DOL_URL_ROOT.'/ticket/card.php';
132
133// Security check - Protection if external user
134if ($user->socid > 0) {
135 $socid = $user->socid;
136}
137$result = restrictedArea($user, 'ticket', $object->id);
138
139$triggermodname = 'TICKET_MODIFY';
140
141// Permissions
142$permissiontoread = $user->hasRight('ticket', 'read');
143$permissiontoadd = $user->hasRight('ticket', 'write');
144$permissiontodelete = $user->hasRight('ticket', 'delete');
145
146$upload_dir = $conf->ticket->dir_output;
147
148
149
150/*
151 * Actions
152 */
153
154$parameters = array();
155$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
156if ($reshook < 0) {
157 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
158}
159
160$error = 0;
161if (empty($reshook)) {
162 // Purge search criteria
163 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{
164 $actioncode = '';
165 $search_agenda_label = '';
166 }
167
168 $backurlforlist = DOL_URL_ROOT . '/ticket/list.php';
169
170 if (empty($backtopage) || ($cancel && empty($id))) {
171 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
172 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
173 $backtopage = $backurlforlist;
174 } else {
175 $backtopage = DOL_URL_ROOT . '/ticket/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__');
176 }
177 }
178 }
179
180 if ($cancel) {
181 if (!empty($backtopageforcancel)) {
182 header("Location: " . $backtopageforcancel);
183 exit;
184 } elseif (!empty($backtopage)) {
185 header("Location: " . $backtopage);
186 exit;
187 }
188 $action = 'view';
189 }
190
191 if (($action == 'add' || ($action == 'update' && $object->status < Ticket::STATUS_CLOSED)) && $permissiontoadd) {
192 $ifErrorAction = ($action == 'add' ? 'create' : 'edit'); // Test on permission not required here
193 if ($action == 'add') { // Test on permission already done
194 $object->track_id = null;
195 }
196 $error = 0;
197
198 $fieldsToCheck = [
199 'ref' => ['check' => 'alpha', 'langs' => 'Ref'],
200 'type_code' => ['check' => 'alpha', 'langs' => 'TicketTypeRequest'],
201 'category_code' => ['check' => 'alpha', 'langs' => 'TicketCategory'],
202 'severity_code' => ['check' => 'alpha', 'langs' => 'TicketSeverity'],
203 'subject' => ['check' => 'alphanohtml', 'langs' => 'Subject'],
204 'message' => ['check' => 'restricthtml', 'langs' => 'Message']
205 ];
206
207 FormTicket::checkRequiredFields($fieldsToCheck, $error);
208
209 if (!empty($error)) {
210 $action = $ifErrorAction;
211 }
212
213 $ret = $extrafields->setOptionalsFromPost(null, $object);
214 if ($ret < 0) {
215 $error++;
216 }
217 $getRef = GETPOST('ref', 'alpha');
218
219 if (!empty($getRef)) {
220 $isExistingRef = $object->checkExistingRef($action, $getRef);
221 } else {
222 $isExistingRef = true;
223 }
224
225 $style = '';
226
227 if ($isExistingRef) {
228 if ($action == 'update') { // Test on permission already done
229 $error++;
230 $action = 'edit';
231 $style = 'errors';
232 } elseif ($action == 'add') { // Test on permission already done
233 $object->ref = $object->getDefaultRef();
234 $object->track_id = null;
235 $style = 'warnings';
236 }
237 if (!empty($getRef)) {
238 setEventMessage($langs->trans('TicketRefAlreadyUsed', $getRef, $object->ref), $style);
239 }
240 }
241 if (!$error) {
242 $db->begin();
243
244 $object->type_code = GETPOST('type_code', 'alpha');
245 $object->category_code = GETPOST('category_code', 'alpha');
246 $object->severity_code = GETPOST('severity_code', 'alpha');
247 $object->subject = GETPOST('subject', 'alpha');
248 $object->message = GETPOST('message', 'restricthtml');
249 $object->fk_soc = GETPOSTINT('socid');
250 $fk_user_assign = GETPOSTINT('fk_user_assign');
251 $object->fk_project = GETPOSTINT('projectid');
252 $object->fk_contract = GETPOSTISSET('contractid') ? GETPOSTINT('contractid') : GETPOSTINT('contratid');
253
254 if ($fk_user_assign > 0) {
255 $object->fk_user_assign = $fk_user_assign;
256 $object->status = $object::STATUS_ASSIGNED;
257 }
258
259 if ($action == 'add') { // Test on permission already done
260 $object->type_code = GETPOST("type_code", 'alpha');
261 $object->type_label = $langs->trans($langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'));
262 $object->category_label = $langs->trans($langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'));
263 $object->severity_label = $langs->trans($langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'));
264 $object->fk_user_create = $user->id;
265 $object->email_from = $user->email;
266 $object->origin_email = null;
267 $notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
268 $object->notify_tiers_at_create = empty($notifyTiers) ? 0 : 1;
269 $object->context['contact_id'] = GETPOSTINT('contact_id');
270 $id = $object->create($user);
271 } else {
272 $id = $object->update($user);
273 }
274
275 if ($id <= 0) {
276 $error++;
277 setEventMessages($object->error, $object->errors, 'errors');
278 $action = $ifErrorAction;
279 }
280
281 if (!$error) {
282 // Category association
283 $categories = GETPOST('categories', 'array');
284 $object->setCategories($categories);
285 }
286
287 if ($action == 'add') { // Test on permission already done
288 if (!$error) {
289 // Add contact
290 $contactid = GETPOSTINT('contactid');
291 $type_contact = GETPOST("type", 'alpha');
292
293 if ($contactid > 0 && $type_contact) {
294 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
295 $result = $object->add_contact($contactid, $typeid, 'external');
296 }
297
298 // Link ticket to project
299 if (GETPOST('origin', 'alpha') == 'projet') {
300 $projectid = GETPOSTINT('originid');
301 } else {
302 $projectid = GETPOSTINT('projectid');
303 }
304
305 if ($projectid > 0) {
306 $object->setProject($projectid);
307 }
308
309 // Auto mark as read if created from backend
310 if (getDolGlobalString('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND') && $user->hasRight('ticket', 'write')) {
311 if (!$object->markAsRead($user) > 0) {
312 setEventMessages($object->error, $object->errors, 'errors');
313 }
314 }
315
316 // Auto assign user
317 if ((empty($fk_user_assign) && getDolGlobalInt('TICKET_AUTO_ASSIGN_USER_CREATE') == 1) || (getDolGlobalInt('TICKET_AUTO_ASSIGN_USER_CREATE') == 2)) {
318 $result = $object->assignUser($user, $user->id, 1);
319 $object->add_contact($user->id, "SUPPORTTEC", 'internal');
320 }
321 }
322
323 if (!$error) {
324 // File transfer
325 $object->copyFilesForTicket(''); // trackid is forced to '' because files were uploaded when no id for ticket exists yet and trackid was ''
326 }
327 }
328 if (!$error) {
329 $db->commit();
330
331 if (!empty($backtopage)) {
332 if (empty($id)) {
333 $url = $backtopage;
334 } else {
335 $url = 'card.php?track_id=' . urlencode($object->track_id);
336 }
337 } else {
338 $url = 'card.php?track_id=' . urlencode($object->track_id);
339 }
340
341 header("Location: " . $url);
342 exit;
343 } else {
344 $db->rollback();
345 setEventMessages($object->error, $object->errors, 'errors');
346 }
347 } else {
348 $action = $ifErrorAction;
349 }
350 }
351
352 // Mark as Read
353 if ($action == "set_read" && $permissiontoadd) {
354 $object->fetch('', '', GETPOST("track_id", 'alpha'));
355
356 if ($object->markAsRead($user) > 0) {
357 setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs');
358
359 header("Location: card.php?track_id=" . $object->track_id);
360 exit;
361 } else {
362 setEventMessages($object->error, $object->errors, 'errors');
363 }
364 $action = 'view';
365 }
366
367 // Assign to someone
368 if ($action == "assign_user" && GETPOST('btn_assign_user', 'alpha') && $permissiontoadd) {
369 $object->fetch('', '', GETPOST("track_id", 'alpha'));
370 $useroriginassign = $object->fk_user_assign;
371 $usertoassign = GETPOSTINT('fk_user_assign');
372
373 /*if (! ($usertoassign > 0)) {
374 $error++;
375 array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("AssignedTo")));
376 $action = 'view';
377 }*/
378
379 if (!$error) {
380 $ret = $object->assignUser($user, $usertoassign);
381 if ($ret < 0) {
382 $error++;
383 }
384 }
385
386 if (!$error) { // Update list of contacts
387 // If a user has already been assigned, we delete him from the contacts.
388 if ($useroriginassign > 0) {
389 $internal_contacts = $object->listeContact(-1, 'internal', 0, 'SUPPORTTEC');
390 foreach ($internal_contacts as $key => $contact) {
391 if ($contact['id'] !== $usertoassign) {
392 $result = $object->delete_contact($contact['rowid']);
393 if ($result < 0) {
394 $error++;
395 setEventMessages($object->error, $object->errors, 'errors');
396 }
397 }
398 }
399 }
400
401 if ($usertoassign > 0 && $usertoassign !== $useroriginassign) {
402 $result = $object->add_contact($usertoassign, "SUPPORTTEC", 'internal', $notrigger = 0);
403 if ($result < 0) {
404 $error++;
405 setEventMessages($object->error, $object->errors, 'errors');
406 }
407 }
408 }
409
410 if (!$error) {
411 // Log action in ticket logs table
412 $object->fetch_user($usertoassign);
413
414 setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs');
415 header("Location: card.php?track_id=" . $object->track_id);
416 exit;
417 } else {
418 array_push($object->errors, $object->error);
419 }
420 $action = 'view';
421 }
422
423 // Action to add a message (private or not, with email or not).
424 // This may also send an email (concatenated with email_intro and email footer if checkbox was selected)
425 if ($action == 'add_message' && GETPOSTISSET('btn_add_message') && $permissiontoread) {
426 $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0), 0);
427
428 if ($ret > 0) {
429 if (!empty($backtopage)) {
430 $url = $backtopage;
431 } else {
432 $url = 'card.php?track_id=' . urlencode($object->track_id);
433 }
434
435 header("Location: " . $url);
436 exit;
437 } else {
438 setEventMessages($object->error, $object->errors, 'errors');
439 $action = 'presend';
440 }
441 }
442
443 if (($action == "confirm_close" || $action == "confirm_abandon") && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
444 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
445
446 if ($object->close($user, ($action == "confirm_abandon" ? 1 : 0))) {
447 setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs');
448
449 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
450 header("Location: " . $url);
451 exit;
452 } else {
453 $action = '';
454 setEventMessages($object->error, $object->errors, 'errors');
455 }
456 }
457
458 if ($action == "confirm_public_close" && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
459 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
460 if ($_SESSION['email_customer'] == $object->origin_email || $_SESSION['email_customer'] == $object->thirdparty->email) {
461 $object->context['contact_id'] = GETPOSTINT('contact_id');
462
463 $object->close($user);
464
465 setEventMessages('<div class="confirm">' . $langs->trans('TicketMarkedAsClosed') . '</div>', null, 'mesgs');
466
467 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
468 header("Location: " . $url);
469 exit;
470 } else {
471 setEventMessages($object->error, $object->errors, 'errors');
472 $action = '';
473 }
474 }
475
476 if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $permissiontodelete) {
477 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
478 if ($object->delete($user) > 0) {
479 setEventMessages('<div class="confirm">' . $langs->trans('TicketDeletedSuccess') . '</div>', null, 'mesgs');
480 header("Location: " . DOL_URL_ROOT . "/ticket/list.php");
481 exit;
482 } else {
483 $langs->load("errors");
484 $mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
485 $action = '';
486 }
487 }
488 }
489
490 // Set parent company
491 if ($action == 'set_thirdparty' && $user->hasRight('ticket', 'write')) {
492 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
493 $result = $object->setCustomer(GETPOSTINT('editcustomer'));
494 $url = $_SERVER["PHP_SELF"] . '?track_id=' . GETPOST('track_id', 'alpha');
495 header("Location: " . $url);
496 exit();
497 }
498 }
499
500 // Set progress status
501 if ($action == 'set_progression' && $user->hasRight('ticket', 'write')) {
502 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
503 $result = $object->setProgression(GETPOST('progress', 'alpha'));
504
505 $url = 'card.php?track_id=' . $object->track_id;
506 header("Location: " . $url);
507 exit();
508 }
509 }
510
511 // Set categories
512 if ($action == 'set_categories' && $user->hasRight('ticket', 'write')) {
513 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
514 $result = $object->setCategories(GETPOST('categories', 'array'));
515
516 $url = 'card.php?track_id=' . $object->track_id;
517 header("Location: " . $url);
518 exit();
519 }
520 }
521
522 // Set Subject
523 if ($action == 'setsubject' && $user->hasRight('ticket', 'write')) {
524 if ($object->fetch(GETPOSTINT('id'))) {
525 if ($action == 'setsubject') { // Test on permission already done
526 $object->subject = GETPOST('subject', 'alphanohtml');
527 }
528
529 if ($action == 'setsubject' && empty($object->subject)) { // Test on permission already done
530 $error++;
531 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors');
532 }
533
534 if (!$error) {
535 if (!$object->update($user) >= 0) {
536 $error++;
537 setEventMessages($object->error, $object->errors, 'errors');
538 }
539 }
540
541 header("Location: " . $_SERVER['PHP_SELF'] . "?track_id=" . $object->track_id);
542 exit;
543 }
544 }
545
546 if ($action == 'confirm_reopen' && $user->hasRight('ticket', 'manage') && !GETPOST('cancel')) {
547 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
548 // prevent browser refresh from reopening ticket several times
549 if ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED) {
550 if ($object->fk_user_assign != null) {
551 $res = $object->setStatut(Ticket::STATUS_ASSIGNED, null, '', 'TICKET_MODIFY');
552 } else {
553 $res = $object->setStatut(Ticket::STATUS_NOT_READ, null, '', 'TICKET_MODIFY');
554 }
555 if ($res) {
556 $url = 'card.php?track_id=' . $object->track_id;
557 header("Location: " . $url);
558 exit();
559 } else {
560 $error++;
561 setEventMessages($object->error, $object->errors, 'errors');
562 }
563 }
564 }
565 } elseif ($action == 'classin' && $permissiontoadd) {
566 // Categorisation dans projet
567 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
568 $object->setProject($projectid);
569 $url = 'card.php?track_id=' . $object->track_id;
570 header("Location: " . $url);
571 exit();
572 }
573 } elseif ($action == 'setcontract' && $permissiontoadd) {
574 // Categorisation dans contrat
575 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
576 $object->setContract(GETPOSTINT('contractid'));
577 $url = 'card.php?track_id=' . $object->track_id;
578 header("Location: " . $url);
579 exit();
580 }
581 } elseif ($action == "set_message" && $user->hasRight('ticket', 'manage')) {
582 if (!GETPOST('cancel')) {
583 $object->fetch('', '', GETPOST('track_id', 'alpha'));
584 //$oldvalue_message = $object->message;
585 $fieldtomodify = GETPOST('message_initial', 'restricthtml');
586
587 $object->message = $fieldtomodify;
588 $ret = $object->update($user);
589 if ($ret > 0) {
590 //include_once DOL_DOCUMENT_ROOT.'/core/class/utils_diff.class.php';
591 // output the result of comparing two files as plain text
592 //$log_action .= Diff::toString(Diff::compare(strip_tags($oldvalue_message), strip_tags($object->message)));
593
594 setEventMessages($langs->trans('TicketMessageSuccesfullyUpdated'), null, 'mesgs');
595 } else {
596 $error++;
597 setEventMessages($object->error, $object->errors, 'errors');
598 }
599 }
600
601 $action = 'view';
602 } elseif ($action == 'confirm_set_status' && $permissiontoadd && !GETPOST('cancel')) {
603 // Reopen ticket
604 if ($object->fetch(GETPOSTINT('id'), GETPOST('track_id', 'alpha')) >= 0) {
605 $new_status = GETPOSTINT('new_status');
606 //$old_status = $object->status;
607 $res = $object->setStatut($new_status);
608 if ($res) {
609 $url = 'card.php?track_id=' . $object->track_id;
610 header("Location: " . $url);
611 exit();
612 } else {
613 $error++;
614 setEventMessages($object->error, $object->errors, 'errors');
615 }
616 }
617 }
618
619 // Action to update an extrafield
620 if ($action == "update_extras" && $permissiontoadd) {
621 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
622
623 $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
624 if ($ret < 0) {
625 $error++;
626 }
627
628 if (!$error) {
629 $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user);
630 if ($result < 0) {
631 $error++;
632 }
633 }
634
635 if ($error) {
636 setEventMessages($object->error, $object->errors, 'errors');
637 $action = 'edit_extras';
638 } else {
639 setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
640 $action = 'view';
641 }
642 }
643
644 if ($action == "change_property" && GETPOST('btn_update_ticket_prop', 'alpha') && $permissiontoadd) {
645 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
646
647 $object->type_code = GETPOST('update_value_type', 'aZ09');
648 $object->severity_code = GETPOST('update_value_severity', 'aZ09');
649 $object->category_code = GETPOST('update_value_category', 'aZ09');
650
651 $ret = $object->update($user);
652 if ($ret > 0) {
653 setEventMessages($langs->trans('TicketUpdated'), null, 'mesgs');
654 } else {
655 $error++;
656 setEventMessages($object->error, $object->errors, 'errors');
657 }
658 $action = 'view';
659 }
660
661
662 $permissiondellink = $user->hasRight('ticket', 'write');
663 include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
664
665 // Actions to build doc
666 include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
667
668 // Actions to send emails
669 $triggersendname = 'TICKET_SENTBYMAIL';
670 $paramname = 'id';
671 $autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add
672 $trackid = 'tic' . $object->id;
673 include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
674
675 // Set $action to correct value for the case we used presend action to add a message
676 if (GETPOSTISSET('actionbis') && $action == 'presend') { // Test on permission not required here
677 $action = 'presend_addmessage';
678 }
679}
680
681
682/*
683 * View
684 */
685
686$userstat = new User($db);
687$form = new Form($db);
688$formfile = new FormFile($db);
689$formticket = new FormTicket($db);
690if (isModEnabled('project')) {
691 $formproject = new FormProjets($db);
692}
693
694$help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket';
695
696$title = $actionobject->getTitle($action);
697
698llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-ticket page-card');
699
700if ($action == 'create' || $action == 'presend') {
701 if (empty($permissiontoadd)) {
702 accessforbidden('NotEnoughPermissions', 0, 1);
703 }
704
705 $formticket = new FormTicket($db);
706
707 print load_fiche_titre($langs->trans('NewTicket'), '', 'ticket');
708
709 $formticket->trackid = ''; // TODO Use a unique key 'tic' to avoid conflict in upload file feature
710 $formticket->withfromsocid = $socid ? $socid : $user->socid;
711 $formticket->withfromcontactid = $contactid ? $contactid : '';
712 $formticket->withtitletopic = 1;
713 $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
714 $formticket->withusercreate = 0;
715 $formticket->withref = 1;
716 $formticket->fk_user_create = $user->id;
717 $formticket->withfile = 2;
718 $formticket->withextrafields = 1;
719 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
720
721 $formticket->withcancel = 1;
722
723 // Init list of files
724 if (GETPOST("mode", "aZ09") == 'init') {
725 $formticket->clear_attached_files();
726 }
727
728 $formticket->showForm(1, 'create', 0, null, $action, $object);
729
730 print dol_get_fiche_end();
731} elseif ($action == 'edit' && $user->rights->ticket->write && $object->status < Ticket::STATUS_CLOSED) {
732 if (empty($permissiontoadd)) {
733 accessforbidden('NotEnoughPermissions', 0, 1);
734 }
735
736 $formticket = new FormTicket($db);
737
739
740 print dol_get_fiche_head($head, 'tabTicket', $langs->trans('Ticket'), -1, 'ticket');
741
742 $formticket->trackid = $object->track_id; // TODO Use a unique key 'tic' to avoid conflict in upload file feature
743 $formticket->withfromsocid = $object->socid;
744 $formticket->withtitletopic = 1;
745 // $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
746 $formticket->withnotifytiersatcreate = 0;
747 $formticket->withusercreate = 0;
748 $formticket->withref = 1;
749 $formticket->fk_user_create = $user->id;
750 $formticket->withfile = 0;
751 $formticket->action = 'update';
752 $formticket->withextrafields = 1;
753 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
754
755 $formticket->withcancel = 1;
756
757 $formticket->showForm(0, 'edit', 0, null, $action, $object);
758
759 print dol_get_fiche_end();
760} 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'])) {
761 if (!empty($res) && $res > 0) {
762 // or for unauthorized internals users
763 if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->hasRight('ticket', 'manage')) {
764 accessforbidden('', 0, 1);
765 }
766
767
768 // Confirmation close
769 if ($action == 'close') {
770 $thirdparty_contacts = $object->getInfosTicketExternalContact(1);
771 $contacts_select = array(
772 '-2' => $langs->trans('TicketNotifyAllTiersAtClose'),
773 '-3' => $langs->trans('TicketNotNotifyTiersAtClose')
774 );
775 foreach ($thirdparty_contacts as $thirdparty_contact) {
776 $contacts_select[$thirdparty_contact['id']] = $thirdparty_contact['civility'] . ' ' . $thirdparty_contact['lastname'] . ' ' . $thirdparty_contact['firstname'];
777 }
778
779 // Default select all or no contact
780 $default = (getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? -2 : -3);
781 $formquestion = array(
782 array(
783 'name' => 'contactid',
784 'type' => 'select',
785 'label' => $langs->trans('NotifyThirdpartyOnTicketClosing'),
786 'values' => $contacts_select,
787 'default' => $default
788 ),
789 );
790
791 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", $formquestion, '', 1);
792 }
793 // Confirmation abandon
794 if ($action == 'abandon') {
795 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("AbandonTicket"), $langs->trans("ConfirmAbandonTicket"), "confirm_abandon", '', '', 1);
796 }
797 // Confirmation delete
798 if ($action == 'delete') {
799 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("Delete"), $langs->trans("ConfirmDeleteTicket"), "confirm_delete_ticket", '', '', 1);
800 }
801 // Confirm reopen
802 if ($action == 'reopen') {
803 print $form->formconfirm($url_page_current.'?track_id='.$object->track_id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenTicket'), 'confirm_reopen', '', '', 1);
804 }
805 // Confirmation status change
806 if ($action == 'set_status') {
807 $new_status = GETPOST('new_status');
808 //var_dump($url_page_current . "?track_id=" . $object->track_id);
809 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);
810 }
811
812 // project info
813 if ($projectid > 0) {
814 $projectstat = new Project($db);
815 if ($projectstat->fetch($projectid) > 0) {
816 $projectstat->fetch_thirdparty();
817
818 // To verify role of users
819 //$userAccess = $object->restrictedProjectArea($user,'read');
820 $userWrite = $projectstat->restrictedProjectArea($user, 'write');
821 //$userDelete = $object->restrictedProjectArea($user,'delete');
822 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
823
824 $head = project_prepare_head($projectstat);
825
826 print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), 0, ($projectstat->public ? 'projectpub' : 'project'));
827
828 print '<table class="border centpercent">';
829
830 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
831
832 // Ref
833 print '<tr><td width="30%">'.$langs->trans('Ref').'</td><td colspan="3">';
834 // Define a complementary filter for search of next/prev ref.
835 if (!$user->hasRight('projet', 'all', 'lire')) {
836 $objectsListId = $projectstat->getProjectsAuthorizedForUser($user, $mine, 0);
837 $projectstat->next_prev_filter = "rowid IN (".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0').")";
838 }
839 print $form->showrefnav($projectstat, 'ref', $linkback, 1, 'ref', 'ref', '');
840 print '</td></tr>';
841
842 // Label
843 print '<tr><td>'.$langs->trans("Label").'</td><td>'.$projectstat->title.'</td></tr>';
844
845 // Customer
846 print "<tr><td>".$langs->trans("ThirdParty")."</td>";
847 print '<td colspan="3">';
848 if ($projectstat->thirdparty->id > 0) {
849 print $projectstat->thirdparty->getNomUrl(1);
850 } else {
851 print '&nbsp;';
852 }
853
854 print '</td></tr>';
855
856 // Visibility
857 print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
858 if ($projectstat->public) {
859 print $langs->trans('SharedProject');
860 } else {
861 print $langs->trans('PrivateProject');
862 }
863
864 print '</td></tr>';
865
866 // Status
867 print '<tr><td>'.$langs->trans("Status").'</td><td>'.$projectstat->getLibStatut(4).'</td></tr>';
868
869 print "</table>";
870
871 print dol_get_fiche_end();
872 } else {
873 print "ErrorRecordNotFound";
874 }
875 } elseif ($socid > 0) {
876 $object->fetch_thirdparty();
877 $head = societe_prepare_head($object->thirdparty);
878
879 print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company');
880
881 dol_banner_tab($object->thirdparty, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom');
882
883 print dol_get_fiche_end();
884 }
885
886 if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) {
887 $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id);
888 } elseif ($user->socid > 0) {
889 $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid);
890 }
891
893
894 print dol_get_fiche_head($head, 'tabTicket', $langs->trans("Ticket"), -1, 'ticket');
895
896 $morehtmlref = '<div class="refidno">';
897
898 if ($user->hasRight('ticket', 'write') && !$user->socid) {
899 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editsubject&token='.newToken().'&track_id='.$object->track_id.'">'.img_edit($langs->transnoentitiesnoconv('SetTitle'), 0).'</a> ';
900 }
901 if ($action != 'editsubject') {
902 $morehtmlref .= dolPrintLabel($object->subject);
903 } else {
904 $morehtmlref .= '<form method="post" action="'.$_SERVER["PHP_SELF"].'">';
905 $morehtmlref .= '<input type="hidden" name="action" value="setsubject">';
906 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
907 $morehtmlref .= '<input type="hidden" name="id" value="20">';
908 $morehtmlref .= '<input type="text" class="minwidth300" id="subject" name="subject" value="'.$object->subject.'" autofocus="">';
909 $morehtmlref .= '<input type="submit" class="smallpaddingimp button valignmiddle" name="modify" value="'.$langs->trans("Modify").'">';
910 $morehtmlref .= '<input type="submit" class="smallpaddingimp button button-cancel vlignmiddle" name="cancel" value="'.$langs->trans("Cancel").'">';
911 $morehtmlref .= '</form>';
912 }
913
914 // Author
915 $createdbyshown = 0;
916 if ($object->fk_user_create > 0) {
917 $morehtmlref .= '<br>'.$langs->trans("CreatedBy").' : ';
918
919 $fuser = new User($db);
920 $fuser->fetch($object->fk_user_create);
921 $morehtmlref .= $fuser->getNomUrl(-1);
922 $createdbyshown++;
923 }
924
925 $createdfrompublicticket = 0;
926 $createdfromemailcollector = 0;
927 if (!empty($object->origin_email) && (empty($object->email_msgid) || preg_match('/dolibarr\-tic\d+/', $object->email_msgid))) {
928 // If ticket create from public interface - TODO Add a more robust test to know if created by public interface
929 $createdfrompublicticket = 1;
930 } elseif (!empty($object->email_msgid)) {
931 // If ticket create by emailcollector - TODO Add a more robust test to know if created by email collector (using import ky ?)
932 $createdfromemailcollector = 1;
933 }
934
935 //var_dump($object);
936 if ($createdfrompublicticket) {
937 $htmltooptip = $langs->trans("OriginEmail").': '.$object->origin_email;
938 $htmltooptip .= '<br>'.$langs->trans("IP").': '.$object->ip;
939 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
940 $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy").' : ');
941 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
942 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByPublicPortal"), $htmltooptip, 1, 'help', '', 0, 3, 'tooltip').'</small>';
943 } elseif ($createdfromemailcollector) {
944 $langs->load("mails");
945 $htmltooltip = $langs->trans("EmailMsgID").': '.$object->email_msgid;
946 $htmltooltip .= '<br>'.$langs->trans("EmailDate").': '.dol_print_date($object->email_date, 'dayhour');
947 $htmltooltip .= '<br>'.$langs->trans("MailFrom").': '.$object->origin_email;
948 $htmltooltip .= '<br>'.$langs->trans("MailReply").': '.$object->origin_replyto;
949 $htmltooltip .= '<br>'.$langs->trans("MailReferences").': '.$object->origin_references;
950 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
951 $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy").' : ');
952 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
953 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByEmailCollector"), $htmltooltip, 1, 'help', '', 0, 3, 'tooltip').'</small>';
954 }
955
956 $permissiontoedit = $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write');
957 //$permissiontoedit = 0;
958
959 // Thirdparty
960 if (isModEnabled("societe")) {
961 $morehtmlref .= '<br>';
962 $morehtmlref .= img_picto($langs->trans("ThirdParty"), 'company', 'class="pictofixedwidth"');
963 if ($action != 'editcustomer' && $permissiontoedit) {
964 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editcustomer&token='.newToken().'&track_id='.$object->track_id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty'), 0).'</a> ';
965 }
966 $morehtmlref .= $form->form_thirdparty($url_page_current.'?track_id='.$object->track_id, $object->socid, $action == 'editcustomer' ? 'editcustomer' : 'none', '', 1, 0, 0, array(), 1);
967 if (!empty($object->socid)) {
968 $morehtmlref .= ' - <a href="'.DOL_URL_ROOT.'/ticket/list.php?socid='.$object->socid.'&sortfield=t.datec&sortorder=desc">'.img_picto($langs->trans("Tickets"), 'ticket', 'class="pictofixedwidth"').' '.$langs->trans("TicketHistory").'</a>';
969 }
970 }
971
972 // Project
973 if (isModEnabled('project')) {
974 $langs->load("projects");
975 $morehtmlref .= '<br>';
976 if ($permissiontoedit) {
977 $object->fetch_project();
978 $morehtmlref .= img_picto($langs->trans("Project"), 'project'.((is_object($object->project) && $object->project->public) ? 'pub' : ''), 'class="pictofixedwidth"');
979 if ($action != 'classify') {
980 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
981 }
982 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
983 } else {
984 if (!empty($object->fk_project)) {
985 $object->fetch_project();
986 $morehtmlref .= $object->project->getNomUrl(1);
987 if ($object->project->title) {
988 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($object->project->title).'</span>';
989 }
990 }
991 }
992 }
993
994 // Contract
995 if (getDolGlobalString('TICKET_LINK_TO_CONTRACT_WITH_HARDLINK')) {
996 // Deprecated. Duplicate feature. Ticket can already be linked to contract with the generic "Link to" feature.
997 if (isModEnabled('contract')) {
998 $langs->load('contracts');
999 $morehtmlref .= '<br>';
1000 if ($permissiontoedit) {
1001 $morehtmlref .= img_picto($langs->trans("Contract"), 'contract', 'class="pictofixedwidth"');
1002 if ($action == 'edit_contrat') {
1003 $formcontract = new FormContract($db);
1004 $morehtmlref .= $formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contract, 'contratid', 0, 1, 1, 1);
1005 } else {
1006 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_contrat&token='.newToken().'&id='.$object->id.'">';
1007 $morehtmlref .= img_edit($langs->trans('SetContract'));
1008 $morehtmlref .= '</a>';
1009 }
1010 } else {
1011 if (!empty($object->fk_contract)) {
1012 $contratstatic = new Contrat($db);
1013 $contratstatic->fetch($object->fk_contract);
1014 //print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
1015 $morehtmlref .= $contratstatic->getNomUrl(0, '', 1);
1016 }
1017 }
1018 }
1019 }
1020
1021 $morehtmlref .= '</div>';
1022
1023 $linkback = '<a href="'.DOL_URL_ROOT.'/ticket/list.php?restore_lastsearch_values=1"><strong>'.$langs->trans("BackToList").'</strong></a> ';
1024
1025 dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref);
1026
1027 print '<div class="fichecenter">';
1028 print '<div class="fichehalfleft">';
1029 print '<div class="underbanner clearboth"></div>';
1030
1031 print '<table class="border tableforfield centpercent">';
1032
1033 // Track ID
1034 print '<tr><td class="titlefield">'.$langs->trans("TicketTrackId").'</td><td>';
1035 if (!empty($object->track_id)) {
1036 if (empty($object->ref)) {
1037 $object->ref = $object->id;
1038 print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'track_id');
1039 } else {
1040 print dolPrintLabel($object->track_id);
1041 }
1042 } else {
1043 print $langs->trans('None');
1044 }
1045 print '</td></tr>';
1046
1047 // Subject
1048 /*
1049 print '<tr><td>';
1050 print $form->editfieldkey("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1051 print '</td><td>';
1052 print $form->editfieldval("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1053 print '</td></tr>';
1054 */
1055
1056 // Creation date
1057 print '<tr><td>'.$langs->trans("DateCreation").'</td><td>';
1058 print dol_print_date($object->datec, 'dayhour', 'tzuser');
1059 print '<span class="opacitymedium"> - '.$langs->trans("TimeElapsedSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->datec, 60)).'</i></span>';
1060 print '</td></tr>';
1061
1062 // Origin
1063 /*
1064 if ($object->email_msgid) {
1065 $texttoshow = $langs->trans("CreatedByEmailCollector");
1066 } elseif ($object->origin_email) {
1067 $texttoshow = $langs->trans("FromPublicEmail");
1068 }
1069 if ($texttoshow) {
1070 print '<tr><td class="titlefield fieldname_email_origin">';
1071 print $langs->trans("Origin");
1072 print '</td>';
1073 print '<td class="valuefield fieldname_email_origin">';
1074 print $texttoshow;
1075 print '</td></tr>';
1076 }
1077 */
1078
1079 // Read date
1080 print '<tr><td>'.$langs->trans("TicketReadOn").'</td><td>';
1081 if (!empty($object->date_read)) {
1082 print dol_print_date($object->date_read, 'dayhour', 'tzuser');
1083 print '<span class="opacitymedium"> - '.$langs->trans("TicketTimeElapsedBeforeSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($object->date_read - $object->datec, 60)).'</i>';
1084 print ' / <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->date_read, 60)).'</i></span>';
1085 }
1086 print '</td></tr>';
1087
1088 // Close date
1089 print '<tr><td>'.$langs->trans("TicketCloseOn").'</td><td>';
1090 if (!empty($object->date_close)) {
1091 print dol_print_date($object->date_close, 'dayhour', 'tzuser');
1092 }
1093 print '</td></tr>';
1094
1095 // User assigned
1096 print '<tr><td>';
1097 print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
1098 print $langs->trans("AssignedTo");
1099 if (isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set', 'alpha') != "assign_ticket" && $user->hasRight('ticket', 'manage')) {
1100 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>';
1101 }
1102 print '</td></tr></table>';
1103 print '</td><td>';
1104 if (GETPOST('set', 'alpha') != "assign_ticket" && $object->fk_user_assign > 0) {
1105 $userstat->fetch($object->fk_user_assign);
1106 print $userstat->getNomUrl(-1);
1107 }
1108
1109 // Show user list to assignate one if status is "read"
1110 if (GETPOST('set', 'alpha') == "assign_ticket" && $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write')) {
1111 print '<form method="post" name="ticket" enctype="multipart/form-data" action="'.$url_page_current.'">';
1112 print '<input type="hidden" name="token" value="'.newToken().'">';
1113 print '<input type="hidden" name="action" value="assign_user">';
1114 print '<input type="hidden" name="track_id" value="'.$object->track_id.'">';
1115 //print '<label for="fk_user_assign">'.$langs->trans("AssignUser").'</label> ';
1116 print $form->select_dolusers(empty($object->fk_user_assign) ? $user->id : $object->fk_user_assign, 'fk_user_assign', 1);
1117 print ' <input type="submit" class="button smallpaddingimp" name="btn_assign_user" value="'.$langs->trans("Validate").'" />';
1118 print '</form>';
1119 }
1120 print '</td></tr>';
1121
1122 // Progression
1123 print '<tr><td>';
1124 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1125 print $langs->trans('Progression').'</td><td class="left">';
1126 print '</td>';
1127 if ($action != 'progression' && isset($object->status) && $object->status < $object::STATUS_CLOSED && !$user->socid) {
1128 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>';
1129 }
1130 print '</tr></table>';
1131 print '</td><td>';
1132 if ($user->hasRight('ticket', 'write') && $action == 'progression') {
1133 print '<form action="'.$url_page_current.'" method="post">';
1134 print '<input type="hidden" name="token" value="'.newToken().'">';
1135 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1136 print '<input type="hidden" name="action" value="set_progression">';
1137 print '<input type="text" class="flat width75" name="progress" value="'.$object->progress.'">';
1138 print ' <input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
1139 print '</form>';
1140 } else {
1141 print($object->progress > 0 ? $object->progress : '0').'%';
1142 }
1143 print '</td>';
1144 print '</tr>';
1145
1146 // Timing (Duration sum of linked fichinter)
1147 if (isModEnabled('intervention')) {
1148 $object->fetchObjectLinked();
1149 $num = count($object->linkedObjects);
1150 $timing = 0;
1151 $foundinter = 0;
1152 if ($num) {
1153 foreach ($object->linkedObjects as $objecttype => $objects) {
1154 if ($objecttype == "fichinter") {
1155 foreach ($objects as $fichinter) {
1156 $foundinter++;
1158 $timing += $fichinter->duration;
1159 }
1160 }
1161 }
1162 }
1163 print '<tr><td>';
1164 print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1);
1165 print '</td><td>';
1166 print $foundinter ? convertSecondToTime($timing, 'all', getDolGlobalInt('MAIN_DURATION_OF_WORKDAY')) : '';
1167 print '</td></tr>';
1168 }
1169
1170 // Other attributes
1171 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1172
1173 print '</table>';
1174
1175
1176 // End of left column and beginning of right column
1177 print '</div><div class="fichehalfright">';
1178
1179
1180 print '<form method="post" name="formticketproperties" action="'.$url_page_current.'">';
1181 print '<input type="hidden" name="token" value="'.newToken().'">';
1182 print '<input type="hidden" name="action" value="change_property">';
1183 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1184 print '<input type="hidden" name="trackid" value="'.$trackid.'">';
1185
1186 // Classification of ticket
1187 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
1188 print '<table class="border tableforfield centpercent margintable bordertopimp">';
1189 print '<tr class="liste_titre">';
1190 print '<td>';
1191 print $langs->trans('TicketProperties');
1192 print '</td>';
1193 print '<td>';
1194 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1195 print '<input type="submit" class="button smallpaddingimp" name="btn_update_ticket_prop" value="'.$langs->trans("Modify").'" />';
1196 } else {
1197 // Button to edit Properties
1198 if (isset($object->status) && ($object->status < $object::STATUS_NEED_MORE_INFO || !getDolGlobalInt('TICKET_DISALLOW_CLASSIFICATION_MODIFICATION_EVEN_IF_CLOSED')) && $user->hasRight('ticket', 'write')) {
1199 print ' <a class="editfielda" href="card.php?track_id='.$object->track_id.'&set=properties">'.img_edit($langs->trans('Modify')).'</a>';
1200 }
1201 }
1202 print '</td>';
1203 print '</tr>';
1204
1205 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1206 print '<tr>';
1207 // Type
1208 print '<td class="titlefield">';
1209 print $langs->trans('Type');
1210 print '</td><td>';
1211 $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2);
1212 print '</td>';
1213 print '</tr>';
1214 // Group
1215 print '<tr>';
1216 print '<td>';
1217 print $langs->trans('TicketCategory');
1218 print '</td><td>';
1219 $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2, 0, 0, 0, 'maxwidth500 widthcentpercentminusxx');
1220 print '</td>';
1221 print '</tr>';
1222 // Severity
1223 print '<tr>';
1224 print '<td>';
1225 print $langs->trans('TicketSeverity');
1226 print '</td><td>';
1227 $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2);
1228 print '</td>';
1229 print '</tr>';
1230 } else {
1231 // Type
1232 print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
1233 if (!empty($object->type_code)) {
1234 print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
1235 }
1236 print '</td></tr>';
1237 // Group
1238 $s = '';
1239 if (!empty($object->category_code)) {
1240 $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
1241 }
1242 print '<tr><td>'.$langs->trans("TicketCategory").'</td><td class="tdoverflowmax200" title="'.dol_escape_htmltag($s).'">';
1243 print dol_escape_htmltag($s);
1244 print '</td></tr>';
1245 // Severity
1246 print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>';
1247 if (!empty($object->severity_code)) {
1248 print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
1249 }
1250 print '</td></tr>';
1251 }
1252 print '</table>'; // End table actions
1253 print '</div>';
1254
1255 print '</form>';
1256
1257 // Tags/Categories
1258 if (isModEnabled('category')) {
1259 print '<table class="border centpercent tableforfield">';
1260 print '<tr>';
1261 print '<td class="valignmiddle titlefield">';
1262 print '<table class="nobordernopadding centpercent"><tr><td class="titlefield">';
1263 print $langs->trans("Categories");
1264 if ($action != 'categories' && !$user->socid) {
1265 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>';
1266 }
1267 print '</table>';
1268 print '</td>';
1269
1270 if ($user->hasRight('ticket', 'write') && $action == 'categories') {
1271 $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
1272 if (is_array($cate_arbo)) {
1273 // Categories
1274 print '<td colspan="3">';
1275 print '<form action="'.$url_page_current.'" method="POST">';
1276 print '<input type="hidden" name="token" value="'.newToken().'">';
1277 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1278 print '<input type="hidden" name="action" value="set_categories">';
1279
1280 $category = new Categorie($db);
1281 $cats = $category->containing($object->id, 'ticket');
1282 $arrayselected = array();
1283 foreach ($cats as $cat) {
1284 $arrayselected[] = $cat->id;
1285 }
1286
1287 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'maxwidth500 widthcentpercentminusx', 0, 0);
1288 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Save').'">';
1289 print '</form>';
1290 print "</td>";
1291 }
1292 } else {
1293 print '<td colspan="3">';
1294 print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1);
1295 print "</td></tr>";
1296 }
1297
1298 print '</table>';
1299 }
1300
1301 // View Original message
1302 $actionobject->viewTicketOriginalMessage($user, $action, $object);
1303
1304
1305 // Display navbar with links to change ticket status
1306 print '<!-- navbar with status -->';
1307 if (!$user->socid && $user->hasRight('ticket', 'write') && isset($object->status) && $object->status < $object::STATUS_CLOSED) {
1308 $actionobject->viewStatusActions($object);
1309 }
1310
1311
1312 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1313 print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png');
1314
1315 print '<div class="div-table-responsive-no-min">';
1316 print '<div class="tagtable centpercent noborder allwidth">';
1317
1318 print '<div class="tagtr liste_titre">';
1319 print '<div class="tagtd">'.$langs->trans("Source").'</div>
1320 <div class="tagtd">' . $langs->trans("Company").'</div>
1321 <div class="tagtd">' . $langs->trans("Contacts").'</div>
1322 <div class="tagtd">' . $langs->trans("ContactType").'</div>
1323 <div class="tagtd">' . $langs->trans("Phone").'</div>
1324 <div class="tagtd center">' . $langs->trans("Status").'</div>';
1325 print '</div><!-- tagtr -->';
1326
1327 // Contact list
1328 $companystatic = new Societe($db);
1329 $contactstatic = new Contact($db);
1330 $userstatic = new User($db);
1331 $var = false;
1332 foreach (array('internal', 'external') as $source) {
1333 $tmpobject = $object;
1334 $tab = $tmpobject->listeContact(-1, $source);
1335 '@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,phone_perso?:string,nom:string}> $tab';
1336 $num = is_array($tab) ? 0 : count($tab);
1337 $i = 0;
1338 foreach (array_keys($tab) as $i) {
1339 $var = !$var;
1340 print '<div class="tagtr '.($var ? 'pair' : 'impair').'">';
1341
1342 print '<div class="tagtd left">';
1343 if ($tab[$i]['source'] == 'internal') {
1344 echo $langs->trans("User");
1345 }
1346
1347 if ($tab[$i]['source'] == 'external') {
1348 echo $langs->trans("ThirdPartyContact");
1349 }
1350
1351 print '</div>';
1352 print '<div class="tagtd left">';
1353
1354 if ($tab[$i]['socid'] > 0) {
1355 $companystatic->fetch($tab[$i]['socid']);
1356 echo $companystatic->getNomUrl(-1);
1357 }
1358 if ($tab[$i]['socid'] < 0) {
1359 echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
1360 }
1361 if (!$tab[$i]['socid']) {
1362 echo '&nbsp;';
1363 }
1364 print '</div>';
1365
1366 print '<div class="tagtd">';
1367 if ($tab[$i]['source'] == 'internal') {
1368 if ($userstatic->fetch($tab[$i]['id'])) {
1369 print $userstatic->getNomUrl(-1);
1370 }
1371 }
1372 if ($tab[$i]['source'] == 'external') {
1373 if ($contactstatic->fetch($tab[$i]['id'])) {
1374 print $contactstatic->getNomUrl(-1);
1375 }
1376 }
1377 print ' </div>
1378 <div class="tagtd">' . $tab[$i]['libelle'].'</div>';
1379
1380 print '<div class="tagtd">';
1381
1382 print dol_print_phone($tab[$i]['phone'], '', 0, 0, 'AC_TEL').'<br>';
1383
1384 if (!empty($tab[$i]['phone_perso'])) {
1385 //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' ';
1386 print '<br>'.dol_print_phone($tab[$i]['phone_perso'], '', 0, 0, 'AC_TEL').'<br>';
1387 }
1388 if (!empty($tab[$i]['phone_mobile'])) {
1389 //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' ';
1390 print dol_print_phone($tab[$i]['phone_mobile'], '', 0, 0, 'AC_TEL').'<br>';
1391 }
1392 print '</div>';
1393
1394 print '<div class="tagtd center">';
1395 if ($object->status >= 0) {
1396 echo '<a href="contact.php?track_id='.$object->track_id.'&amp;action=swapstatut&amp;ligne='.$tab[$i]['rowid'].'">';
1397 }
1398
1399 if ($tab[$i]['source'] == 'internal') {
1400 $userstatic->id = $tab[$i]['id'];
1401 $userstatic->lastname = $tab[$i]['lastname'];
1402 $userstatic->firstname = $tab[$i]['firstname'];
1403 echo $userstatic->LibStatut($tab[$i]['statuscontact'], 3);
1404 }
1405 if ($tab[$i]['source'] == 'external') {
1406 $contactstatic->id = $tab[$i]['id'];
1407 $contactstatic->lastname = $tab[$i]['lastname'];
1408 $contactstatic->firstname = $tab[$i]['firstname'];
1409 echo $contactstatic->LibStatut($tab[$i]['statuscontact'], 3);
1410 }
1411 if ($object->status >= 0) {
1412 echo '</a>';
1413 }
1414
1415 print '</div>';
1416
1417 print '</div><!-- tagtr -->';
1418
1419 $i++;
1420 }
1421 }
1422
1423 print '</div><!-- contact list -->';
1424 print '</div>';
1425 }
1426
1427 print '</div></div>';
1428 print '<div class="clearboth"></div>';
1429
1430 print dol_get_fiche_end();
1431
1432
1433 // Buttons for actions
1434 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') {
1435 print '<div class="tabsAction">'."\n";
1436 $parameters = array();
1437 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1438 if ($reshook < 0) {
1439 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1440 }
1441
1442 if (empty($reshook)) {
1443 // Email
1444 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1445 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', '');
1446 }
1447
1448 // Show link to add a message (if read and not closed)
1449 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1450 print dolGetButtonAction('', $langs->trans('TicketAddPrivateMessage'), 'default', $_SERVER["PHP_SELF"].'?action=presend_addmessage&mode=init&token='.newToken().'&track_id='.$object->track_id.'#formmailbeforetitle', '');
1451 }
1452
1453 // Link to create an intervention
1454 // socid is needed otherwise fichinter ask it and forgot origin after form submit :\
1455 if (!$object->fk_soc && $user->hasRight("ficheinter", "creer")) {
1456 print dolGetButtonAction($langs->trans('UnableToCreateInterIfNoSocid'), $langs->trans('TicketAddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1457 }
1458 if ($object->fk_soc > 0 && isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ficheinter', 'creer')) {
1459 print dolGetButtonAction('', $langs->trans('TicketAddIntervention'), 'default', DOL_URL_ROOT.'/fichinter/card.php?action=create&token='.newToken().'&socid='. $object->fk_soc.'&origin=ticket_ticket&originid='. $object->id, '');
1460 }
1461
1462 // Close ticket if status is read
1463 if (isset($object->status) && $object->status >= 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1464 print dolGetButtonAction('', $langs->trans('CloseTicket'), 'default', $_SERVER["PHP_SELF"].'?action=close&token='.newToken().'&track_id='.$object->track_id, '');
1465 }
1466
1467 // Abandon ticket if status is read
1468 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1469 print dolGetButtonAction('', $langs->trans('AbandonTicket'), 'default', $_SERVER["PHP_SELF"].'?action=abandon&token='.newToken().'&track_id='.$object->track_id, '');
1470 }
1471
1472 // Re-open ticket
1473 if (!$user->socid && (isset($object->status) && ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED)) && !$user->socid) {
1474 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&track_id='.$object->track_id, '');
1475 }
1476
1477 // Edit ticket
1478 if ($permissiontoedit) {
1479 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoedit);
1480 }
1481
1482 // Delete ticket
1483 if ($user->hasRight('ticket', 'delete') && !$user->socid) {
1484 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&track_id='.$object->track_id, '');
1485 }
1486 }
1487 print '</div>'."\n";
1488 }
1489
1490 // Select mail models is same action as presend
1491 if (GETPOST('modelselected')) {
1492 $action = 'presend';
1493 }
1494 // Set $action to correct value for the case we used presend action to add a message
1495 if (GETPOSTISSET('actionbis') && $action == 'presend') {
1496 $action = 'presend_addmessage';
1497 }
1498
1499 // add a message
1500 if ($action == 'presend' || $action == 'presend_addmessage') {
1501 if ($object->fk_soc > 0) {
1502 $object->fetch_thirdparty();
1503 }
1504
1505 $outputlangs = $langs;
1506 $newlang = '';
1507 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1508 $newlang = GETPOST('lang_id', 'aZ09');
1509 } elseif (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && is_object($object->thirdparty)) {
1510 $newlang = $object->thirdparty->default_lang;
1511 }
1512 if (!empty($newlang)) {
1513 $outputlangs = new Translate("", $conf);
1514 $outputlangs->setDefaultLang($newlang);
1515 }
1516
1517 $arrayoffamiliestoexclude = array('objectamount');
1518
1519 $action = 'add_message'; // action to use to post the message
1520 $modelmail = 'ticket_send';
1521
1522 // Substitution array
1523 $morehtmlright = '';
1524 $help = "";
1525 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object);
1526 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1527 $morehtmlright .= $form->textwithpicto('<span class="opacitymedium">'.$langs->trans("TicketMessageSubstitutionReplacedByGenericValues").'</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution');
1528
1529 print '<div>';
1530
1531 print '<div id="formmailbeforetitle" name="formmailbeforetitle"></div>';
1532
1533 print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket');
1534
1535 print '<hr>';
1536
1537 $formticket = new FormTicket($db);
1538
1539 $formticket->action = $action;
1540 $formticket->track_id = $object->track_id;
1541 $formticket->ref = $object->ref;
1542 $formticket->id = $object->id;
1543 $formticket->trackid = 'tic'.$object->id;
1544
1545 $formticket->withfile = 2;
1546 $formticket->withcancel = 1;
1547 $formticket->param = array('fk_user_create' => $user->id);
1548 $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang);
1549
1550 // Table of additional post parameters
1551 $formticket->param['models'] = $modelmail;
1552 $formticket->param['models_id'] = GETPOSTINT('modelmailselected');
1553 //$formticket->param['socid']=$object->fk_soc;
1554 $formticket->param['returnurl'] = $_SERVER["PHP_SELF"].'?track_id='.$object->track_id;
1555
1556 $formticket->withsubstit = 1;
1557 $formticket->substit = $substitutionarray;
1558 $formticket->backtopage = $backtopage;
1559
1560 $formticket->showMessageForm('100%');
1561 print '</div>';
1562 }
1563
1564 // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
1565 if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) {
1566 $param = '&id='.$object->id;
1567 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1568 $param .= '&contextpage='.$contextpage;
1569 }
1570 if ($limit > 0 && $limit != $conf->liste_limit) {
1571 $param .= '&limit='.$limit;
1572 }
1573 if ($actioncode) {
1574 $param .= '&actioncode='.urlencode($actioncode);
1575 }
1576 if ($search_agenda_label) {
1577 $param .= '&search_agenda_label='.urlencode($search_agenda_label);
1578 }
1579
1580 $morehtmlright = '';
1581
1582 $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id;
1583 $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 1);
1584
1585 // Show link to add a message (if read and not closed)
1586 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1587 $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init';
1588 $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fa fa-comment-dots', $url, 'add-new-ticket-title-button', (int) $btnstatus);
1589
1590 // Show link to add event (if read and not closed)
1591 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1592 $url = dol_buildpath('/comm/action/card.php', 1).'?action=create&datep='.date('YmdHi').'&origin=ticket&originid='.$object->id.'&projectid='.$object->fk_project.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?track_id='.$object->track_id);
1593 $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', (int) $btnstatus);
1594
1595 print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
1596
1597 // List of all actions
1598 $filters = array();
1599 $filters['search_agenda_label'] = $search_agenda_label;
1600 $filters['search_rowid'] = $search_rowid;
1601
1602 show_actions_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder);
1603 }
1604
1605 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') {
1606 print '<div class="fichecenter"><div class="fichehalfleft">';
1607 print '<a name="builddoc"></a>'; // ancre
1608 /*
1609 * Generated documents
1610 */
1611 $filename = dol_sanitizeFileName($object->ref);
1612 $filedir = $upload_dir."/".dol_sanitizeFileName($object->ref);
1613 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1614 $genallowed = $permissiontoadd;
1615 $delallowed = $permissiontodelete;
1616 $codelang = '';
1617 if ($object->fk_soc > 0) {
1618 $object->fetch_thirdparty();
1619 $codelang = $object->thirdparty->default_lang;
1620 }
1621
1622 print $formfile->showdocuments('ticket', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $codelang);
1623
1624 // Show links to link elements
1625 $linktoelem = $form->showLinkToObjectBlock($object, null, array('ticket'));
1626 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1627
1628 // Show direct link to public interface
1629 print '<br><!-- Link to public interface -->'."\n";
1630 print showDirectPublicLink($object).'<br>';
1631 print '</div>';
1632
1633 if (!getDolGlobalString('MAIN_HIDE_MESSAGES_ON_CARD')) {
1634 print '<div class="fichehalfright">';
1635
1636 $MAXEVENT = 10;
1637
1638 $morehtmlcenter = '<div class="nowraponall">';
1639 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/ticket/messaging.php?id='.$object->id);
1640 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id);
1641 $morehtmlcenter .= '</div>';
1642
1643 // List of actions on element
1644 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1645 $formactions = new FormActions($db);
1646 $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
1647
1648 print '</div>';
1649 }
1650
1651 print '</div>';
1652 }
1653 }
1654}
1655
1656// End of page
1657llxFooter();
1658$db->close();
$id
Definition account.php:39
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:70
Class Actions of the module ticket.
Class to manage categories.
Class to manage contact/addresses.
Class to manage standard extra fields.
Class to manage building of HTML components.
Class to manage generation of HTML components for contract module.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage building of HTML components.
static checkRequiredFields(array $fields, int &$errors)
Check required fields.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
societe_prepare_head(Societe $object)
Return array of tabs to used on pages for third parties cards.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:241
llxFooter()
Footer empty.
Definition document.php:107
show_actions_messaging($conf, $langs, $db, $filterobj, $objcon=null, $noprint=0, $actioncode='', $donetodo='done', $filters=array(), $sortfield='a.datep, a.id', $sortorder='DESC')
Show html area with actions in messaging format.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='paddingright')
Format phone numbers according to country.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
roundUpToNextMultiple($n, $x=5)
Round to next multiple.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dolPrintLabel($s)
Return a string label (so on 1 line only and that should not contains any HTML) ready to be output on...
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Class to generate the form for creating a new ticket.
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
showDirectPublicLink($object)
Return string with full Url.
ticket_prepare_head($object)
Build tabs for a Ticket object.