create_ticket.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <?php
  2. /* Copyright (C) 2013-2016 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 3 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 <https://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file htdocs/public/ticket/create_ticket.php
  20. * \ingroup ticket
  21. * \brief Display public form to add new ticket
  22. */
  23. if (!defined('NOREQUIREUSER')) {
  24. define('NOREQUIREUSER', '1');
  25. }
  26. if (!defined('NOTOKENRENEWAL')) {
  27. define('NOTOKENRENEWAL', '1');
  28. }
  29. if (!defined('NOREQUIREMENU')) {
  30. define('NOREQUIREMENU', '1');
  31. }
  32. if (!defined('NOREQUIREHTML')) {
  33. define('NOREQUIREHTML', '1');
  34. }
  35. if (!defined('NOLOGIN')) {
  36. define("NOLOGIN", 1); // This means this output page does not require to be logged.
  37. }
  38. if (!defined('NOCSRFCHECK')) {
  39. define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
  40. }
  41. if (!defined('NOIPCHECK')) {
  42. define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
  43. }
  44. if (!defined('NOBROWSERNOTIF')) {
  45. define('NOBROWSERNOTIF', '1');
  46. }
  47. // For MultiCompany module.
  48. // Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
  49. $entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
  50. if (is_numeric($entity)) {
  51. define("DOLENTITY", $entity);
  52. }
  53. require '../../main.inc.php';
  54. require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php';
  55. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formticket.class.php';
  56. require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
  57. require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
  58. require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
  59. require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
  60. require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
  61. require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  62. // Load translation files required by the page
  63. $langs->loadLangs(array('companies', 'other', 'mails', 'ticket'));
  64. // Get parameters
  65. $id = GETPOST('id', 'int');
  66. $msg_id = GETPOST('msg_id', 'int');
  67. $action = GETPOST('action', 'aZ09');
  68. // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
  69. $hookmanager->initHooks(array('publicnewticketcard', 'globalcard'));
  70. $object = new Ticket($db);
  71. $extrafields = new ExtraFields($db);
  72. $extrafields->fetch_name_optionals_label($object->table_element);
  73. if (empty($conf->ticket->enabled)) {
  74. accessforbidden('', 0, 0, 1);
  75. }
  76. /*
  77. * Actions
  78. */
  79. $parameters = array(
  80. 'id' => $id,
  81. );
  82. // Note that $action and $object may have been modified by some hooks
  83. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
  84. if ($reshook < 0) {
  85. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  86. }
  87. // Add file in email form
  88. if (empty($reshook) && GETPOST('addfile', 'alpha') && !GETPOST('save', 'alpha')) {
  89. ////$res = $object->fetch('','',GETPOST('track_id'));
  90. ////if($res > 0)
  91. ////{
  92. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  93. // Set tmp directory TODO Use a dedicated directory for temp mails files
  94. $vardir = $conf->ticket->dir_output;
  95. $upload_dir_tmp = $vardir.'/temp/'.session_id();
  96. if (!dol_is_dir($upload_dir_tmp)) {
  97. dol_mkdir($upload_dir_tmp);
  98. }
  99. dol_add_file_process($upload_dir_tmp, 0, 0, 'addedfile', '', null, '', 0);
  100. $action = 'create_ticket';
  101. ////}
  102. }
  103. // Remove file
  104. if (empty($reshook) && GETPOST('removedfile', 'alpha') && !GETPOST('save', 'alpha')) {
  105. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  106. // Set tmp directory
  107. $vardir = $conf->ticket->dir_output.'/';
  108. $upload_dir_tmp = $vardir.'/temp/'.session_id();
  109. // TODO Delete only files that was uploaded from email form
  110. dol_remove_file_process(GETPOST('removedfile'), 0, 0);
  111. $action = 'create_ticket';
  112. }
  113. if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) {
  114. $error = 0;
  115. $origin_email = GETPOST('email', 'alpha');
  116. if (empty($origin_email)) {
  117. $error++;
  118. array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Email")));
  119. $action = '';
  120. } else {
  121. // Search company saved with email
  122. $searched_companies = $object->searchSocidByEmail($origin_email, '0');
  123. // Chercher un contact existant avec cette adresse email
  124. // Le premier contact trouvé est utilisé pour déterminer le contact suivi
  125. $contacts = $object->searchContactByEmail($origin_email);
  126. // Option to require email exists to create ticket
  127. if (!empty($conf->global->TICKET_EMAIL_MUST_EXISTS) && !$contacts[0]->socid) {
  128. $error++;
  129. array_push($object->errors, $langs->trans("ErrorEmailMustExistToCreateTicket"));
  130. $action = '';
  131. }
  132. }
  133. if (!GETPOST("subject", "restricthtml")) {
  134. $error++;
  135. array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")));
  136. $action = '';
  137. } elseif (!GETPOST("message", "restricthtml")) {
  138. $error++;
  139. array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message")));
  140. $action = '';
  141. }
  142. // Check email address
  143. if (!isValidEmail($origin_email)) {
  144. $error++;
  145. array_push($object->errors, $langs->trans("ErrorBadEmailAddress", $langs->transnoentities("email")));
  146. $action = '';
  147. }
  148. // Check Captcha code if is enabled
  149. if (!empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) {
  150. $sessionkey = 'dol_antispam_value';
  151. $ok = (array_key_exists($sessionkey, $_SESSION) === true && (strtolower($_SESSION[$sessionkey]) === strtolower(GETPOST('code', 'restricthtml'))));
  152. if (!$ok) {
  153. $error++;
  154. array_push($object->errors, $langs->trans("ErrorBadValueForCode"));
  155. $action = '';
  156. }
  157. }
  158. if (!$error) {
  159. $object->db->begin();
  160. $object->track_id = generate_random_id(16);
  161. $object->subject = GETPOST("subject", "restricthtml");
  162. $object->message = GETPOST("message", "restricthtml");
  163. $object->origin_email = $origin_email;
  164. $object->type_code = GETPOST("type_code", 'aZ09');
  165. $object->category_code = GETPOST("category_code", 'aZ09');
  166. $object->severity_code = GETPOST("severity_code", 'aZ09');
  167. if (is_array($searched_companies)) {
  168. $object->fk_soc = $searched_companies[0]->id;
  169. }
  170. if (is_array($contacts) and count($contacts) > 0) {
  171. $object->fk_soc = $contacts[0]->socid;
  172. $usertoassign = $contacts[0]->id;
  173. }
  174. $ret = $extrafields->setOptionalsFromPost(null, $object);
  175. // Generate new ref
  176. $object->ref = $object->getDefaultRef();
  177. if (!is_object($user)) {
  178. $user = new User($db);
  179. }
  180. $object->context['disableticketemail'] = 1; // Disable emails sent by ticket trigger when creation is done from this page, emails are already sent later
  181. $id = $object->create($user);
  182. if ($id <= 0) {
  183. $error++;
  184. $errors = ($object->error ? array($object->error) : $object->errors);
  185. array_push($object->errors, $object->error ? array($object->error) : $object->errors);
  186. $action = 'create_ticket';
  187. }
  188. if (!$error && $id > 0) {
  189. if ($usertoassign > 0) {
  190. $object->add_contact($usertoassign, "SUPPORTCLI", 'external', 0);
  191. }
  192. }
  193. if (!$error) {
  194. $object->db->commit();
  195. $action = "infos_success";
  196. } else {
  197. $object->db->rollback();
  198. setEventMessages($object->error, $object->errors, 'errors');
  199. $action = 'create_ticket';
  200. }
  201. if (!$error) {
  202. $res = $object->fetch($id);
  203. if ($res) {
  204. // Create form object
  205. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
  206. include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  207. $formmail = new FormMail($db);
  208. // Init to avoid errors
  209. $filepath = array();
  210. $filename = array();
  211. $mimetype = array();
  212. $attachedfiles = $formmail->get_attached_files();
  213. $filepath = $attachedfiles['paths'];
  214. $filename = $attachedfiles['names'];
  215. $mimetype = $attachedfiles['mimes'];
  216. // Send email to customer
  217. $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubject', $object->ref, $object->track_id);
  218. $message = ($conf->global->TICKET_MESSAGE_MAIL_NEW ? $conf->global->TICKET_MESSAGE_MAIL_NEW : $langs->transnoentities('TicketNewEmailBody')).'<br><br>';
  219. $message .= $langs->transnoentities('TicketNewEmailBodyInfosTicket').'<br>';
  220. $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id;
  221. $infos_new_ticket = $langs->transnoentities('TicketNewEmailBodyInfosTrackId', '<a href="'.$url_public_ticket.'" rel="nofollow noopener">'.$object->track_id.'</a>').'<br>';
  222. $infos_new_ticket .= $langs->transnoentities('TicketNewEmailBodyInfosTrackUrl').'<br><br>';
  223. $message .= $infos_new_ticket;
  224. $message .= $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE ? $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE : $langs->transnoentities('TicketMessageMailSignatureText');
  225. $sendto = GETPOST('email', 'alpha');
  226. $from = $conf->global->MAIN_INFO_SOCIETE_NOM.' <'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
  227. $replyto = $from;
  228. $sendtocc = '';
  229. $deliveryreceipt = 0;
  230. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  231. $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
  232. $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
  233. }
  234. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  235. $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', 'tic'.$object->id, '', 'ticket');
  236. if ($mailfile->error || $mailfile->errors) {
  237. setEventMessages($mailfile->error, $mailfile->errors, 'errors');
  238. } else {
  239. $result = $mailfile->sendfile();
  240. }
  241. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  242. $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
  243. }
  244. // Send email to TICKET_NOTIFICATION_EMAIL_TO
  245. $sendto = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
  246. if ($sendto) {
  247. $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubjectAdmin', $object->ref, $object->track_id);
  248. $message_admin = $langs->transnoentities('TicketNewEmailBodyAdmin', $object->track_id).'<br><br>';
  249. $message_admin .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
  250. $message_admin .= '<li>'.$langs->trans('Type').' : '.$object->type_label.'</li>';
  251. $message_admin .= '<li>'.$langs->trans('Category').' : '.$object->category_label.'</li>';
  252. $message_admin .= '<li>'.$langs->trans('Severity').' : '.$object->severity_label.'</li>';
  253. $message_admin .= '<li>'.$langs->trans('From').' : '.$object->origin_email.'</li>';
  254. // Extrafields
  255. $extrafields->fetch_name_optionals_label($object->table_element);
  256. if (is_array($object->array_options) && count($object->array_options) > 0) {
  257. foreach ($object->array_options as $key => $value) {
  258. $key = substr($key, 8); // remove "options_"
  259. $message_admin .= '<li>'.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' : '.$extrafields->showOutputField($key, $value, '', $object->table_element).'</li>';
  260. }
  261. }
  262. $message_admin .= '</ul>';
  263. $message_admin .= '<p>'.$langs->trans('Message').' : <br>'.$object->message.'</p>';
  264. $message_admin .= '<p><a href="'.dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id.'" rel="nofollow noopener">'.$langs->trans('SeeThisTicketIntomanagementInterface').'</a></p>';
  265. $from = $conf->global->MAIN_INFO_SOCIETE_NOM.' <'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
  266. $replyto = $from;
  267. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  268. $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
  269. $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
  270. }
  271. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  272. $mailfile = new CMailFile($subject, $sendto, $from, $message_admin, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', 'tic'.$object->id, '', 'ticket');
  273. if ($mailfile->error || $mailfile->errors) {
  274. setEventMessages($mailfile->error, $mailfile->errors, 'errors');
  275. } else {
  276. $result = $mailfile->sendfile();
  277. }
  278. if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
  279. $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
  280. }
  281. }
  282. }
  283. // Copy files into ticket directory
  284. $destdir = $conf->ticket->dir_output.'/'.$object->ref;
  285. if (!dol_is_dir($destdir)) {
  286. dol_mkdir($destdir);
  287. }
  288. foreach ($filename as $i => $val) {
  289. dol_move($filepath[$i], $destdir.'/'.$filename[$i], 0, 1);
  290. $formmail->remove_attached_files($i);
  291. }
  292. //setEventMessages($langs->trans('YourTicketSuccessfullySaved'), null, 'mesgs');
  293. // Make a redirect to avoid to have ticket submitted twice if we make back
  294. $messagetoshow = $langs->trans('MesgInfosPublicTicketCreatedWithTrackId', '{s1}', '{s2}');
  295. $messagetoshow = str_replace(array('{s1}', '{s2}'), array('<strong>'.$object->track_id.'</strong>', '<strong>'.$object->ref.'</strong>'), $messagetoshow);
  296. setEventMessages($messagetoshow, null, 'warnings');
  297. setEventMessages($langs->trans('PleaseRememberThisId'), null, 'warnings');
  298. header("Location: index.php".(!empty($entity) && !empty($conf->multicompany->enabled)?'?entity='.$entity:''));
  299. exit;
  300. }
  301. } else {
  302. setEventMessages($object->error, $object->errors, 'errors');
  303. }
  304. }
  305. /*
  306. * View
  307. */
  308. $form = new Form($db);
  309. $formticket = new FormTicket($db);
  310. if (!$conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) {
  311. print '<div class="error">'.$langs->trans('TicketPublicInterfaceForbidden').'</div>';
  312. $db->close();
  313. exit();
  314. }
  315. $arrayofjs = array();
  316. $arrayofcss = array('/opensurvey/css/style.css', '/ticket/css/styles.css.php');
  317. llxHeaderTicket($langs->trans("CreateTicket"), "", 0, 0, $arrayofjs, $arrayofcss);
  318. print '<div class="ticketpublicarea">';
  319. if ($action != "infos_success") {
  320. $formticket->withfromsocid = isset($socid) ? $socid : $user->socid;
  321. $formticket->withtitletopic = 1;
  322. $formticket->withcompany = 0;
  323. $formticket->withusercreate = 1;
  324. $formticket->fk_user_create = 0;
  325. $formticket->withemail = 1;
  326. $formticket->ispublic = 1;
  327. $formticket->withfile = 2;
  328. $formticket->action = 'create_ticket';
  329. $formticket->param = array('returnurl' => $_SERVER['PHP_SELF'].($conf->entity > 1 ? '?entity='.$conf->entity : ''));
  330. print load_fiche_titre($langs->trans('NewTicket'), '', '', 0, 0, 'marginleftonly');
  331. if (empty($conf->global->TICKET_NOTIFICATION_EMAIL_FROM)) {
  332. $langs->load("errors");
  333. print '<div class="error">';
  334. print $langs->trans("ErrorFieldRequired", $langs->transnoentities("TicketEmailNotificationFrom")).'<br>';
  335. print $langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentities("Ticket"));
  336. print '</div>';
  337. } else {
  338. print '<div class="info marginleftonly marginrightonly">'.$langs->trans('TicketPublicInfoCreateTicket').'</div>';
  339. $formticket->showForm(0, 'edit', 1);
  340. }
  341. }
  342. print '</div>';
  343. // End of page
  344. htmlPrintOnlinePaymentFooter($mysoc, $langs, 1, $suffix, $object);
  345. llxFooter('', 'public');
  346. $db->close();