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