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