card.php 61 KB

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