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