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