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