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);
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 // 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
1158
1159
1160 print '<form method="post" name="formticketproperties" action="'.$url_page_current.'">';
1161 print '<input type="hidden" name="token" value="'.newToken().'">';
1162 print '<input type="hidden" name="action" value="change_property">';
1163 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1164 print '<input type="hidden" name="trackid" value="'.$trackid.'">';
1165
1166 // Classification of ticket
1167 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
1168 print '<table class="border tableforfield centpercent margintable bordertopimp">';
1169 print '<tr class="liste_titre">';
1170 print '<td>';
1171 print $langs->trans('TicketProperties');
1172 print '</td>';
1173 print '<td>';
1174 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1175 print '<input type="submit" class="button smallpaddingimp" name="btn_update_ticket_prop" value="'.$langs->trans("Modify").'" />';
1176 } else {
1177 // Button to edit Properties
1178 if (isset($object->status) && ($object->status < $object::STATUS_NEED_MORE_INFO || getDolGlobalString('TICKET_ALLOW_CLASSIFICATION_MODIFICATION_EVEN_IF_CLOSED')) && $user->hasRight('ticket', 'write')) {
1179 print ' <a class="editfielda" href="card.php?track_id='.$object->track_id.'&set=properties">'.img_edit($langs->trans('Modify')).'</a>';
1180 }
1181 }
1182 print '</td>';
1183 print '</tr>';
1184
1185 if (GETPOST('set', 'alpha') == 'properties' && $user->hasRight('ticket', 'write')) {
1186 print '<tr>';
1187 // Type
1188 print '<td class="titlefield">';
1189 print $langs->trans('Type');
1190 print '</td><td>';
1191 $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2);
1192 print '</td>';
1193 print '</tr>';
1194 // Group
1195 print '<tr>';
1196 print '<td>';
1197 print $langs->trans('TicketCategory');
1198 print '</td><td>';
1199 $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2, 0, 0, 0, 'maxwidth500 widthcentpercentminusxx');
1200 print '</td>';
1201 print '</tr>';
1202 // Severity
1203 print '<tr>';
1204 print '<td>';
1205 print $langs->trans('TicketSeverity');
1206 print '</td><td>';
1207 $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2);
1208 print '</td>';
1209 print '</tr>';
1210 } else {
1211 // Type
1212 print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
1213 if (!empty($object->type_code)) {
1214 print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
1215 }
1216 print '</td></tr>';
1217 // Group
1218 $s = '';
1219 if (!empty($object->category_code)) {
1220 $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
1221 }
1222 print '<tr><td>'.$langs->trans("TicketCategory").'</td><td class="tdoverflowmax200" title="'.dol_escape_htmltag($s).'">';
1223 print dol_escape_htmltag($s);
1224 print '</td></tr>';
1225 // Severity
1226 print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>';
1227 if (!empty($object->severity_code)) {
1228 print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
1229 }
1230 print '</td></tr>';
1231 }
1232 print '</table>'; // End table actions
1233 print '</div>';
1234
1235 print '</form>';
1236
1237 // Tags/Categories
1238 if (isModEnabled('category')) {
1239 print '<table class="border centpercent tableforfield">';
1240 print '<tr>';
1241 print '<td class="valignmiddle titlefield">';
1242 print '<table class="nobordernopadding centpercent"><tr><td class="titlefield">';
1243 print $langs->trans("Categories");
1244 if ($action != 'categories' && !$user->socid) {
1245 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>';
1246 }
1247 print '</table>';
1248 print '</td>';
1249
1250 if ($user->hasRight('ticket', 'write') && $action == 'categories') {
1251 $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 3);
1252 if (is_array($cate_arbo)) {
1253 // Categories
1254 print '<td colspan="3">';
1255 print '<form action="'.$url_page_current.'" method="POST">';
1256 print '<input type="hidden" name="token" value="'.newToken().'">';
1257 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1258 print '<input type="hidden" name="action" value="set_categories">';
1259
1260 $category = new Categorie($db);
1261 $cats = $category->containing($object->id, 'ticket');
1262 $arrayselected = array();
1263 foreach ($cats as $cat) {
1264 $arrayselected[] = $cat->id;
1265 }
1266
1267 print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'maxwidth500 widthcentpercentminusx', 0, 0);
1268 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Save').'">';
1269 print '</form>';
1270 print "</td>";
1271 }
1272 } else {
1273 print '<td colspan="3">';
1274 print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1);
1275 print "</td></tr>";
1276 }
1277
1278 print '</table>';
1279 }
1280
1281 // View Original message
1282 $actionobject->viewTicketOriginalMessage($user, $action, $object);
1283
1284
1285 // Display navbar with links to change ticket status
1286 print '<!-- navbar with status -->';
1287 if (!$user->socid && $user->hasRight('ticket', 'write') && isset($object->status) && $object->status < $object::STATUS_CLOSED) {
1288 $actionobject->viewStatusActions($object);
1289 }
1290
1291
1292 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1293 print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png');
1294
1295 print '<div class="div-table-responsive-no-min">';
1296 print '<div class="tagtable centpercent noborder allwidth">';
1297
1298 print '<div class="tagtr liste_titre">';
1299 print '<div class="tagtd">'.$langs->trans("Source").'</div>
1300 <div class="tagtd">' . $langs->trans("Company").'</div>
1301 <div class="tagtd">' . $langs->trans("Contacts").'</div>
1302 <div class="tagtd">' . $langs->trans("ContactType").'</div>
1303 <div class="tagtd">' . $langs->trans("Phone").'</div>
1304 <div class="tagtd center">' . $langs->trans("Status").'</div>';
1305 print '</div><!-- tagtr -->';
1306
1307 // Contact list
1308 $companystatic = new Societe($db);
1309 $contactstatic = new Contact($db);
1310 $userstatic = new User($db);
1311 $var = false;
1312 foreach (array('internal', 'external') as $source) {
1313 $tmpobject = $object;
1314 $tab = $tmpobject->listeContact(-1, $source);
1315 '@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';
1316 $num = is_array($tab) ? 0 : count($tab);
1317 $i = 0;
1318 foreach (array_keys($tab) as $i) {
1319 $var = !$var;
1320 print '<div class="tagtr '.($var ? 'pair' : 'impair').'">';
1321
1322 print '<div class="tagtd left">';
1323 if ($tab[$i]['source'] == 'internal') {
1324 echo $langs->trans("User");
1325 }
1326
1327 if ($tab[$i]['source'] == 'external') {
1328 echo $langs->trans("ThirdPartyContact");
1329 }
1330
1331 print '</div>';
1332 print '<div class="tagtd left">';
1333
1334 if ($tab[$i]['socid'] > 0) {
1335 $companystatic->fetch($tab[$i]['socid']);
1336 echo $companystatic->getNomUrl(-1);
1337 }
1338 if ($tab[$i]['socid'] < 0) {
1339 echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
1340 }
1341 if (!$tab[$i]['socid']) {
1342 echo '&nbsp;';
1343 }
1344 print '</div>';
1345
1346 print '<div class="tagtd">';
1347 if ($tab[$i]['source'] == 'internal') {
1348 if ($userstatic->fetch($tab[$i]['id'])) {
1349 print $userstatic->getNomUrl(-1);
1350 }
1351 }
1352 if ($tab[$i]['source'] == 'external') {
1353 if ($contactstatic->fetch($tab[$i]['id'])) {
1354 print $contactstatic->getNomUrl(-1);
1355 }
1356 }
1357 print ' </div>
1358 <div class="tagtd">' . $tab[$i]['libelle'].'</div>';
1359
1360 print '<div class="tagtd">';
1361
1362 print dol_print_phone($tab[$i]['phone'], '', '', '', 'AC_TEL').'<br>';
1363
1364 if (!empty($tab[$i]['phone_perso'])) {
1365 //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' ';
1366 print '<br>'.dol_print_phone($tab[$i]['phone_perso'], '', '', '', 'AC_TEL').'<br>';
1367 }
1368 if (!empty($tab[$i]['phone_mobile'])) {
1369 //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' ';
1370 print dol_print_phone($tab[$i]['phone_mobile'], '', '', '', 'AC_TEL').'<br>';
1371 }
1372 print '</div>';
1373
1374 print '<div class="tagtd center">';
1375 if ($object->status >= 0) {
1376 echo '<a href="contact.php?track_id='.$object->track_id.'&amp;action=swapstatut&amp;ligne='.$tab[$i]['rowid'].'">';
1377 }
1378
1379 if ($tab[$i]['source'] == 'internal') {
1380 $userstatic->id = $tab[$i]['id'];
1381 $userstatic->lastname = $tab[$i]['lastname'];
1382 $userstatic->firstname = $tab[$i]['firstname'];
1383 echo $userstatic->LibStatut($tab[$i]['statuscontact'], 3);
1384 }
1385 if ($tab[$i]['source'] == 'external') {
1386 $contactstatic->id = $tab[$i]['id'];
1387 $contactstatic->lastname = $tab[$i]['lastname'];
1388 $contactstatic->firstname = $tab[$i]['firstname'];
1389 echo $contactstatic->LibStatut($tab[$i]['statuscontact'], 3);
1390 }
1391 if ($object->status >= 0) {
1392 echo '</a>';
1393 }
1394
1395 print '</div>';
1396
1397 print '</div><!-- tagtr -->';
1398
1399 $i++;
1400 }
1401 }
1402
1403 print '</div><!-- contact list -->';
1404 print '</div>';
1405 }
1406
1407 print '</div></div>';
1408 print '<div class="clearboth"></div>';
1409
1410 print dol_get_fiche_end();
1411
1412
1413 // Buttons for actions
1414 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') {
1415 print '<div class="tabsAction">'."\n";
1416 $parameters = array();
1417 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1418 if ($reshook < 0) {
1419 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1420 }
1421
1422 if (empty($reshook)) {
1423 // Email
1424 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1425 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', '');
1426 }
1427
1428 // Show link to add a message (if read and not closed)
1429 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1430 print dolGetButtonAction('', $langs->trans('TicketAddPrivateMessage'), 'default', $_SERVER["PHP_SELF"].'?action=presend_addmessage&mode=init&token='.newToken().'&track_id='.$object->track_id.'#formmailbeforetitle', '');
1431 }
1432
1433 // Link to create an intervention
1434 // socid is needed otherwise fichinter ask it and forgot origin after form submit :\
1435 if (!$object->fk_soc && $user->hasRight("ficheinter", "creer")) {
1436 print dolGetButtonAction($langs->trans('UnableToCreateInterIfNoSocid'), $langs->trans('TicketAddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1437 }
1438 if ($object->fk_soc > 0 && isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ficheinter', 'creer')) {
1439 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, '');
1440 }
1441
1442 // Close ticket if status is read
1443 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1444 print dolGetButtonAction('', $langs->trans('CloseTicket'), 'default', $_SERVER["PHP_SELF"].'?action=close&token='.newToken().'&track_id='.$object->track_id, '');
1445 }
1446
1447 // Abandon ticket if status is read
1448 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ticket', 'write')) {
1449 print dolGetButtonAction('', $langs->trans('AbandonTicket'), 'default', $_SERVER["PHP_SELF"].'?action=abandon&token='.newToken().'&track_id='.$object->track_id, '');
1450 }
1451
1452 // Re-open ticket
1453 if (!$user->socid && (isset($object->status) && ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED)) && !$user->socid) {
1454 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&track_id='.$object->track_id, '');
1455 }
1456
1457 // Edit ticket
1458 if ($permissiontoedit) {
1459 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoedit);
1460 }
1461
1462 // Delete ticket
1463 if ($user->hasRight('ticket', 'delete') && !$user->socid) {
1464 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&track_id='.$object->track_id, '');
1465 }
1466 }
1467 print '</div>'."\n";
1468 }
1469
1470 // Select mail models is same action as presend
1471 if (GETPOST('modelselected')) {
1472 $action = 'presend';
1473 }
1474 // Set $action to correct value for the case we used presend action to add a message
1475 if (GETPOSTISSET('actionbis') && $action == 'presend') {
1476 $action = 'presend_addmessage';
1477 }
1478
1479 // add a message
1480 if ($action == 'presend' || $action == 'presend_addmessage') {
1481 if ($object->fk_soc > 0) {
1482 $object->fetch_thirdparty();
1483 }
1484
1485 $outputlangs = $langs;
1486 $newlang = '';
1487 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1488 $newlang = GETPOST('lang_id', 'aZ09');
1489 } elseif (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && is_object($object->thirdparty)) {
1490 $newlang = $object->thirdparty->default_lang;
1491 }
1492 if (!empty($newlang)) {
1493 $outputlangs = new Translate("", $conf);
1494 $outputlangs->setDefaultLang($newlang);
1495 }
1496
1497 $arrayoffamiliestoexclude = array('objectamount');
1498
1499 $action = 'add_message'; // action to use to post the message
1500 $modelmail = 'ticket_send';
1501
1502 // Substitution array
1503 $morehtmlright = '';
1504 $help = "";
1505 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object);
1506 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1507 $morehtmlright .= $form->textwithpicto('<span class="opacitymedium">'.$langs->trans("TicketMessageSubstitutionReplacedByGenericValues").'</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution');
1508
1509 print '<div>';
1510
1511 print '<div id="formmailbeforetitle" name="formmailbeforetitle"></div>';
1512
1513 print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket');
1514
1515 print '<hr>';
1516
1517 $formticket = new FormTicket($db);
1518
1519 $formticket->action = $action;
1520 $formticket->track_id = $object->track_id;
1521 $formticket->ref = $object->ref;
1522 $formticket->id = $object->id;
1523 $formticket->trackid = 'tic'.$object->id;
1524
1525 $formticket->withfile = 2;
1526 $formticket->withcancel = 1;
1527 $formticket->param = array('fk_user_create' => $user->id);
1528 $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang);
1529
1530 // Table of additional post parameters
1531 $formticket->param['models'] = $modelmail;
1532 $formticket->param['models_id'] = GETPOSTINT('modelmailselected');
1533 //$formticket->param['socid']=$object->fk_soc;
1534 $formticket->param['returnurl'] = $_SERVER["PHP_SELF"].'?track_id='.$object->track_id;
1535
1536 $formticket->withsubstit = 1;
1537 $formticket->substit = $substitutionarray;
1538 $formticket->backtopage = $backtopage;
1539
1540 $formticket->showMessageForm('100%');
1541 print '</div>';
1542 }
1543
1544 // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
1545 if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) {
1546 $param = '&id='.$object->id;
1547 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1548 $param .= '&contextpage='.$contextpage;
1549 }
1550 if ($limit > 0 && $limit != $conf->liste_limit) {
1551 $param .= '&limit='.$limit;
1552 }
1553 if ($actioncode) {
1554 $param .= '&actioncode='.urlencode($actioncode);
1555 }
1556 if ($search_agenda_label) {
1557 $param .= '&search_agenda_label='.urlencode($search_agenda_label);
1558 }
1559
1560 $morehtmlright = '';
1561
1562 $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id;
1563 $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 1);
1564
1565 // Show link to add a message (if read and not closed)
1566 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1567 $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init';
1568 $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fa fa-comment-dots', $url, 'add-new-ticket-title-button', $btnstatus);
1569
1570 // Show link to add event (if read and not closed)
1571 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1572 $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);
1573 $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', $btnstatus);
1574
1575 print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
1576
1577 // List of all actions
1578 $filters = array();
1579 $filters['search_agenda_label'] = $search_agenda_label;
1580 $filters['search_rowid'] = $search_rowid;
1581
1582 show_actions_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder);
1583 }
1584
1585 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') {
1586 print '<div class="fichecenter"><div class="fichehalfleft">';
1587 print '<a name="builddoc"></a>'; // ancre
1588 /*
1589 * Generated documents
1590 */
1591 $filename = dol_sanitizeFileName($object->ref);
1592 $filedir = $upload_dir."/".dol_sanitizeFileName($object->ref);
1593 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1594 $genallowed = $permissiontoadd;
1595 $delallowed = $permissiontodelete;
1596 $codelang = '';
1597 if ($object->fk_soc > 0) {
1598 $object->fetch_thirdparty();
1599 $codelang = $object->thirdparty->default_lang;
1600 }
1601
1602 print $formfile->showdocuments('ticket', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', 0, '', $codelang);
1603
1604 // Show links to link elements
1605 $linktoelem = $form->showLinkToObjectBlock($object, null, array('ticket'));
1606 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1607
1608 // Show direct link to public interface
1609 print '<br><!-- Link to public interface -->'."\n";
1610 print showDirectPublicLink($object).'<br>';
1611 print '</div>';
1612
1613 if (!getDolGlobalString('MAIN_HIDE_MESSAGES_ON_CARD')) {
1614 print '<div class="fichehalfright">';
1615
1616 $MAXEVENT = 10;
1617
1618 $morehtmlcenter = '<div class="nowraponall">';
1619 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/ticket/messaging.php?id='.$object->id);
1620 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id);
1621 $morehtmlcenter .= '</div>';
1622
1623 // List of actions on element
1624 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1625 $formactions = new FormActions($db);
1626 $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
1627
1628 print '</div>';
1629 }
1630
1631 print '</div>';
1632 }
1633 }
1634}
1635
1636// End of page
1637llxFooter();
1638$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:241
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.