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