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