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