card.php 57 KB

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