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';
193 if ($action == 'add') $object->track_id = null;
194 $error = 0;
195
196 $fieldsToCheck = [
197 'ref' => ['check' => 'alpha', 'langs' => 'Ref'],
198 'type_code' => ['check' => 'alpha', 'langs' => 'TicketTypeRequest'],
199 'category_code' => ['check' => 'alpha', 'langs' => 'TicketCategory'],
200 'severity_code' => ['check' => 'alpha', 'langs' => 'TicketSeverity'],
201 'subject' => ['check' => 'alphanohtml', 'langs' => 'Subject'],
202 'message' => ['check' => 'restricthtml', 'langs' => 'Message']
203 ];
204
205 FormTicket::checkRequiredFields($fieldsToCheck, $error);
206
207 if (!empty($error)) {
208 $action = $ifErrorAction;
209 }
210
211 $ret = $extrafields->setOptionalsFromPost(null, $object);
212 if ($ret < 0) {
213 $error++;
214 }
215 $getRef = GETPOST('ref', 'alpha');
216
217 if (!empty($getRef)) {
218 $isExistingRef = $object->checkExistingRef($action, $getRef);
219 } else {
220 $isExistingRef = true;
221 }
222
223 $style = '';
224
225 if ($isExistingRef) {
226 if ($action == 'update') {
227 $error++;
228 $action = 'edit';
229 $style = 'errors';
230 } elseif ($action == 'add') {
231 $object->ref = $object->getDefaultRef();
232 $object->track_id = null;
233 $style = 'warnings';
234 }
235 if (!empty($getRef)) {
236 setEventMessage($langs->trans('TicketRefAlreadyUsed', $getRef, $object->ref), $style);
237 }
238 }
239 if (!$error) {
240 $db->begin();
241
242 $object->type_code = GETPOST('type_code', 'alpha');
243 $object->category_code = GETPOST('category_code', 'alpha');
244 $object->severity_code = GETPOST('severity_code', 'alpha');
245 $object->subject = GETPOST('subject', 'alpha');
246 $object->message = GETPOST('message', 'restricthtml');
247 $object->fk_soc = GETPOSTINT('socid');
248 $fk_user_assign = GETPOSTINT('fk_user_assign');
249 $object->fk_project = GETPOSTINT('projectid');
250 $object->fk_contract = GETPOSTINT('fk_contract');
251
252 if ($fk_user_assign > 0) {
253 $object->fk_user_assign = $fk_user_assign;
254 $object->status = $object::STATUS_ASSIGNED;
255 }
256
257 if ($action == 'add') {
258 $object->type_code = GETPOST("type_code", 'alpha');
259 $object->type_label = $langs->trans($langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'));
260 $object->category_label = $langs->trans($langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'));
261 $object->severity_label = $langs->trans($langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'));
262 $object->fk_user_create = $user->id;
263 $object->email_from = $user->email;
264 $object->origin_email = null;
265 $notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
266 $object->notify_tiers_at_create = empty($notifyTiers) ? 0 : 1;
267 $object->context['contact_id'] = GETPOSTINT('contact_id');
268 $id = $object->create($user);
269 } else {
270 $id = $object->update($user);
271 }
272
273 if ($id <= 0) {
274 $error++;
275 setEventMessages($object->error, $object->errors, 'errors');
276 $action = $ifErrorAction;
277 }
278
279 if (!$error) {
280 // Category association
281 $categories = GETPOST('categories', 'array');
282 $object->setCategories($categories);
283 }
284
285 if ($action == 'add') {
286 if (!$error) {
287 // Add contact
288 $contactid = GETPOSTINT('contactid');
289 $type_contact = GETPOST("type", 'alpha');
290
291 if ($contactid > 0 && $type_contact) {
292 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
293 $result = $object->add_contact($contactid, $typeid, 'external');
294 }
295
296 // Link ticket to project
297 if (GETPOST('origin', 'alpha') == 'projet') {
298 $projectid = GETPOSTINT('originid');
299 } else {
300 $projectid = GETPOSTINT('projectid');
301 }
302
303 if ($projectid > 0) {
304 $object->setProject($projectid);
305 }
306
307 // Auto mark as read if created from backend
308 if (getDolGlobalString('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND') && $user->hasRight('ticket', 'write')) {
309 if (!$object->markAsRead($user) > 0) {
310 setEventMessages($object->error, $object->errors, 'errors');
311 }
312 }
313
314 // Auto assign user
315 if (getDolGlobalString('TICKET_AUTO_ASSIGN_USER_CREATE')) {
316 $result = $object->assignUser($user, $user->id, 1);
317 $object->add_contact($user->id, "SUPPORTTEC", 'internal');
318 }
319 }
320
321 if (!$error) {
322 // File transfer
323 $object->copyFilesForTicket(''); // trackid is forced to '' because files were uploaded when no id for ticket exists yet and trackid was ''
324 }
325 }
326 if (!$error) {
327 $db->commit();
328
329 if (!empty($backtopage)) {
330 if (empty($id)) {
331 $url = $backtopage;
332 } else {
333 $url = 'card.php?track_id=' . urlencode($object->track_id);
334 }
335 } else {
336 $url = 'card.php?track_id=' . urlencode($object->track_id);
337 }
338
339 header("Location: " . $url);
340 exit;
341 } else {
342 $db->rollback();
343 setEventMessages($object->error, $object->errors, 'errors');
344 }
345 } else $action = $ifErrorAction;
346 }
347
348 // Mark as Read
349 if ($action == "set_read" && $permissiontoadd) {
350 $object->fetch('', '', GETPOST("track_id", 'alpha'));
351
352 if ($object->markAsRead($user) > 0) {
353 setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs');
354
355 header("Location: card.php?track_id=" . $object->track_id);
356 exit;
357 } else {
358 setEventMessages($object->error, $object->errors, 'errors');
359 }
360 $action = 'view';
361 }
362
363 // Assign to someone
364 if ($action == "assign_user" && GETPOST('btn_assign_user', 'alpha') && $permissiontoadd) {
365 $object->fetch('', '', GETPOST("track_id", 'alpha'));
366 $useroriginassign = $object->fk_user_assign;
367 $usertoassign = GETPOSTINT('fk_user_assign');
368
369 /*if (! ($usertoassign > 0)) {
370 $error++;
371 array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("AssignedTo")));
372 $action = 'view';
373 }*/
374
375 if (!$error) {
376 $ret = $object->assignUser($user, $usertoassign);
377 if ($ret < 0) {
378 $error++;
379 }
380 }
381
382 if (!$error) { // Update list of contacts
383 // If a user has already been assigned, we delete him from the contacts.
384 if ($useroriginassign > 0) {
385 $internal_contacts = $object->listeContact(-1, 'internal', 0, 'SUPPORTTEC');
386 foreach ($internal_contacts as $key => $contact) {
387 if ($contact['id'] !== $usertoassign) {
388 $result = $object->delete_contact($contact['rowid']);
389 if ($result < 0) {
390 $error++;
391 setEventMessages($object->error, $object->errors, 'errors');
392 }
393 }
394 }
395 }
396
397 if ($usertoassign > 0 && $usertoassign !== $useroriginassign) {
398 $result = $object->add_contact($usertoassign, "SUPPORTTEC", 'internal', $notrigger = 0);
399 if ($result < 0) {
400 $error++;
401 setEventMessages($object->error, $object->errors, 'errors');
402 }
403 }
404 }
405
406 if (!$error) {
407 // Log action in ticket logs table
408 $object->fetch_user($usertoassign);
409
410 setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs');
411 header("Location: card.php?track_id=" . $object->track_id);
412 exit;
413 } else {
414 array_push($object->errors, $object->error);
415 }
416 $action = 'view';
417 }
418
419 // Action to add a message (private or not, with email or not).
420 // This may also send an email (concatenated with email_intro and email footer if checkbox was selected)
421 if ($action == 'add_message' && GETPOSTISSET('btn_add_message') && $permissiontoread) {
422 $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0), 0);
423
424 if ($ret > 0) {
425 if (!empty($backtopage)) {
426 $url = $backtopage;
427 } else {
428 $url = 'card.php?track_id=' . urlencode($object->track_id);
429 }
430
431 header("Location: " . $url);
432 exit;
433 } else {
434 setEventMessages($object->error, $object->errors, 'errors');
435 $action = 'presend';
436 }
437 }
438
439 if (($action == "confirm_close" || $action == "confirm_abandon") && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
440 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
441
442 if ($object->close($user, ($action == "confirm_abandon" ? 1 : 0))) {
443 setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs');
444
445 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
446 header("Location: " . $url);
447 exit;
448 } else {
449 $action = '';
450 setEventMessages($object->error, $object->errors, 'errors');
451 }
452 }
453
454 if ($action == "confirm_public_close" && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
455 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
456 if ($_SESSION['email_customer'] == $object->origin_email || $_SESSION['email_customer'] == $object->thirdparty->email) {
457 $object->context['contact_id'] = GETPOSTINT('contact_id');
458
459 $object->close($user);
460
461 setEventMessages('<div class="confirm">' . $langs->trans('TicketMarkedAsClosed') . '</div>', null, 'mesgs');
462
463 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
464 header("Location: " . $url);
465 exit;
466 } else {
467 setEventMessages($object->error, $object->errors, 'errors');
468 $action = '';
469 }
470 }
471
472 if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $permissiontodelete) {
473 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
474 if ($object->delete($user) > 0) {
475 setEventMessages('<div class="confirm">' . $langs->trans('TicketDeletedSuccess') . '</div>', null, 'mesgs');
476 header("Location: " . DOL_URL_ROOT . "/ticket/list.php");
477 exit;
478 } else {
479 $langs->load("errors");
480 $mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
481 $action = '';
482 }
483 }
484 }
485
486 // Set parent company
487 if ($action == 'set_thirdparty' && $user->hasRight('ticket', 'write')) {
488 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
489 $result = $object->setCustomer(GETPOSTINT('editcustomer'));
490 $url = $_SERVER["PHP_SELF"] . '?track_id=' . GETPOST('track_id', 'alpha');
491 header("Location: " . $url);
492 exit();
493 }
494 }
495
496 // Set progress status
497 if ($action == 'set_progression' && $user->hasRight('ticket', 'write')) {
498 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
499 $result = $object->setProgression(GETPOST('progress', 'alpha'));
500
501 $url = 'card.php?track_id=' . $object->track_id;
502 header("Location: " . $url);
503 exit();
504 }
505 }
506
507 // Set categories
508 if ($action == 'set_categories' && $user->hasRight('ticket', 'write')) {
509 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
510 $result = $object->setCategories(GETPOST('categories', 'array'));
511
512 $url = 'card.php?track_id=' . $object->track_id;
513 header("Location: " . $url);
514 exit();
515 }
516 }
517
518 // Set Subject
519 if ($action == 'setsubject' && $user->hasRight('ticket', 'write')) {
520 if ($object->fetch(GETPOSTINT('id'))) {
521 if ($action == 'setsubject') {
522 $object->subject = GETPOST('subject', 'alphanohtml');
523 }
524
525 if ($action == 'setsubject' && empty($object->subject)) {
526 $error++;
527 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors');
528 }
529
530 if (!$error) {
531 if (!$object->update($user) >= 0) {
532 $error++;
533 setEventMessages($object->error, $object->errors, 'errors');
534 }
535 }
536
537 header("Location: " . $_SERVER['PHP_SELF'] . "?track_id=" . $object->track_id);
538 exit;
539 }
540 }
541
542 if ($action == 'confirm_reopen' && $user->hasRight('ticket', 'manage') && !GETPOST('cancel')) {
543 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
544 // prevent browser refresh from reopening ticket several times
545 if ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED) {
546 if ($object->fk_user_assign != null) {
547 $res = $object->setStatut(Ticket::STATUS_ASSIGNED);
548 } else {
549 $res = $object->setStatut(Ticket::STATUS_NOT_READ);
550 }
551 if ($res) {
552 $url = 'card.php?track_id=' . $object->track_id;
553 header("Location: " . $url);
554 exit();
555 } else {
556 $error++;
557 setEventMessages($object->error, $object->errors, 'errors');
558 }
559 }
560 }
561 } elseif ($action == 'classin' && $permissiontoadd) {
562 // Categorisation dans projet
563 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
564 $object->setProject($projectid);
565 $url = 'card.php?track_id=' . $object->track_id;
566 header("Location: " . $url);
567 exit();
568 }
569 } elseif ($action == 'setcontract' && $permissiontoadd) {
570 // Categorisation dans contrat
571 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
572 $object->setContract(GETPOSTINT('contractid'));
573 $url = 'card.php?track_id=' . $object->track_id;
574 header("Location: " . $url);
575 exit();
576 }
577 } elseif ($action == "set_message" && $user->hasRight('ticket', 'manage')) {
578 if (!GETPOST('cancel')) {
579 $object->fetch('', '', GETPOST('track_id', 'alpha'));
580 //$oldvalue_message = $object->message;
581 $fieldtomodify = GETPOST('message_initial', 'restricthtml');
582
583 $object->message = $fieldtomodify;
584 $ret = $object->update($user);
585 if ($ret > 0) {
586 //include_once DOL_DOCUMENT_ROOT.'/core/class/utils_diff.class.php';
587 // output the result of comparing two files as plain text
588 //$log_action .= Diff::toString(Diff::compare(strip_tags($oldvalue_message), strip_tags($object->message)));
589
590 setEventMessages($langs->trans('TicketMessageSuccesfullyUpdated'), null, 'mesgs');
591 } else {
592 $error++;
593 setEventMessages($object->error, $object->errors, 'errors');
594 }
595 }
596
597 $action = 'view';
598 } elseif ($action == 'confirm_set_status' && $permissiontoadd && !GETPOST('cancel')) {
599 // Reopen ticket
600 if ($object->fetch(GETPOSTINT('id'), GETPOST('track_id', 'alpha')) >= 0) {
601 $new_status = GETPOSTINT('new_status');
602 //$old_status = $object->status;
603 $res = $object->setStatut($new_status);
604 if ($res) {
605 $url = 'card.php?track_id=' . $object->track_id;
606 header("Location: " . $url);
607 exit();
608 } else {
609 $error++;
610 setEventMessages($object->error, $object->errors, 'errors');
611 }
612 }
613 }
614
615 // Action to update an extrafield
616 if ($action == "update_extras" && $permissiontoadd) {
617 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
618
619 $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
620 if ($ret < 0) {
621 $error++;
622 }
623
624 if (!$error) {
625 $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user);
626 if ($result < 0) {
627 $error++;
628 }
629 }
630
631 if ($error) {
632 setEventMessages($object->error, $object->errors, 'errors');
633 $action = 'edit_extras';
634 } else {
635 setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
636 $action = 'view';
637 }
638 }
639
640 if ($action == "change_property" && GETPOST('btn_update_ticket_prop', 'alpha') && $permissiontoadd) {
641 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
642
643 $object->type_code = GETPOST('update_value_type', 'aZ09');
644 $object->severity_code = GETPOST('update_value_severity', 'aZ09');
645 $object->category_code = GETPOST('update_value_category', 'aZ09');
646
647 $ret = $object->update($user);
648 if ($ret > 0) {
649 setEventMessages($langs->trans('TicketUpdated'), null, 'mesgs');
650 } else {
651 $error++;
652 setEventMessages($object->error, $object->errors, 'errors');
653 }
654 $action = 'view';
655 }
656
657
658 $permissiondellink = $user->hasRight('ticket', 'write');
659 include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
660
661 // Actions to build doc
662 include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
663
664 // Actions to send emails
665 $triggersendname = 'TICKET_SENTBYMAIL';
666 $paramname = 'id';
667 $autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add
668 $trackid = 'tic' . $object->id;
669 include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
670
671 // Set $action to correct value for the case we used presend action to add a message
672 if (GETPOSTISSET('actionbis') && $action == 'presend') {
673 $action = 'presend_addmessage';
674 }
675}
676
677
678/*
679 * View
680 */
681
682$userstat = new User($db);
683$form = new Form($db);
684$formfile = new FormFile($db);
685$formticket = new FormTicket($db);
686if (isModEnabled('project')) {
687 $formproject = new FormProjets($db);
688}
689
690$help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket';
691
692$title = $actionobject->getTitle($action);
693
694llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-ticket page-card');
695
696if ($action == 'create' || $action == 'presend') {
697 if (empty($permissiontoadd)) {
698 accessforbidden('NotEnoughPermissions', 0, 1);
699 }
700
701 $formticket = new FormTicket($db);
702
703 print load_fiche_titre($langs->trans('NewTicket'), '', 'ticket');
704
705 $formticket->trackid = ''; // TODO Use a unique key 'tic' to avoid conflict in upload file feature
706 $formticket->withfromsocid = $socid ? $socid : $user->socid;
707 $formticket->withfromcontactid = $contactid ? $contactid : '';
708 $formticket->withtitletopic = 1;
709 $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
710 $formticket->withusercreate = 0;
711 $formticket->withref = 1;
712 $formticket->fk_user_create = $user->id;
713 $formticket->withfile = 2;
714 $formticket->withextrafields = 1;
715 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
716
717 $formticket->withcancel = 1;
718
719 $formticket->showForm(1, 'create', 0, null, $action, $object);
720
721 print dol_get_fiche_end();
722} elseif ($action == 'edit' && $object->status < Ticket::STATUS_CLOSED) {
723 if (empty($permissiontoadd)) {
724 accessforbidden('NotEnoughPermissions', 0, 1);
725 }
726
727 $formticket = new FormTicket($db);
728
730
731 print dol_get_fiche_head($head, 'tabTicket', $langs->trans('Ticket'), -1, 'ticket');
732
733 $formticket->trackid = $object->track_id; // TODO Use a unique key 'tic' to avoid conflict in upload file feature
734 $formticket->withfromsocid = $object->socid;
735 $formticket->withtitletopic = 1;
736 // $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
737 $formticket->withnotifytiersatcreate = 0;
738 $formticket->withusercreate = 0;
739 $formticket->withref = 1;
740 $formticket->fk_user_create = $user->id;
741 $formticket->withfile = 0;
742 $formticket->action = 'update';
743 $formticket->withextrafields = 1;
744 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
745
746 $formticket->withcancel = 1;
747
748 $formticket->showForm(0, 'edit', 0, null, $action, $object);
749
750 print dol_get_fiche_end();
751} 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'])) {
752 if (!empty($res) && $res > 0) {
753 // or for unauthorized internals users
754 if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$user->hasRight('ticket', 'manage')) {
755 accessforbidden('', 0, 1);
756 }
757
758
759 // Confirmation close
760 if ($action == 'close') {
761 $thirdparty_contacts = $object->getInfosTicketExternalContact(1);
762 $contacts_select = array(
763 '-2' => $langs->trans('TicketNotifyAllTiersAtClose'),
764 '-3' => $langs->trans('TicketNotNotifyTiersAtClose')
765 );
766 foreach ($thirdparty_contacts as $thirdparty_contact) {
767 $contacts_select[$thirdparty_contact['id']] = $thirdparty_contact['civility'] . ' ' . $thirdparty_contact['lastname'] . ' ' . $thirdparty_contact['firstname'];
768 }
769
770 // Default select all or no contact
771 $default = (getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? -2 : -3);
772 $formquestion = array(
773 array(
774 'name' => 'contactid',
775 'type' => 'select',
776 'label' => $langs->trans('NotifyThirdpartyOnTicketClosing'),
777 'values' => $contacts_select,
778 'default' => $default
779 ),
780 );
781
782 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", $formquestion, '', 1);
783 }
784 // Confirmation abandon
785 if ($action == 'abandon') {
786 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("AbandonTicket"), $langs->trans("ConfirmAbandonTicket"), "confirm_abandon", '', '', 1);
787 }
788 // Confirmation delete
789 if ($action == 'delete') {
790 print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("Delete"), $langs->trans("ConfirmDeleteTicket"), "confirm_delete_ticket", '', '', 1);
791 }
792 // Confirm reopen
793 if ($action == 'reopen') {
794 print $form->formconfirm($url_page_current.'?track_id='.$object->track_id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenTicket'), 'confirm_reopen', '', '', 1);
795 }
796 // Confirmation status change
797 if ($action == 'set_status') {
798 $new_status = GETPOST('new_status');
799 //var_dump($url_page_current . "?track_id=" . $object->track_id);
800 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);
801 }
802
803 // project info
804 if ($projectid > 0) {
805 $projectstat = new Project($db);
806 if ($projectstat->fetch($projectid) > 0) {
807 $projectstat->fetch_thirdparty();
808
809 // To verify role of users
810 //$userAccess = $object->restrictedProjectArea($user,'read');
811 $userWrite = $projectstat->restrictedProjectArea($user, 'write');
812 //$userDelete = $object->restrictedProjectArea($user,'delete');
813 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
814
815 $head = project_prepare_head($projectstat);
816
817 print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), 0, ($projectstat->public ? 'projectpub' : 'project'));
818
819 print '<table class="border centpercent">';
820
821 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
822
823 // Ref
824 print '<tr><td width="30%">'.$langs->trans('Ref').'</td><td colspan="3">';
825 // Define a complementary filter for search of next/prev ref.
826 if (!$user->hasRight('projet', 'all', 'lire')) {
827 $objectsListId = $projectstat->getProjectsAuthorizedForUser($user, $mine, 0);
828 $projectstat->next_prev_filter = "rowid IN (".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0').")";
829 }
830 print $form->showrefnav($projectstat, 'ref', $linkback, 1, 'ref', 'ref', '');
831 print '</td></tr>';
832
833 // Label
834 print '<tr><td>'.$langs->trans("Label").'</td><td>'.$projectstat->title.'</td></tr>';
835
836 // Customer
837 print "<tr><td>".$langs->trans("ThirdParty")."</td>";
838 print '<td colspan="3">';
839 if ($projectstat->thirdparty->id > 0) {
840 print $projectstat->thirdparty->getNomUrl(1);
841 } else {
842 print '&nbsp;';
843 }
844
845 print '</td></tr>';
846
847 // Visibility
848 print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
849 if ($projectstat->public) {
850 print $langs->trans('SharedProject');
851 } else {
852 print $langs->trans('PrivateProject');
853 }
854
855 print '</td></tr>';
856
857 // Status
858 print '<tr><td>'.$langs->trans("Status").'</td><td>'.$projectstat->getLibStatut(4).'</td></tr>';
859
860 print "</table>";
861
862 print dol_get_fiche_end();
863 } else {
864 print "ErrorRecordNotFound";
865 }
866 } elseif ($socid > 0) {
867 $object->fetch_thirdparty();
868 $head = societe_prepare_head($object->thirdparty);
869
870 print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company');
871
872 dol_banner_tab($object->thirdparty, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom');
873
874 print dol_get_fiche_end();
875 }
876
877 if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) {
878 $object->next_prev_filter = "te.fk_user_assign = ".((int) $user->id);
879 } elseif ($user->socid > 0) {
880 $object->next_prev_filter = "te.fk_soc = ".((int) $user->socid);
881 }
882
884
885 print dol_get_fiche_head($head, 'tabTicket', $langs->trans("Ticket"), -1, 'ticket');
886
887 $morehtmlref = '<div class="refidno">';
888 $morehtmlref .= $object->subject;
889 // Author
890 $createdbyshown = 0;
891 if ($object->fk_user_create > 0) {
892 $morehtmlref .= '<br>'.$langs->trans("CreatedBy").' : ';
893
894 $fuser = new User($db);
895 $fuser->fetch($object->fk_user_create);
896 $morehtmlref .= $fuser->getNomUrl(-1);
897 $createdbyshown++;
898 }
899
900 //var_dump($object);
901 if (!empty($object->origin_email)) { // If ticket create from public interface - TODO Add a more robust test to know if created by pubic interface
902 $htmltooptip = $langs->trans("OriginEmail").': '.$object->origin_email;
903 $htmltooptip .= '<br>'.$langs->trans("IP").': '.$object->ip;
904 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
905 $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy").' : ');
906 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
907 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByPublicPortal"), $htmltooptip, 1, 'help', '', 0, 3, 'tooltip').'</small>';
908 } elseif (!empty($object->email_msgid)) { // If ticket create by emailcollector - TODO Add a more robust test to know if created by email collector (using import ky ?)
909 $langs->load("mails");
910 $htmltooltip = $langs->trans("EmailMsgID").': '.$object->email_msgid;
911 $htmltooltip .= '<br>'.$langs->trans("EmailDate").': '.dol_print_date($object->email_date, 'dayhour');
912 $htmltooltip .= '<br>'.$langs->trans("MailFrom").': '.$object->email_from;
913 $htmltooltip .= '<br>'.$langs->trans("MailReply").': '.$object->origin_replyto;
914 $htmltooltip .= '<br>'.$langs->trans("MailReferences").': '.$object->origin_references;
915 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
916 $morehtmlref .= ($createdbyshown ? '' : $langs->trans("CreatedBy").' : ');
917 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
918 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByEmailCollector"), $htmltooltip, 1, 'help', '', 0, 3, 'tooltip').'</small>';
919 }
920
921 $permissiontoedit = $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write');
922 //$permissiontoedit = 0;
923
924 // Thirdparty
925 if (isModEnabled("societe")) {
926 $morehtmlref .= '<br>';
927 $morehtmlref .= img_picto($langs->trans("ThirdParty"), 'company', 'class="pictofixedwidth"');
928 if ($action != 'editcustomer' && $permissiontoedit) {
929 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editcustomer&token='.newToken().'&track_id='.$object->track_id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty'), 0).'</a> ';
930 }
931 $morehtmlref .= $form->form_thirdparty($url_page_current.'?track_id='.$object->track_id, $object->socid, $action == 'editcustomer' ? 'editcustomer' : 'none', '', 1, 0, 0, array(), 1);
932 if (!empty($object->socid)) {
933 $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>';
934 }
935 }
936
937 // Project
938 if (isModEnabled('project')) {
939 $langs->load("projects");
940 $morehtmlref .= '<br>';
941 if ($permissiontoedit) {
942 $object->fetch_project();
943 $morehtmlref .= img_picto($langs->trans("Project"), 'project'.((is_object($object->project) && $object->project->public) ? 'pub' : ''), 'class="pictofixedwidth"');
944 if ($action != 'classify') {
945 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
946 }
947 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
948 } else {
949 if (!empty($object->fk_project)) {
950 $object->fetch_project();
951 $morehtmlref .= $object->project->getNomUrl(1);
952 if ($object->project->title) {
953 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($object->project->title).'</span>';
954 }
955 }
956 }
957 }
958
959 // Contract
960 if (getDolGlobalString('TICKET_LINK_TO_CONTRACT_WITH_HARDLINK')) {
961 // Deprecated. Duplicate feature. Ticket can already be linked to contract with the generic "Link to" feature.
962 if (isModEnabled('contract')) {
963 $langs->load('contracts');
964 $morehtmlref .= '<br>';
965 if ($permissiontoedit) {
966 $morehtmlref .= img_picto($langs->trans("Contract"), 'contract', 'class="pictofixedwidth"');
967 if ($action == 'edit_contrat') {
968 $formcontract = new FormContract($db);
969 $morehtmlref .= $formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contract, 'contratid', 0, 1, 1, 1);
970 } else {
971 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_contrat&token='.newToken().'&id='.$object->id.'">';
972 $morehtmlref .= img_edit($langs->trans('SetContract'));
973 $morehtmlref .= '</a>';
974 }
975 } else {
976 if (!empty($object->fk_contract)) {
977 $contratstatic = new Contrat($db);
978 $contratstatic->fetch($object->fk_contract);
979 //print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
980 $morehtmlref .= $contratstatic->getNomUrl(0, '', 1);
981 }
982 }
983 }
984 }
985
986 $morehtmlref .= '</div>';
987
988 $linkback = '<a href="'.DOL_URL_ROOT.'/ticket/list.php?restore_lastsearch_values=1"><strong>'.$langs->trans("BackToList").'</strong></a> ';
989
990 dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref);
991
992 print '<div class="fichecenter">';
993 print '<div class="fichehalfleft">';
994 print '<div class="underbanner clearboth"></div>';
995
996 print '<table class="border tableforfield centpercent">';
997
998 // Track ID
999 print '<tr><td class="titlefield">'.$langs->trans("TicketTrackId").'</td><td>';
1000 if (!empty($object->track_id)) {
1001 if (empty($object->ref)) {
1002 $object->ref = $object->id;
1003 print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'track_id');
1004 } else {
1005 print $object->track_id;
1006 }
1007 } else {
1008 print $langs->trans('None');
1009 }
1010 print '</td></tr>';
1011
1012 // Subject
1013 print '<tr><td>';
1014 print $form->editfieldkey("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1015 print '</td><td>';
1016 print $form->editfieldval("Subject", 'subject', $object->subject, $object, $user->hasRight('ticket', 'write') && !$user->socid, 'string');
1017 print '</td></tr>';
1018
1019 // Creation date
1020 print '<tr><td>'.$langs->trans("DateCreation").'</td><td>';
1021 print dol_print_date($object->datec, 'dayhour', 'tzuser');
1022 print '<span class="opacitymedium"> - '.$langs->trans("TimeElapsedSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->datec, 60)).'</i></span>';
1023 print '</td></tr>';
1024
1025 // Origin
1026 /*
1027 if ($object->email_msgid) {
1028 $texttoshow = $langs->trans("CreatedByEmailCollector");
1029 } elseif ($object->origin_email) {
1030 $texttoshow = $langs->trans("FromPublicEmail");
1031 }
1032 if ($texttoshow) {
1033 print '<tr><td class="titlefield fieldname_email_origin">';
1034 print $langs->trans("Origin");
1035 print '</td>';
1036 print '<td class="valuefield fieldname_email_origin">';
1037 print $texttoshow;
1038 print '</td></tr>';
1039 }
1040 */
1041
1042 // Read date
1043 print '<tr><td>'.$langs->trans("TicketReadOn").'</td><td>';
1044 if (!empty($object->date_read)) {
1045 print dol_print_date($object->date_read, 'dayhour', 'tzuser');
1046 print '<span class="opacitymedium"> - '.$langs->trans("TicketTimeElapsedBeforeSince").': <i>'.convertSecondToTime(roundUpToNextMultiple($object->date_read - $object->datec, 60)).'</i>';
1047 print ' / <i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->date_read, 60)).'</i></span>';
1048 }
1049 print '</td></tr>';
1050
1051 // Close date
1052 print '<tr><td>'.$langs->trans("TicketCloseOn").'</td><td>';
1053 if (!empty($object->date_close)) {
1054 print dol_print_date($object->date_close, 'dayhour', 'tzuser');
1055 }
1056 print '</td></tr>';
1057
1058 // User assigned
1059 print '<tr><td>';
1060 print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
1061 print $langs->trans("AssignedTo");
1062 if (isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set', 'alpha') != "assign_ticket" && $user->hasRight('ticket', 'manage')) {
1063 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>';
1064 }
1065 print '</td></tr></table>';
1066 print '</td><td>';
1067 if (GETPOST('set', 'alpha') != "assign_ticket" && $object->fk_user_assign > 0) {
1068 $userstat->fetch($object->fk_user_assign);
1069 print $userstat->getNomUrl(-1);
1070 }
1071
1072 // Show user list to assignate one if status is "read"
1073 if (GETPOST('set', 'alpha') == "assign_ticket" && $object->status < 8 && !$user->socid && $user->hasRight('ticket', 'write')) {
1074 print '<form method="post" name="ticket" enctype="multipart/form-data" action="'.$url_page_current.'">';
1075 print '<input type="hidden" name="token" value="'.newToken().'">';
1076 print '<input type="hidden" name="action" value="assign_user">';
1077 print '<input type="hidden" name="track_id" value="'.$object->track_id.'">';
1078 //print '<label for="fk_user_assign">'.$langs->trans("AssignUser").'</label> ';
1079 print $form->select_dolusers(empty($object->fk_user_assign) ? $user->id : $object->fk_user_assign, 'fk_user_assign', 1);
1080 print ' <input type="submit" class="button small" name="btn_assign_user" value="'.$langs->trans("Validate").'" />';
1081 print '</form>';
1082 }
1083 print '</td></tr>';
1084
1085 // Progression
1086 print '<tr><td>';
1087 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1088 print $langs->trans('Progression').'</td><td class="left">';
1089 print '</td>';
1090 if ($action != 'progression' && isset($object->status) && $object->status < $object::STATUS_CLOSED && !$user->socid) {
1091 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>';
1092 }
1093 print '</tr></table>';
1094 print '</td><td>';
1095 if ($user->hasRight('ticket', 'write') && $action == 'progression') {
1096 print '<form action="'.$url_page_current.'" method="post">';
1097 print '<input type="hidden" name="token" value="'.newToken().'">';
1098 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1099 print '<input type="hidden" name="action" value="set_progression">';
1100 print '<input type="text" class="flat width75" name="progress" value="'.$object->progress.'">';
1101 print ' <input type="submit" class="button button-edit small" value="'.$langs->trans('Modify').'">';
1102 print '</form>';
1103 } else {
1104 print($object->progress > 0 ? $object->progress : '0').'%';
1105 }
1106 print '</td>';
1107 print '</tr>';
1108
1109 // Timing (Duration sum of linked fichinter)
1110 if (isModEnabled('intervention')) {
1111 $object->fetchObjectLinked();
1112 $num = count($object->linkedObjects);
1113 $timing = 0;
1114 $foundinter = 0;
1115 if ($num) {
1116 foreach ($object->linkedObjects as $objecttype => $objects) {
1117 if ($objecttype == "fichinter") {
1118 foreach ($objects as $fichinter) {
1119 $foundinter++;
1120 $timing += $fichinter->duration;
1121 }
1122 }
1123 }
1124 }
1125 print '<tr><td>';
1126 print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1);
1127 print '</td><td>';
1128 print $foundinter ? convertSecondToTime($timing, 'all', getDolGlobalString('MAIN_DURATION_OF_WORKDAY')) : '';
1129 print '</td></tr>';
1130 }
1131
1132 // Other attributes
1133 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1134
1135 print '</table>';
1136
1137
1138 // End of left column and beginning of right column
1139 print '</div><div class="fichehalfright">';
1140
1141
1142 print '<form method="post" name="formticketproperties" action="'.$url_page_current.'">';
1143 print '<input type="hidden" name="token" value="'.newToken().'">';
1144 print '<input type="hidden" name="action" value="change_property">';
1145 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1146 print '<input type="hidden" name="trackid" value="'.$trackid.'">';
1147
1148 //print '<div class="underbanner clearboth"></div>';
1149
1150 // View Original message
1151 $actionobject->viewTicketOriginalMessage($user, $action, $object);
1152
1153 // Classification of ticket
1154 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
1155 print '<table class="border tableforfield centpercent margintable">';
1156 print '<tr class="liste_titre">';
1157 print '<td>';
1158 print $langs->trans('TicketProperties');
1159 print '</td>';
1160 print '<td>';
1161 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1162 print '<input type="submit" class="button smallpaddingimp" name="btn_update_ticket_prop" value="'.$langs->trans("Modify").'" />';
1163 } else {
1164 // Button to edit Properties
1165 if (isset($object->status) && ($object->status < $object::STATUS_NEED_MORE_INFO || !getDolGlobalInt('TICKET_DISALLOW_CLASSIFICATION_MODIFICATION_EVEN_IF_CLOSED')) && $user->hasRight('ticket', 'write')) {
1166 print ' <a class="editfielda" href="card.php?track_id='.$object->track_id.'&set=properties">'.img_edit($langs->trans('Modify')).'</a>';
1167 }
1168 }
1169 print '</td>';
1170 print '</tr>';
1171
1172 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1173 print '<tr>';
1174 // Type
1175 print '<td class="titlefield">';
1176 print $langs->trans('Type');
1177 print '</td><td>';
1178 $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2);
1179 print '</td>';
1180 print '</tr>';
1181 // Group
1182 print '<tr>';
1183 print '<td>';
1184 print $langs->trans('TicketCategory');
1185 print '</td><td>';
1186 $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2, 0, 0, 0, 'maxwidth500 widthcentpercentminusxx');
1187 print '</td>';
1188 print '</tr>';
1189 // Severity
1190 print '<tr>';
1191 print '<td>';
1192 print $langs->trans('TicketSeverity');
1193 print '</td><td>';
1194 $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2);
1195 print '</td>';
1196 print '</tr>';
1197 } else {
1198 // Type
1199 print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
1200 if (!empty($object->type_code)) {
1201 print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
1202 }
1203 print '</td></tr>';
1204 // Group
1205 $s = '';
1206 if (!empty($object->category_code)) {
1207 $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
1208 }
1209 print '<tr><td>'.$langs->trans("TicketCategory").'</td><td class="tdoverflowmax200" title="'.dol_escape_htmltag($s).'">';
1210 print dol_escape_htmltag($s);
1211 print '</td></tr>';
1212 // Severity
1213 print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>';
1214 if (!empty($object->severity_code)) {
1215 print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
1216 }
1217 print '</td></tr>';
1218 }
1219 print '</table>'; // End table actions
1220 print '</div>';
1221
1222 print '</form>';
1223
1224 // Tags/Categories
1225 if (isModEnabled('category')) {
1226 print '<table class="border centpercent tableforfield">';
1227 print '<tr>';
1228 print '<td class="valignmiddle titlefield">';
1229 print '<table class="nobordernopadding centpercent"><tr><td class="titlefield">';
1230 print $langs->trans("Categories");
1231 if ($action != 'categories' && !$user->socid) {
1232 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>';
1233 }
1234 print '</table>';
1235 print '</td>';
1236
1237 if ($user->hasRight('ticket', 'write') && $action == 'categories') {
1238 $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
1239 if (is_array($cate_arbo)) {
1240 // Categories
1241 print '<td colspan="3">';
1242 print '<form action="'.$url_page_current.'" method="POST">';
1243 print '<input type="hidden" name="token" value="'.newToken().'">';
1244 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1245 print '<input type="hidden" name="action" value="set_categories">';
1246
1247 $category = new Categorie($db);
1248 $cats = $category->containing($object->id, 'ticket');
1249 $arrayselected = array();
1250 foreach ($cats as $cat) {
1251 $arrayselected[] = $cat->id;
1252 }
1253
1254 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'maxwidth500 widthcentpercentminusx', 0, 0);
1255 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Save').'">';
1256 print '</form>';
1257 print "</td>";
1258 }
1259 } else {
1260 print '<td colspan="3">';
1261 print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1);
1262 print "</td></tr>";
1263 }
1264
1265 print '</table>';
1266 }
1267
1268
1269 // Display navbar with links to change ticket status
1270 print '<!-- navbar with status -->';
1271 if (!$user->socid && $user->hasRight('ticket', 'write') && isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set') !== 'properties') {
1272 $actionobject->viewStatusActions($object);
1273 }
1274
1275
1276 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1277 print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png');
1278
1279 print '<div class="div-table-responsive-no-min">';
1280 print '<div class="tagtable centpercent noborder allwidth">';
1281
1282 print '<div class="tagtr liste_titre">';
1283 print '<div class="tagtd">'.$langs->trans("Source").'</div>
1284 <div class="tagtd">' . $langs->trans("Company").'</div>
1285 <div class="tagtd">' . $langs->trans("Contacts").'</div>
1286 <div class="tagtd">' . $langs->trans("ContactType").'</div>
1287 <div class="tagtd">' . $langs->trans("Phone").'</div>
1288 <div class="tagtd center">' . $langs->trans("Status").'</div>';
1289 print '</div><!-- tagtr -->';
1290
1291 // Contact list
1292 $companystatic = new Societe($db);
1293 $contactstatic = new Contact($db);
1294 $userstatic = new User($db);
1295 $var = false;
1296 foreach (array('internal', 'external') as $source) {
1297 $tmpobject = $object;
1298 $tab = $tmpobject->listeContact(-1, $source);
1299 '@phan-var-force array<array{source:string,id:int,rowid:int,email:string,civility:string,firstname:string,lastname:string,labeltype:string,libelle:string,socid:int,code:string,status:int,statuscontact:string,fk_c_typecontact:string,phone:string,phone_mobile:string,nom:string}> $tab';
1300 $num = is_array($tab) ? 0 : count($tab);
1301 $i = 0;
1302 foreach (array_keys($tab) as $i) {
1303 $var = !$var;
1304 print '<div class="tagtr '.($var ? 'pair' : 'impair').'">';
1305
1306 print '<div class="tagtd left">';
1307 if ($tab[$i]['source'] == 'internal') {
1308 echo $langs->trans("User");
1309 }
1310
1311 if ($tab[$i]['source'] == 'external') {
1312 echo $langs->trans("ThirdPartyContact");
1313 }
1314
1315 print '</div>';
1316 print '<div class="tagtd left">';
1317
1318 if ($tab[$i]['socid'] > 0) {
1319 $companystatic->fetch($tab[$i]['socid']);
1320 echo $companystatic->getNomUrl(-1);
1321 }
1322 if ($tab[$i]['socid'] < 0) {
1323 echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
1324 }
1325 if (!$tab[$i]['socid']) {
1326 echo '&nbsp;';
1327 }
1328 print '</div>';
1329
1330 print '<div class="tagtd">';
1331 if ($tab[$i]['source'] == 'internal') {
1332 if ($userstatic->fetch($tab[$i]['id'])) {
1333 print $userstatic->getNomUrl(-1);
1334 }
1335 }
1336 if ($tab[$i]['source'] == 'external') {
1337 if ($contactstatic->fetch($tab[$i]['id'])) {
1338 print $contactstatic->getNomUrl(-1);
1339 }
1340 }
1341 print ' </div>
1342 <div class="tagtd">' . $tab[$i]['libelle'].'</div>';
1343
1344 print '<div class="tagtd">';
1345
1346 print dol_print_phone($tab[$i]['phone'], '', '', '', 'AC_TEL').'<br>';
1347
1348 if (!empty($tab[$i]['phone_perso'])) {
1349 //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' ';
1350 print '<br>'.dol_print_phone($tab[$i]['phone_perso'], '', '', '', 'AC_TEL').'<br>';
1351 }
1352 if (!empty($tab[$i]['phone_mobile'])) {
1353 //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' ';
1354 print dol_print_phone($tab[$i]['phone_mobile'], '', '', '', 'AC_TEL').'<br>';
1355 }
1356 print '</div>';
1357
1358 print '<div class="tagtd center">';
1359 if ($object->status >= 0) {
1360 echo '<a href="contact.php?track_id='.$object->track_id.'&amp;action=swapstatut&amp;ligne='.$tab[$i]['rowid'].'">';
1361 }
1362
1363 if ($tab[$i]['source'] == 'internal') {
1364 $userstatic->id = $tab[$i]['id'];
1365 $userstatic->lastname = $tab[$i]['lastname'];
1366 $userstatic->firstname = $tab[$i]['firstname'];
1367 echo $userstatic->LibStatut($tab[$i]['statuscontact'], 3);
1368 }
1369 if ($tab[$i]['source'] == 'external') {
1370 $contactstatic->id = $tab[$i]['id'];
1371 $contactstatic->lastname = $tab[$i]['lastname'];
1372 $contactstatic->firstname = $tab[$i]['firstname'];
1373 echo $contactstatic->LibStatut($tab[$i]['statuscontact'], 3);
1374 }
1375 if ($object->status >= 0) {
1376 echo '</a>';
1377 }
1378
1379 print '</div>';
1380
1381 print '</div><!-- tagtr -->';
1382
1383 $i++;
1384 }
1385 }
1386
1387 print '</div><!-- contact list -->';
1388 print '</div>';
1389 }
1390
1391 print '</div></div>';
1392 print '<div class="clearboth"></div>';
1393
1394 print dol_get_fiche_end();
1395
1396
1397 // Buttons for actions
1398 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') {
1399 print '<div class="tabsAction">'."\n";
1400 $parameters = array();
1401 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1402 if ($reshook < 0) {
1403 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1404 }
1405
1406 if (empty($reshook)) {
1407 // Email
1408 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1409 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', '');
1410 }
1411
1412 // Show link to add a message (if read and not closed)
1413 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1414 print dolGetButtonAction('', $langs->trans('TicketAddPrivateMessage'), 'default', $_SERVER["PHP_SELF"].'?action=presend_addmessage&mode=init&token='.newToken().'&track_id='.$object->track_id.'#formmailbeforetitle', '');
1415 }
1416
1417 // Link to create an intervention
1418 // socid is needed otherwise fichinter ask it and forgot origin after form submit :\
1419 if (!$object->fk_soc && $user->hasRight("ficheinter", "creer")) {
1420 print dolGetButtonAction($langs->trans('UnableToCreateInterIfNoSocid'), $langs->trans('TicketAddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1421 }
1422 if ($object->fk_soc > 0 && isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ficheinter', 'creer')) {
1423 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, '');
1424 }
1425
1426 // Close ticket if status is read
1427 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1428 print dolGetButtonAction('', $langs->trans('CloseTicket'), 'default', $_SERVER["PHP_SELF"].'?action=close&token='.newToken().'&track_id='.$object->track_id, '');
1429 }
1430
1431 // Abandon ticket if status is read
1432 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1433 print dolGetButtonAction('', $langs->trans('AbandonTicket'), 'default', $_SERVER["PHP_SELF"].'?action=abandon&token='.newToken().'&track_id='.$object->track_id, '');
1434 }
1435
1436 // Re-open ticket
1437 if (!$user->socid && (isset($object->status) && ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED)) && !$user->socid) {
1438 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&track_id='.$object->track_id, '');
1439 }
1440
1441 // Edit ticket
1442 if ($permissiontoedit) {
1443 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoedit);
1444 }
1445
1446 // Delete ticket
1447 if ($user->hasRight('ticket', 'delete') && !$user->socid) {
1448 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&track_id='.$object->track_id, '');
1449 }
1450 }
1451 print '</div>'."\n";
1452 }
1453
1454 // Select mail models is same action as presend
1455 if (GETPOST('modelselected')) {
1456 $action = 'presend';
1457 }
1458 // Set $action to correct value for the case we used presend action to add a message
1459 if (GETPOSTISSET('actionbis') && $action == 'presend') {
1460 $action = 'presend_addmessage';
1461 }
1462
1463 // add a message
1464 if ($action == 'presend' || $action == 'presend_addmessage') {
1465 if ($object->fk_soc > 0) {
1466 $object->fetch_thirdparty();
1467 }
1468
1469 $outputlangs = $langs;
1470 $newlang = '';
1471 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1472 $newlang = GETPOST('lang_id', 'aZ09');
1473 } elseif (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && is_object($object->thirdparty)) {
1474 $newlang = $object->thirdparty->default_lang;
1475 }
1476 if (!empty($newlang)) {
1477 $outputlangs = new Translate("", $conf);
1478 $outputlangs->setDefaultLang($newlang);
1479 }
1480
1481 $arrayoffamiliestoexclude = array('objectamount');
1482
1483 $action = 'add_message'; // action to use to post the message
1484 $modelmail = 'ticket_send';
1485
1486 // Substitution array
1487 $morehtmlright = '';
1488 $help = "";
1489 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object);
1490 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1491 $morehtmlright .= $form->textwithpicto('<span class="opacitymedium">'.$langs->trans("TicketMessageSubstitutionReplacedByGenericValues").'</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution');
1492
1493 print '<div>';
1494
1495 print '<div id="formmailbeforetitle" name="formmailbeforetitle"></div>';
1496
1497 print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket');
1498
1499 print '<hr>';
1500
1501 $formticket = new FormTicket($db);
1502
1503 $formticket->action = $action;
1504 $formticket->track_id = $object->track_id;
1505 $formticket->ref = $object->ref;
1506 $formticket->id = $object->id;
1507 $formticket->trackid = 'tic'.$object->id;
1508
1509 $formticket->withfile = 2;
1510 $formticket->withcancel = 1;
1511 $formticket->param = array('fk_user_create' => $user->id);
1512 $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang);
1513
1514 // Table of additional post parameters
1515 $formticket->param['models'] = $modelmail;
1516 $formticket->param['models_id'] = GETPOSTINT('modelmailselected');
1517 //$formticket->param['socid']=$object->fk_soc;
1518 $formticket->param['returnurl'] = $_SERVER["PHP_SELF"].'?track_id='.$object->track_id;
1519
1520 $formticket->withsubstit = 1;
1521 $formticket->substit = $substitutionarray;
1522 $formticket->backtopage = $backtopage;
1523
1524 $formticket->showMessageForm('100%');
1525 print '</div>';
1526 }
1527
1528 // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
1529 if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) {
1530 $param = '&id='.$object->id;
1531 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1532 $param .= '&contextpage='.$contextpage;
1533 }
1534 if ($limit > 0 && $limit != $conf->liste_limit) {
1535 $param .= '&limit='.$limit;
1536 }
1537 if ($actioncode) {
1538 $param .= '&actioncode='.urlencode($actioncode);
1539 }
1540 if ($search_agenda_label) {
1541 $param .= '&search_agenda_label='.urlencode($search_agenda_label);
1542 }
1543
1544 $morehtmlright = '';
1545
1546 $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id;
1547 $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 1);
1548
1549 // Show link to add a message (if read and not closed)
1550 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1551 $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init';
1552 $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fa fa-comment-dots', $url, 'add-new-ticket-title-button', $btnstatus);
1553
1554 // Show link to add event (if read and not closed)
1555 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1556 $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);
1557 $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus);
1558
1559 print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
1560
1561 // List of all actions
1562 $filters = array();
1563 $filters['search_agenda_label'] = $search_agenda_label;
1564 $filters['search_rowid'] = $search_rowid;
1565
1566 show_actions_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder);
1567 }
1568
1569 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') {
1570 print '<div class="fichecenter"><div class="fichehalfleft">';
1571 print '<a name="builddoc"></a>'; // ancre
1572 /*
1573 * Generated documents
1574 */
1575 $filename = dol_sanitizeFileName($object->ref);
1576 $filedir = $upload_dir."/".dol_sanitizeFileName($object->ref);
1577 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1578 $genallowed = $permissiontoadd;
1579 $delallowed = $permissiontodelete;
1580 $codelang = '';
1581 if ($object->fk_soc > 0) {
1582 $object->fetch_thirdparty();
1583 $codelang = $object->thirdparty->default_lang;
1584 }
1585
1586 print $formfile->showdocuments('ticket', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $codelang);
1587
1588 // Show links to link elements
1589 $linktoelem = $form->showLinkToObjectBlock($object, null, array('ticket'));
1590 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1591
1592 // Show direct link to public interface
1593 print '<br><!-- Link to public interface -->'."\n";
1594 print showDirectPublicLink($object).'<br>';
1595 print '</div>';
1596
1597 if (!getDolGlobalString('MAIN_HIDE_MESSAGES_ON_CARD')) {
1598 print '<div class="fichehalfright">';
1599
1600 $MAXEVENT = 10;
1601
1602 $morehtmlcenter = '<div class="nowraponall">';
1603 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/ticket/messaging.php?id='.$object->id);
1604 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id);
1605 $morehtmlcenter .= '</div>';
1606
1607 // List of actions on element
1608 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1609 $formactions = new FormActions($db);
1610 $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
1611
1612 print '</div>';
1613 }
1614
1615 print '</div>';
1616 }
1617 }
1618}
1619
1620// End of page
1621llxFooter();
1622$db->close();
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 contracts.
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.
dol_print_phone($phone, $countrycode='', $cid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='')
Format phone numbers according to country.
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.
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)
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).
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
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 dolibarr global constant string value.
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.