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