html.formticket.class.php 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. <?php
  2. /* Copyright (C) - 2013-2015 Jean-François FERRY <hello@librethic.io>
  3. * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file ticket/class/html.ticket.class.php
  20. * \ingroup ticket
  21. * \brief Fichier de la classe permettant la generation du formulaire html d'envoi de mail unitaire
  22. */
  23. require_once DOL_DOCUMENT_ROOT . "/core/class/html.form.class.php";
  24. require_once DOL_DOCUMENT_ROOT . "/core/class/html.formmail.class.php";
  25. if (!class_exists('FormCompany')) {
  26. include DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php';
  27. }
  28. /**
  29. * Classe permettant la generation du formulaire d'un nouveau ticket.
  30. *
  31. * @package Ticket
  32. * \remarks Utilisation: $formticket = new FormTicket($db)
  33. * \remarks $formticket->proprietes=1 ou chaine ou tableau de valeurs
  34. * \remarks $formticket->show_form() affiche le formulaire
  35. */
  36. class FormTicket
  37. {
  38. /**
  39. * @var DoliDB Database handler.
  40. */
  41. public $db;
  42. public $track_id;
  43. public $fk_user_create;
  44. public $message;
  45. public $topic_title;
  46. public $action;
  47. public $withtopic;
  48. public $withemail;
  49. /**
  50. *
  51. * @var int $withsubstit Show substitution array
  52. */
  53. public $withsubstit;
  54. public $withfile;
  55. public $ispublic; // To show information or not into public form
  56. public $withtitletopic;
  57. public $withcompany; // affiche liste déroulante company
  58. public $withfromsocid;
  59. public $withfromcontactid;
  60. public $withnotnotifytiersatcreate;
  61. public $withusercreate; // Show name of creating user in form
  62. public $withcreatereadonly;
  63. public $withref; // Show ref field
  64. public $withcancel;
  65. /**
  66. *
  67. * @var array $substit Substitutions
  68. */
  69. public $substit = array();
  70. public $param = array();
  71. /**
  72. * @var string Error code (or message)
  73. */
  74. public $error;
  75. /**
  76. * Constructor
  77. *
  78. * @param DoliDB $db Database handler
  79. */
  80. public function __construct($db)
  81. {
  82. $this->db = $db;
  83. $this->action = 'add_ticket';
  84. $this->withcompany = 1;
  85. $this->withfromsocid = 0;
  86. $this->withfromcontactid = 0;
  87. //$this->withthreadid=0;
  88. //$this->withtitletopic='';
  89. $this->withnotnotifytiersatcreate = 0;
  90. $this->withusercreate = 1;
  91. $this->withcreatereadonly = 1;
  92. $this->withemail = 0;
  93. $this->withref = 0;
  94. $this->withextrafields = 0; // Show extrafields or not
  95. //$this->withtopicreadonly=0;
  96. }
  97. /**
  98. * Show the form to input ticket
  99. *
  100. * @param int $withdolfichehead With dol_fiche_head
  101. * @return void
  102. */
  103. public function showForm($withdolfichehead=0)
  104. {
  105. global $conf, $langs, $user, $hookmanager;
  106. // Load translation files required by the page
  107. $langs->loadLangs(array('other', 'mails', 'ticket'));
  108. $form = new Form($this->db);
  109. $formcompany = new FormCompany($this->db);
  110. $ticketstatic = new Ticket($this->db);
  111. $soc = new Societe($this->db);
  112. if (!empty($this->withfromsocid) && $this->withfromsocid > 0) {
  113. $soc->fetch($this->withfromsocid);
  114. }
  115. $ticketstat = new Ticket($this->db);
  116. $extrafields = new ExtraFields($this->db);
  117. $extralabels = $extrafields->fetch_name_optionals_label($ticketstat->table_element);
  118. print "\n<!-- Begin form TICKETSUP -->\n";
  119. if ($withdolfichehead) dol_fiche_head(null, 'card', '', 0, '');
  120. print '<form method="POST" '.($withdolfichehead?'':'style="margin-bottom: 30px;" ').'name="ticket" id="form_create_ticket" enctype="multipart/form-data" action="' . $this->param["returnurl"] . '">';
  121. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  122. print '<input type="hidden" name="action" value="' . $this->action . '">';
  123. foreach ($this->param as $key => $value) {
  124. print '<input type="hidden" name="' . $key . '" value="' . $value . '">';
  125. }
  126. print '<input type="hidden" name="fk_user_create" value="' . $this->fk_user_create . '">';
  127. print '<table class="border">';
  128. if ($this->withref) {
  129. // Ref
  130. $defaultref = $ticketstat->getDefaultRef();
  131. print '<tr><td class="titlefield"><span class="fieldrequired">' . $langs->trans("Ref") . '</span></td><td><input size="18" type="text" name="ref" value="' . (GETPOST("ref", 'alpha') ? GETPOST("ref", 'alpha') : $defaultref) . '"></td></tr>';
  132. }
  133. // FK_USER_CREATE
  134. if ($this->withusercreate > 0 && $this->fk_user_create) {
  135. print '<tr><td class="titlefield">' . $langs->trans("CreatedBy") . '</td><td>';
  136. $langs->load("users");
  137. $fuser = new User($this->db);
  138. if ($this->withcreatereadonly) {
  139. if ($res = $fuser->fetch($this->fk_user_create)) {
  140. print $fuser->getNomUrl(1);
  141. }
  142. }
  143. print ' &nbsp; ';
  144. print "</td></tr>\n";
  145. }
  146. // Customer or supplier
  147. if ($this->withcompany) {
  148. // altairis: force company and contact id for external user
  149. if (empty($user->socid)) {
  150. // Company
  151. print '<tr><td class="titlefield">' . $langs->trans("ThirdParty") . '</td><td>';
  152. $events = array();
  153. $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled'));
  154. print $form->select_company($this->withfromsocid, 'socid', '', 1, 1, '', $events, 0, 'minwidth200');
  155. print '</td></tr>';
  156. if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT)) {
  157. $htmlname = 'socid';
  158. print '<script type="text/javascript">
  159. $(document).ready(function () {
  160. jQuery("#'.$htmlname.'").change(function () {
  161. var obj = '.json_encode($events).';
  162. $.each(obj, function(key,values) {
  163. if (values.method.length) {
  164. runJsCodeForEvent'.$htmlname.'(values);
  165. }
  166. });
  167. });
  168. function runJsCodeForEvent'.$htmlname.'(obj) {
  169. console.log("Run runJsCodeForEvent'.$htmlname.'");
  170. var id = $("#'.$htmlname.'").val();
  171. var method = obj.method;
  172. var url = obj.url;
  173. var htmlname = obj.htmlname;
  174. var showempty = obj.showempty;
  175. $.getJSON(url,
  176. {
  177. action: method,
  178. id: id,
  179. htmlname: htmlname,
  180. showempty: showempty
  181. },
  182. function(response) {
  183. $.each(obj.params, function(key,action) {
  184. if (key.length) {
  185. var num = response.num;
  186. if (num > 0) {
  187. $("#" + key).removeAttr(action);
  188. } else {
  189. $("#" + key).attr(action, action);
  190. }
  191. }
  192. });
  193. $("select#" + htmlname).html(response.value);
  194. if (response.num) {
  195. var selecthtml_str = response.value;
  196. var selecthtml_dom=$.parseHTML(selecthtml_str);
  197. $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
  198. } else {
  199. $("#inputautocomplete"+htmlname).val("");
  200. }
  201. $("select#" + htmlname).change(); /* Trigger event change */
  202. }
  203. );
  204. }
  205. });
  206. </script>';
  207. }
  208. // Contact and type
  209. print '<tr><td>' . $langs->trans("Contact") . '</td><td>';
  210. // If no socid, set to -1 to avoid full contacts list
  211. $selectedCompany = ($this->withfromsocid > 0) ? $this->withfromsocid : -1;
  212. $nbofcontacts = $form->select_contacts($selectedCompany, $this->withfromcontactid, 'contactid', 3, '', '', 0, 'minwidth200');
  213. $formcompany->selectTypeContact($ticketstatic, '', 'type', 'external', '', 0, 'maginleftonly');
  214. print '</td></tr>';
  215. } else {
  216. print '<tr><td class="titlefield"><input type="hidden" name="socid" value="' . $user->socid . '"/></td>';
  217. print '<td><input type="hidden" name="contactid" value="' . $user->contactid . '"/></td>';
  218. print '<td><input type="hidden" name="type" value="Z"/></td></tr>';
  219. }
  220. }
  221. // TITLE
  222. if ($this->withemail) {
  223. print '<tr><td class="titlefield"><label for="email"><span class="fieldrequired">' . $langs->trans("Email") . '</span></label></td><td>';
  224. print '<input class="text minwidth200" id="email" name="email" value="' . (GETPOST('email', 'alpha') ? GETPOST('email', 'alpha') : $subject) . '" />';
  225. print '</td></tr>';
  226. }
  227. // Si origin du ticket
  228. if (isset($this->param['origin']) && $this->param['originid'] > 0) {
  229. // Parse element/subelement (ex: project_task)
  230. $element = $subelement = $this->param['origin'];
  231. if (preg_match('/^([^_]+)_([^_]+)/i', $this->param['origin'], $regs)) {
  232. $element = $regs[1];
  233. $subelement = $regs[2];
  234. }
  235. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  236. $classname = ucfirst($subelement);
  237. $objectsrc = new $classname($this->db);
  238. $objectsrc->fetch(GETPOST('originid','int'));
  239. if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines')) {
  240. $objectsrc->fetch_lines();
  241. }
  242. $objectsrc->fetch_thirdparty();
  243. $newclassname = $classname;
  244. print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2"><input name="' . $subelement . 'id" value="' . GETPOST('originid') . '" type="hidden" />' . $objectsrc->getNomUrl(1) . '</td></tr>';
  245. }
  246. // Type
  247. print '<tr><td class="titlefield"><span class="fieldrequired"><label for="selecttype_code">' . $langs->trans("TicketTypeRequest") . '</span></label></td><td>';
  248. print $this->selectTypesTickets((GETPOST('type_code') ? GETPOST('type_code') : $this->type_code), 'type_code', '', '2');
  249. print '</td></tr>';
  250. // Category
  251. print '<tr><td><span class="fieldrequired"><label for="selectcategory_code">' . $langs->trans("TicketCategory") . '</span></label></td><td>';
  252. print $this->selectCategoriesTickets((GETPOST('category_code') ? GETPOST('category_code') : $this->category_code), 'category_code', '', '2');
  253. print '</td></tr>';
  254. // Severity
  255. print '<tr><td><span class="fieldrequired"><label for="selectseverity_code">' . $langs->trans("TicketSeverity") . '</span></label></td><td>';
  256. print $this->selectSeveritiesTickets((GETPOST('severity_code') ? GETPOST('severity_code') : $this->severity_code), 'severity_code', '', '2');
  257. print '</td></tr>';
  258. // Notify thirdparty at creation
  259. if (empty($this->ispublic))
  260. {
  261. print '<tr><td><label for="notify_tiers_at_create">' . $langs->trans("TicketNotifyTiersAtCreation") . '</label></td><td>';
  262. print '<input type="checkbox" id="notify_tiers_at_create" name="notify_tiers_at_create"'.($this->withnotifytiersatcreate?' checked="checked"':'').'>';
  263. print '</td></tr>';
  264. }
  265. // TITLE
  266. if ($this->withtitletopic) {
  267. print '<tr><td><label for="subject"><span class="fieldrequired">' . $langs->trans("Subject") . '</span></label></td><td>';
  268. // Réponse à un ticket : affichage du titre du thread en readonly
  269. if ($this->withtopicreadonly) {
  270. print $langs->trans('SubjectAnswerToTicket') . ' ' . $this->topic_title;
  271. print '</td></tr>';
  272. } else {
  273. if ($this->withthreadid > 0) {
  274. $subject = $langs->trans('SubjectAnswerToTicket') . ' ' . $this->withthreadid . ' : ' . $this->topic_title . '';
  275. }
  276. print '<input class="text" size="50" id="subject" name="subject" value="' . (GETPOST('subject', 'alpha') ? GETPOST('subject', 'alpha') : $subject) . '" />';
  277. print '</td></tr>';
  278. }
  279. }
  280. // MESSAGE
  281. $msg = GETPOST('message', 'alpha') ? GETPOST('message', 'alpha') : '';
  282. print '<tr><td><label for="message"><span class="fieldrequired">' . $langs->trans("Message") . '</span></label></td><td>';
  283. // If public form, display more information
  284. if ($this->ispublic) {
  285. print '<div class="warning">' . ($conf->global->TICKET_PUBLIC_TEXT_HELP_MESSAGE ? $conf->global->TICKET_PUBLIC_TEXT_HELP_MESSAGE : $langs->trans('TicketPublicPleaseBeAccuratelyDescribe')) . '</div>';
  286. }
  287. include_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  288. $uselocalbrowser = true;
  289. $doleditor = new DolEditor('message', GETPOST('message', 'alpha'), '100%', 250, 'dolibarr_details', 'In', true, $uselocalbrowser);
  290. $doleditor->Create();
  291. print '</td></tr>';
  292. // Attached files
  293. if (!empty($this->withfile)) {
  294. // Define list of attached files
  295. $listofpaths = array();
  296. $listofnames = array();
  297. $listofmimes = array();
  298. if (!empty($_SESSION["listofpaths"])) {
  299. $listofpaths = explode(';', $_SESSION["listofpaths"]);
  300. }
  301. if (!empty($_SESSION["listofnames"])) {
  302. $listofnames = explode(';', $_SESSION["listofnames"]);
  303. }
  304. if (!empty($_SESSION["listofmimes"])) {
  305. $listofmimes = explode(';', $_SESSION["listofmimes"]);
  306. }
  307. $out .= '<tr>';
  308. $out .= '<td width="180">' . $langs->trans("MailFile") . '</td>';
  309. $out .= '<td colspan="2">';
  310. // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
  311. $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">' . "\n";
  312. $out .= '<script type="text/javascript" language="javascript">';
  313. $out .= 'jQuery(document).ready(function () {';
  314. $out .= ' jQuery(".removedfile").click(function() {';
  315. $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
  316. $out .= ' });';
  317. $out .= '})';
  318. $out .= '</script>' . "\n";
  319. if (count($listofpaths)) {
  320. foreach ($listofpaths as $key => $val) {
  321. $out .= '<div id="attachfile_' . $key . '">';
  322. $out .= img_mime($listofnames[$key]) . ' ' . $listofnames[$key];
  323. if (!$this->withfilereadonly) {
  324. $out .= ' <input type="image" style="border: 0px;" src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/delete.png" value="' . ($key + 1) . '" class="removedfile" id="removedfile_' . $key . '" name="removedfile_' . $key . '" />';
  325. }
  326. $out .= '<br></div>';
  327. }
  328. } else {
  329. $out .= $langs->trans("NoAttachedFiles") . '<br>';
  330. }
  331. if ($this->withfile == 2) { // Can add other files
  332. $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="' . $langs->trans("Upload") . '" />';
  333. $out .= ' ';
  334. $out .= '<input type="submit" class="button" id="addfile" name="addfile" value="' . $langs->trans("MailingAddFile") . '" />';
  335. }
  336. $out .= "</td></tr>\n";
  337. print $out;
  338. }
  339. // Other attributes
  340. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $ticketstat, $action); // Note that $action and $object may have been modified by hook
  341. if (empty($reshook))
  342. {
  343. print $ticketstat->showOptionals($extrafields, 'edit');
  344. }
  345. print '</table>';
  346. if ($withdolfichehead) dol_fiche_end();
  347. print '<center>';
  348. print '<input class="button" type="submit" name="add_ticket" value="' . $langs->trans(($this->withthreadid > 0 ? "SendResponse" : "NewTicket")) . '" />';
  349. if ($this->withcancel) {
  350. print " &nbsp; &nbsp; ";
  351. print "<input class=\"button\" type=\"submit\" name=\"cancel\" value=\"" . $langs->trans("Cancel") . "\">";
  352. }
  353. print "</center>\n";
  354. print "</form>\n";
  355. print "<!-- End form TICKET -->\n";
  356. }
  357. /**
  358. * Return html list of tickets type
  359. *
  360. * @param string $selected Id du type pre-selectionne
  361. * @param string $htmlname Nom de la zone select
  362. * @param string $filtertype To filter on field type in llx_c_ticket_type (array('code'=>xx,'label'=>zz))
  363. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  364. * @param int $empty 1=peut etre vide, 0 sinon
  365. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  366. * @param int $maxlength Max length of label
  367. * @param string $morecss More CSS
  368. * @return void
  369. */
  370. public function selectTypesTickets($selected = '', $htmlname = 'tickettype', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss='')
  371. {
  372. global $langs, $user;
  373. $ticketstat = new Ticket($this->db);
  374. dol_syslog(get_class($this) . "::select_types_tickets " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
  375. $filterarray = array();
  376. if ($filtertype != '' && $filtertype != '-1') {
  377. $filterarray = explode(',', $filtertype);
  378. }
  379. $ticketstat->loadCacheTypesTickets();
  380. print '<select id="select' . $htmlname . '" class="flat minwidth100'.($morecss?' '.$morecss:'').'" name="' . $htmlname . '">';
  381. if ($empty) {
  382. print '<option value="">&nbsp;</option>';
  383. }
  384. if (is_array($ticketstat->cache_types_tickets) && count($ticketstat->cache_types_tickets)) {
  385. foreach ($ticketstat->cache_types_tickets as $id => $arraytypes) {
  386. // On passe si on a demande de filtrer sur des modes de paiments particuliers
  387. if (count($filterarray) && !in_array($arraytypes['type'], $filterarray)) {
  388. continue;
  389. }
  390. // We discard empty line if showempty is on because an empty line has already been output.
  391. if ($empty && empty($arraytypes['code'])) {
  392. continue;
  393. }
  394. if ($format == 0) {
  395. print '<option value="' . $id . '"';
  396. }
  397. if ($format == 1) {
  398. print '<option value="' . $arraytypes['code'] . '"';
  399. }
  400. if ($format == 2) {
  401. print '<option value="' . $arraytypes['code'] . '"';
  402. }
  403. if ($format == 3) {
  404. print '<option value="' . $id . '"';
  405. }
  406. // Si selected est text, on compare avec code, sinon avec id
  407. if (preg_match('/[a-z]/i', $selected) && $selected == $arraytypes['code']) {
  408. print ' selected="selected"';
  409. } elseif ($selected == $id) {
  410. print ' selected="selected"';
  411. } elseif ($arraytypes['use_default'] == "1" && !$empty) {
  412. print ' selected="selected"';
  413. }
  414. print '>';
  415. if ($format == 0) {
  416. $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
  417. }
  418. if ($format == 1) {
  419. $value = $arraytypes['code'];
  420. }
  421. if ($format == 2) {
  422. $value = ($maxlength ? dol_trunc($arraytypes['label'], $maxlength) : $arraytypes['label']);
  423. }
  424. if ($format == 3) {
  425. $value = $arraytypes['code'];
  426. }
  427. print $value ? $value : '&nbsp;';
  428. print '</option>';
  429. }
  430. }
  431. print '</select>';
  432. if ($user->admin && !$noadmininfo) {
  433. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  434. }
  435. print ajax_combobox('select'.$htmlname);
  436. }
  437. /**
  438. * Return html list of ticket categories
  439. *
  440. * @param string $selected Id categorie pre-selectionnée
  441. * @param string $htmlname Nom de la zone select
  442. * @param string $filtertype To filter on field type in llx_c_ticket_category (array('code'=>xx,'label'=>zz))
  443. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  444. * @param int $empty 1=peut etre vide, 0 sinon
  445. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  446. * @param int $maxlength Max length of label
  447. * @param string $morecss More CSS
  448. * @return void
  449. */
  450. public function selectCategoriesTickets($selected = '', $htmlname = 'ticketcategory', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss='')
  451. {
  452. global $langs, $user;
  453. $ticketstat = new Ticket($this->db);
  454. dol_syslog(get_class($this) . "::selectCategoryTickets " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
  455. $filterarray = array();
  456. if ($filtertype != '' && $filtertype != '-1') {
  457. $filterarray = explode(',', $filtertype);
  458. }
  459. $ticketstat->loadCacheCategoriesTickets();
  460. print '<select id="select' . $htmlname . '" class="flat minwidth100'.($morecss?' '.$morecss:'').'" name="' . $htmlname . '">';
  461. if ($empty) {
  462. print '<option value="">&nbsp;</option>';
  463. }
  464. if (is_array($ticketstat->cache_category_tickets) && count($ticketstat->cache_category_tickets)) {
  465. foreach ($ticketstat->cache_category_tickets as $id => $arraycategories) {
  466. // On passe si on a demande de filtrer sur des modes de paiments particuliers
  467. if (count($filterarray) && !in_array($arraycategories['type'], $filterarray)) {
  468. continue;
  469. }
  470. // We discard empty line if showempty is on because an empty line has already been output.
  471. if ($empty && empty($arraycategories['code'])) {
  472. continue;
  473. }
  474. if ($format == 0) {
  475. print '<option value="' . $id . '"';
  476. }
  477. if ($format == 1) {
  478. print '<option value="' . $arraycategories['code'] . '"';
  479. }
  480. if ($format == 2) {
  481. print '<option value="' . $arraycategories['code'] . '"';
  482. }
  483. if ($format == 3) {
  484. print '<option value="' . $id . '"';
  485. }
  486. // Si selected est text, on compare avec code, sinon avec id
  487. if (preg_match('/[a-z]/i', $selected) && $selected == $arraycategories['code']) {
  488. print ' selected="selected"';
  489. } elseif ($selected == $id) {
  490. print ' selected="selected"';
  491. } elseif ($arraycategories['use_default'] == "1" && !$empty) {
  492. print ' selected="selected"';
  493. }
  494. print '>';
  495. if ($format == 0) {
  496. $value = ($maxlength ? dol_trunc($arraycategories['label'], $maxlength) : $arraycategories['label']);
  497. }
  498. if ($format == 1) {
  499. $value = $arraycategories['code'];
  500. }
  501. if ($format == 2) {
  502. $value = ($maxlength ? dol_trunc($arraycategories['label'], $maxlength) : $arraycategories['label']);
  503. }
  504. if ($format == 3) {
  505. $value = $arraycategories['code'];
  506. }
  507. print $value ? $value : '&nbsp;';
  508. print '</option>';
  509. }
  510. }
  511. print '</select>';
  512. if ($user->admin && !$noadmininfo) {
  513. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  514. }
  515. print ajax_combobox('select'.$htmlname);
  516. }
  517. /**
  518. * Return html list of ticket severitys
  519. *
  520. * @param string $selected Id severity pre-selectionnée
  521. * @param string $htmlname Nom de la zone select
  522. * @param string $filtertype To filter on field type in llx_c_ticket_severity (array('code'=>xx,'label'=>zz))
  523. * @param int $format 0=id+libelle, 1=code+code, 2=code+libelle, 3=id+code
  524. * @param int $empty 1=peut etre vide, 0 sinon
  525. * @param int $noadmininfo 0=Add admin info, 1=Disable admin info
  526. * @param int $maxlength Max length of label
  527. * @param string $morecss More CSS
  528. * @return void
  529. */
  530. public function selectSeveritiesTickets($selected = '', $htmlname = 'ticketseverity', $filtertype = '', $format = 0, $empty = 0, $noadmininfo = 0, $maxlength = 0, $morecss='')
  531. {
  532. global $langs, $user;
  533. $ticketstat = new Ticket($this->db);
  534. dol_syslog(get_class($this) . "::selectSeveritiesTickets " . $selected . ", " . $htmlname . ", " . $filtertype . ", " . $format, LOG_DEBUG);
  535. $filterarray = array();
  536. if ($filtertype != '' && $filtertype != '-1') {
  537. $filterarray = explode(',', $filtertype);
  538. }
  539. $ticketstat->loadCacheSeveritiesTickets();
  540. print '<select id="select' . $htmlname . '" class="flat minwidth150'.($morecss?' '.$morecss:'').'" name="' . $htmlname . '">';
  541. if ($empty) {
  542. print '<option value="">&nbsp;</option>';
  543. }
  544. if (is_array($ticketstat->cache_severity_tickets) && count($ticketstat->cache_severity_tickets)) {
  545. foreach ($ticketstat->cache_severity_tickets as $id => $arrayseverities) {
  546. // On passe si on a demande de filtrer sur des modes de paiments particuliers
  547. if (count($filterarray) && !in_array($arrayseverities['type'], $filterarray)) {
  548. continue;
  549. }
  550. // We discard empty line if showempty is on because an empty line has already been output.
  551. if ($empty && empty($arrayseverities['code'])) {
  552. continue;
  553. }
  554. if ($format == 0) {
  555. print '<option value="' . $id . '"';
  556. }
  557. if ($format == 1) {
  558. print '<option value="' . $arrayseverities['code'] . '"';
  559. }
  560. if ($format == 2) {
  561. print '<option value="' . $arrayseverities['code'] . '"';
  562. }
  563. if ($format == 3) {
  564. print '<option value="' . $id . '"';
  565. }
  566. // Si selected est text, on compare avec code, sinon avec id
  567. if (preg_match('/[a-z]/i', $selected) && $selected == $arrayseverities['code']) {
  568. print ' selected="selected"';
  569. } elseif ($selected == $id) {
  570. print ' selected="selected"';
  571. } elseif ($arrayseverities['use_default'] == "1" && !$empty) {
  572. print ' selected="selected"';
  573. }
  574. print '>';
  575. if ($format == 0) {
  576. $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
  577. }
  578. if ($format == 1) {
  579. $value = $arrayseverities['code'];
  580. }
  581. if ($format == 2) {
  582. $value = ($maxlength ? dol_trunc($arrayseverities['label'], $maxlength) : $arrayseverities['label']);
  583. }
  584. if ($format == 3) {
  585. $value = $arrayseverities['code'];
  586. }
  587. print $value ? $value : '&nbsp;';
  588. print '</option>';
  589. }
  590. }
  591. print '</select>';
  592. if ($user->admin && !$noadmininfo) {
  593. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  594. }
  595. print ajax_combobox('select'.$htmlname);
  596. }
  597. /**
  598. * Show the form to add message on ticket
  599. *
  600. * @param string $width Width of form
  601. * @return void
  602. */
  603. public function showMessageForm($width = '40%')
  604. {
  605. global $conf, $langs, $user, $mysoc;
  606. // Load translation files required by the page
  607. $langs->loadLangs(array('other', 'mails'));
  608. $addfileaction = 'addfile';
  609. $form = new Form($this->db);
  610. $formmail = new FormMail($this->db);
  611. // Define list of attached files
  612. $listofpaths = array();
  613. $listofnames = array();
  614. $listofmimes = array();
  615. if (!empty($_SESSION["listofpaths"])) {
  616. $listofpaths = explode(';', $_SESSION["listofpaths"]);
  617. }
  618. if (!empty($_SESSION["listofnames"])) {
  619. $listofnames = explode(';', $_SESSION["listofnames"]);
  620. }
  621. if (!empty($_SESSION["listofmimes"])) {
  622. $listofmimes = explode(';', $_SESSION["listofmimes"]);
  623. }
  624. // Define output language
  625. $outputlangs = $langs;
  626. $newlang = '';
  627. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
  628. $newlang = $this->param['langsmodels'];
  629. }
  630. if (! empty($newlang)) {
  631. $outputlangs = new Translate("", $conf);
  632. $outputlangs->setDefaultLang($newlang);
  633. $outputlangs->load('other');
  634. }
  635. print "\n<!-- Begin message_form TICKETSUP -->\n";
  636. $send_email = GETPOST('send_email', 'int') ? GETPOST('send_email', 'int') : 0;
  637. // Example 1 : Adding jquery code
  638. print '<script type="text/javascript" language="javascript">
  639. jQuery(document).ready(function() {
  640. send_email=' . $send_email . ';
  641. if (send_email) {
  642. jQuery(".email_line").show();
  643. } else {
  644. jQuery(".email_line").hide();
  645. }
  646. jQuery("#send_msg_email").click(function() {
  647. if(jQuery(this).is(":checked")) {
  648. jQuery(".email_line").show();
  649. }
  650. else {
  651. jQuery(".email_line").hide();
  652. }
  653. });';
  654. print '});
  655. </script>';
  656. print '<form method="post" name="ticket" enctype="multipart/form-data" action="' . $this->param["returnurl"] . '">';
  657. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  658. print '<input type="hidden" name="action" value="' . $this->action . '">';
  659. foreach ($this->param as $key => $value) {
  660. print '<input type="hidden" name="' . $key . '" value="' . $value . '">';
  661. }
  662. // Get message template
  663. $model_id=0;
  664. if (array_key_exists('models_id', $this->param)) {
  665. $model_id=$this->param["models_id"];
  666. $arraydefaultmessage=$formmail->getEMailTemplate($this->db, $this->param["models"], $user, $outputlangs, $model_id);
  667. }
  668. $result = $formmail->fetchAllEMailTemplate($this->param["models"], $user, $outputlangs);
  669. if ($result<0) {
  670. setEventMessages($this->error, $this->errors, 'errors');
  671. }
  672. $modelmail_array=array();
  673. foreach ($formmail->lines_model as $line) {
  674. $modelmail_array[$line->id]=$line->label;
  675. }
  676. print '<table class="border" width="' . $width . '">';
  677. // External users can't send message email
  678. if ($user->rights->ticket->write && !$user->socid) {
  679. print '<tr><td width="30%"></td><td colspan="2">';
  680. $checkbox_selected = ( GETPOST('send_email') == "1" ? ' checked' : '');
  681. print '<input type="checkbox" name="send_email" value="1" id="send_msg_email" '.$checkbox_selected.'/> ';
  682. print '<label for="send_msg_email">' . $langs->trans('SendMessageByEmail') . '</label>';
  683. print '</td></tr>';
  684. // Zone to select its email template
  685. if (count($modelmail_array)>0) {
  686. print '<tr class="email_line"><td></td><td colspan="2"><div style="padding: 3px 0 3px 0">'."\n";
  687. print $langs->trans('SelectMailModel').': '.$formmail->selectarray('modelmailselected', $modelmail_array, $this->param['models_id'], 1);
  688. if ($user->admin) {
  689. print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
  690. }
  691. print ' &nbsp; ';
  692. print '<input class="button" type="submit" value="'.$langs->trans('Use').'" name="modelselected" id="modelselected">';
  693. print ' &nbsp; ';
  694. print '</div></td>';
  695. }
  696. // Substitution array
  697. if ($this->withsubstit) {
  698. print '<tr class="email_line"><td></td><td colspan="2">';
  699. $help="";
  700. foreach ($this->substit as $key => $val) {
  701. $help.=$key.' -> '.$langs->trans($val).'<br>';
  702. }
  703. print $form->textwithpicto($langs->trans("TicketMessageSubstitutionReplacedByGenericValues"), $help);
  704. print "</td></tr>";
  705. }
  706. if (! $user->socid) {
  707. print '<tr><td width="30%"></td><td>';
  708. $checkbox_selected = ( GETPOST('private_message') == "1" ? ' checked' : '');
  709. print '<input type="checkbox" name="private_message" value="1" id="private_message" '.$checkbox_selected.'/> ';
  710. print '<label for="private_message">' . $langs->trans('MarkMessageAsPrivate') . '</label>';
  711. print '</td><td align="center">';
  712. print $form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help');
  713. print '</td></tr>';
  714. }
  715. print '<tr class="email_line"><td width=20%">' . $langs->trans('Subject') . '</td>';
  716. $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
  717. print '<td colspan="2"><input type="text" class="text" size="80" name="subject" value="[' . $label_title . ' - ticket #' . $this->track_id . '] ' . $langs->trans('TicketNewMessage') . '" />';
  718. print '</td></tr>';
  719. // Destinataires
  720. print '<tr class="email_line"><td>' . $langs->trans('MailRecipients') . '</td><td colspan="2">';
  721. $ticketstat = new Ticket($this->db);
  722. $res = $ticketstat->fetch('', '', $this->track_id);
  723. if ($res) {
  724. // Retrieve email of all contacts (internal and external)
  725. $contacts = $ticketstat->getInfosTicketInternalContact();
  726. $contacts = array_merge($contacts, $ticketstat->getInfosTicketExternalContact());
  727. // Build array to display recipient list
  728. if (is_array($contacts) && count($contacts) > 0) {
  729. foreach ($contacts as $key => $info_sendto) {
  730. if ($info_sendto['email'] != '') {
  731. $sendto[] = dol_escape_htmltag(trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . "> (" . $info_sendto['libelle'] . ")");
  732. }
  733. }
  734. }
  735. if ($ticketstat->origin_email && !in_array($this->dao->origin_email, $sendto)) {
  736. $sendto[] = $ticketstat->origin_email . "(origin)";
  737. }
  738. if ($ticketstat->fk_soc > 0) {
  739. $ticketstat->socid = $ticketstat->fk_soc;
  740. $ticketstat->fetch_thirdparty();
  741. if (is_array($ticketstat->thirdparty->email) && !in_array($ticketstat->thirdparty->email, $sendto)) {
  742. $sendto[] = $ticketstat->thirdparty->email . '(' . $langs->trans('Customer') . ')';
  743. }
  744. }
  745. if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) {
  746. $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO . '(generic email)';
  747. }
  748. // Print recipient list
  749. if (is_array($sendto) && count($sendto) > 0) {
  750. print implode(', ', $sendto);
  751. } else {
  752. print '<div class="warning">' . $langs->trans('WarningNoEMailsAdded') . ' ' . $langs->trans('TicketGoIntoContactTab') . '</div>';
  753. }
  754. }
  755. print '</td></tr>';
  756. }
  757. // Intro
  758. // External users can't send message email
  759. if ($user->rights->ticket->write && !$user->socid) {
  760. $mail_intro = GETPOST('mail_intro') ? GETPOST('mail_intro') : $conf->global->TICKET_MESSAGE_MAIL_INTRO;
  761. print '<tr class="email_line"><td><label for="mail_intro">' . $langs->trans("TicketMessageMailIntro") . '</label>';
  762. print '</td><td>';
  763. include_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  764. $uselocalbrowser = true;
  765. $doleditor = new DolEditor('mail_intro', $mail_intro, '100%', 140, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70);
  766. $doleditor->Create();
  767. print '</td><td align="center">';
  768. print $form->textwithpicto('', $langs->trans("TicketMessageMailIntroHelp"), 1, 'help');
  769. print '</td></tr>';
  770. }
  771. // MESSAGE
  772. $defaultmessage="";
  773. if (is_array($arraydefaultmessage) && count($arraydefaultmessage) > 0 && $arraydefaultmessage->content) {
  774. $defaultmessage=$arraydefaultmessage->content;
  775. }
  776. $defaultmessage=str_replace('\n', "\n", $defaultmessage);
  777. // Deal with format differences between message and signature (text / HTML)
  778. if (dol_textishtml($defaultmessage) && !dol_textishtml($this->substit['__SIGNATURE__'])) {
  779. $this->substit['__SIGNATURE__'] = dol_nl2br($this->substit['__SIGNATURE__']);
  780. } elseif (!dol_textishtml($defaultmessage) && dol_textishtml($this->substit['__SIGNATURE__'])) {
  781. $defaultmessage = dol_nl2br($defaultmessage);
  782. }
  783. if (isset($_POST["message"]) && ! $_POST['modelselected']) {
  784. $defaultmessage=GETPOST('message');
  785. } else {
  786. $defaultmessage=make_substitutions($defaultmessage, $this->substit);
  787. // Clean first \n and br (to avoid empty line when CONTACTCIVNAME is empty)
  788. $defaultmessage=preg_replace("/^(<br>)+/", "", $defaultmessage);
  789. $defaultmessage=preg_replace("/^\n+/", "", $defaultmessage);
  790. }
  791. print '<tr><td><label for="message"><span class="fieldrequired">' . $langs->trans("Message") . '</span></label></td><td>';
  792. include_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  793. $doleditor = new DolEditor('message', $defaultmessage, '100%', 350, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70);
  794. $doleditor->Create();
  795. print '</td><td align="center">';
  796. if ($user->rights->ticket->write && !$user->socid) {
  797. print $form->textwithpicto('', $langs->trans("TicketMessageHelp"), 1, 'help');
  798. }
  799. print '</td></tr>';
  800. // Signature
  801. // External users can't send message email
  802. if ($user->rights->ticket->write && !$user->socid) {
  803. $mail_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE;
  804. print '<tr class="email_line"><td><label for="mail_intro">' . $langs->trans("TicketMessageMailSignature") . '</label>';
  805. print '</td><td>';
  806. include_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  807. $doleditor = new DolEditor('mail_signature', $mail_signature, '100%', 150, 'dolibarr_details', '', false, true, $conf->global->FCKEDITOR_ENABLE_SOCIETE, ROWS_2, 70);
  808. $doleditor->Create();
  809. print '</td><td align="center">';
  810. print $form->textwithpicto('', $langs->trans("TicketMessageMailSignatureHelp"), 1, 'help');
  811. print '</td></tr>';
  812. }
  813. // Attached files
  814. if (!empty($this->withfile)) {
  815. $out .= '<tr>';
  816. $out .= '<td width="180">' . $langs->trans("MailFile") . '</td>';
  817. $out .= '<td colspan="2">';
  818. // TODO Trick to have param removedfile containing nb of image to delete. But this does not works without javascript
  819. $out .= '<input type="hidden" class="removedfilehidden" name="removedfile" value="">' . "\n";
  820. $out .= '<script type="text/javascript" language="javascript">';
  821. $out .= 'jQuery(document).ready(function () {';
  822. $out .= ' jQuery(".removedfile").click(function() {';
  823. $out .= ' jQuery(".removedfilehidden").val(jQuery(this).val());';
  824. $out .= ' });';
  825. $out .= '})';
  826. $out .= '</script>' . "\n";
  827. if (count($listofpaths)) {
  828. foreach ($listofpaths as $key => $val) {
  829. $out .= '<div id="attachfile_' . $key . '">';
  830. $out .= img_mime($listofnames[$key]) . ' ' . $listofnames[$key];
  831. if (!$this->withfilereadonly) {
  832. $out .= ' <input type="image" style="border: 0px;" src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/delete.png" value="' . ($key + 1) . '" class="removedfile" id="removedfile_' . $key . '" name="removedfile_' . $key . '" />';
  833. }
  834. $out .= '<br></div>';
  835. }
  836. } else {
  837. $out .= $langs->trans("NoAttachedFiles") . '<br>';
  838. }
  839. if ($this->withfile == 2) { // Can add other files
  840. $out .= '<input type="file" class="flat" id="addedfile" name="addedfile" value="' . $langs->trans("Upload") . '" />';
  841. $out .= ' ';
  842. $out .= '<input type="submit" class="button" id="' . $addfileaction . '" name="' . $addfileaction . '" value="' . $langs->trans("MailingAddFile") . '" />';
  843. }
  844. $out .= "</td></tr>\n";
  845. print $out;
  846. }
  847. print '<tr><td colspan="3">';
  848. print '<center>';
  849. print '<input class="button" type="submit" name="btn_add_message" value="' . $langs->trans("AddMessage") . '" />';
  850. if ($this->withcancel) {
  851. print " &nbsp; &nbsp; ";
  852. print "<input class=\"button\" type=\"submit\" name=\"cancel\" value=\"" . $langs->trans("Cancel") . "\">";
  853. }
  854. print "</center>\n";
  855. print '</td></tr>';
  856. print '</table>';
  857. print "</form>\n";
  858. print "<!-- End form TICKET -->\n";
  859. }
  860. }