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