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