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