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