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