list.php 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. <?php
  2. /* Copyright (C) 2013-2018 Jean-François FERRY <hello@librethic.io>
  3. * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
  4. * Copyright (C) 2018 Regis Houssin <regis.houssin@inodbox.com>
  5. * Copyright (C) 2019-2021 Juanjo Menent <jmenent@2byte.es>
  6. * Copyright (C) 2019-2020 Laurent Destailleur <eldy@users.sourceforge.net>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/ticket/list.php
  23. * \ingroup ticket
  24. * \brief List page for tickets
  25. */
  26. require '../main.inc.php';
  27. require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formticket.class.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  30. require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
  31. require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  32. include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
  33. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
  34. include_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
  35. // Load translation files required by the page
  36. $langs->loadLangs(array("ticket", "companies", "other", "projects"));
  37. // Get parameters
  38. $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
  39. $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
  40. $show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ?
  41. $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
  42. $cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
  43. $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
  44. $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'ticketlist'; // To manage different context of search
  45. $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
  46. $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
  47. $id = GETPOST('id', 'int');
  48. $msg_id = GETPOST('msg_id', 'int');
  49. $socid = GETPOST('socid', 'int');
  50. $projectid = GETPOST('projectid', 'int');
  51. $project_ref = GETPOST('project_ref', 'alpha');
  52. $search_societe = GETPOST('search_societe', 'alpha');
  53. $search_fk_project = GETPOST('search_fk_project', 'int') ?GETPOST('search_fk_project', 'int') : GETPOST('projectid', 'int');
  54. $search_fk_status = GETPOST('search_fk_statut', 'array');
  55. $search_date_start = dol_mktime(0, 0, 0, GETPOST('search_date_startmonth', 'int'), GETPOST('search_date_startday', 'int'), GETPOST('search_date_startyear', 'int'));
  56. $search_date_end = dol_mktime(23, 59, 59, GETPOST('search_date_endmonth', 'int'), GETPOST('search_date_endday', 'int'), GETPOST('search_date_endyear', 'int'));
  57. $search_dateread_start = dol_mktime(0, 0, 0, GETPOST('search_dateread_startmonth', 'int'), GETPOST('search_dateread_startday', 'int'), GETPOST('search_dateread_startyear', 'int'));
  58. $search_dateread_end = dol_mktime(23, 59, 59, GETPOST('search_dateread_endmonth', 'int'), GETPOST('search_dateread_endday', 'int'), GETPOST('search_dateread_endyear', 'int'));
  59. $search_dateclose_start = dol_mktime(0, 0, 0, GETPOST('search_dateclose_startmonth', 'int'), GETPOST('search_dateclose_startday', 'int'), GETPOST('search_dateclose_startyear', 'int'));
  60. $search_dateclose_end = dol_mktime(23, 59, 59, GETPOST('search_dateclose_endmonth', 'int'), GETPOST('search_dateclose_endday', 'int'), GETPOST('search_dateclose_endyear', 'int'));
  61. $mode = GETPOST('mode', 'alpha');
  62. // Load variable for pagination
  63. $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
  64. $sortfield = GETPOST('sortfield', 'aZ09comma');
  65. $sortorder = GETPOST('sortorder', 'aZ09comma');
  66. $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
  67. if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
  68. // If $page is not defined, or '' or -1 or if we click on clear filters
  69. $page = 0;
  70. }
  71. $offset = $limit * $page;
  72. $pageprev = $page - 1;
  73. $pagenext = $page + 1;
  74. // Initialize technical objects
  75. $object = new Ticket($db);
  76. $extrafields = new ExtraFields($db);
  77. $diroutputmassaction = $conf->ticket->dir_output.'/temp/massgeneration/'.$user->id;
  78. if ($socid > 0) {
  79. $hookmanager->initHooks(array('thirdpartyticket'));
  80. } elseif ($projectid > 0) {
  81. $hookmanager->initHooks(array('projectticket'));
  82. } else {
  83. $hookmanager->initHooks(array('ticketlist'));
  84. }
  85. // Fetch optionals attributes and labels
  86. $extrafields->fetch_name_optionals_label($object->table_element);
  87. $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
  88. // Default sort order (if not yet defined by previous GETPOST)
  89. if (!$sortfield) {
  90. $sortfield = "t.datec";
  91. }
  92. if (!$sortorder) {
  93. $sortorder = "DESC";
  94. }
  95. if (GETPOST('search_fk_status', 'alpha') == 'non_closed') {
  96. $_GET['search_fk_statut'][] = 'openall'; // For backward compatibility
  97. }
  98. // Initialize array of search criterias
  99. $search_all = (GETPOSTISSET("search_all") ? GETPOST("search_all", 'alpha') : GETPOST('sall'));
  100. $search = array();
  101. foreach ($object->fields as $key => $val) {
  102. if (GETPOST('search_'.$key, 'alpha') !== '') {
  103. $search[$key] = GETPOST('search_'.$key, 'alpha');
  104. }
  105. if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
  106. $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int'));
  107. $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int'));
  108. }
  109. }
  110. // List of fields to search into when doing a "search in all"
  111. $fieldstosearchall = array();
  112. foreach ($object->fields as $key => $val) {
  113. if (!empty($val['searchall'])) {
  114. $fieldstosearchall['t.'.$key] = $val['label'];
  115. }
  116. }
  117. $fieldstosearchall['s.name_alias'] = "AliasNameShort";
  118. $fieldstosearchall['s.zip'] = "Zip";
  119. $fieldstosearchall['s.town'] = "Town";
  120. // Definition of array of fields for columns
  121. $arrayfields = array();
  122. foreach ($object->fields as $key => $val) {
  123. // If $val['visible']==0, then we never show the field
  124. if (!empty($val['visible'])) {
  125. $visible = (int) dol_eval($val['visible'], 1);
  126. $arrayfields['t.'.$key] = array(
  127. 'label'=>$val['label'],
  128. 'checked'=>(($visible < 0) ? 0 : 1),
  129. 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)),
  130. 'position'=>$val['position'],
  131. 'help'=> isset($val['help']) ? $val['help'] : ''
  132. );
  133. }
  134. }
  135. // Extra fields
  136. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
  137. $object->fields = dol_sort_array($object->fields, 'position');
  138. $arrayfields = dol_sort_array($arrayfields, 'position');
  139. // Security check
  140. if (!$user->rights->ticket->read) {
  141. accessforbidden();
  142. }
  143. // Store current page url
  144. $url_page_current = dol_buildpath('/ticket/list.php', 1);
  145. if ($project_ref) {
  146. $tmpproject = new Project($db);
  147. $tmpproject->fetch(0, $project_ref);
  148. $projectid = $tmpproject->id;
  149. $search_fk_project = $projectid;
  150. }
  151. $permissiontoread = $user->rights->ticket->read;
  152. $permissiontoadd = $user->rights->ticket->write;
  153. $permissiontodelete = $user->rights->ticket->delete;
  154. $error = 0;
  155. /*
  156. * Actions
  157. */
  158. if (GETPOST('cancel', 'alpha')) {
  159. $action = 'list'; $massaction = '';
  160. }
  161. if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
  162. $massaction = '';
  163. }
  164. $parameters = array();
  165. if ($socid > 0) {
  166. $parameters['socid'] = $socid;
  167. }
  168. if ($projectid > 0) {
  169. $parameters['projectid'] = $projectid;
  170. }
  171. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  172. if ($reshook < 0) {
  173. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  174. }
  175. if (empty($reshook)) {
  176. // Selection of new fields
  177. include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
  178. // Purge search criteria
  179. if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
  180. foreach ($object->fields as $key => $val) {
  181. $search[$key] = '';
  182. }
  183. $toselect = '';
  184. $search_array_options = array();
  185. $search_date_start = '';
  186. $search_date_end = '';
  187. $search_dateread_start = '';
  188. $search_dateread_end = '';
  189. $search_dateclose_start = '';
  190. $search_dateclose_end = '';
  191. }
  192. if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
  193. || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
  194. $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
  195. }
  196. // Mass actions
  197. $objectclass = 'Ticket';
  198. $objectlabel = 'Ticket';
  199. $uploaddir = $conf->ticket->dir_output;
  200. include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
  201. // Close records
  202. if (!$error && $massaction == 'close' && $permissiontoadd) {
  203. $objecttmp = new $objectclass($db);
  204. if (!$error) {
  205. $db->begin();
  206. $nbok = 0;
  207. foreach ($toselect as $toselectid) {
  208. $result = $objecttmp->fetch($toselectid);
  209. if ($result > 0) {
  210. $result = $objecttmp->close($user);
  211. if ($result < 0) {
  212. setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
  213. $error++;
  214. break;
  215. } else {
  216. $nbok++;
  217. }
  218. } else {
  219. setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
  220. $error++;
  221. break;
  222. }
  223. }
  224. if (!$error) {
  225. if ($nbok > 1) {
  226. setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
  227. } else {
  228. setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
  229. }
  230. $db->commit();
  231. } else {
  232. $db->rollback();
  233. }
  234. //var_dump($listofobjectthirdparties);exit;
  235. }
  236. }
  237. // Reopen records
  238. if (!$error && $massaction == 'reopen' && $permissiontoadd) {
  239. $objecttmp = new $objectclass($db);
  240. if (!$error) {
  241. $db->begin();
  242. $nbok = 0;
  243. foreach ($toselect as $toselectid) {
  244. $result = $objecttmp->fetch($toselectid);
  245. if ($result > 0) {
  246. if ($objecttmp->status == Ticket::STATUS_CLOSED || $objecttmp->status == Ticket::STATUS_CANCELED) {
  247. $result = $objecttmp->setStatut(Ticket::STATUS_ASSIGNED);
  248. if ($result < 0) {
  249. setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
  250. $error++;
  251. break;
  252. } else {
  253. $nbok++;
  254. }
  255. } else {
  256. $langs->load("errors");
  257. setEventMessages($langs->trans("ErrorObjectMustHaveStatusClosedToBeReOpened", $objecttmp->ref), null, 'errors');
  258. $error++;
  259. break;
  260. }
  261. } else {
  262. setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
  263. $error++;
  264. break;
  265. }
  266. }
  267. if (!$error) {
  268. if ($nbok > 1) {
  269. setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
  270. } else {
  271. setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
  272. }
  273. $db->commit();
  274. } else {
  275. $db->rollback();
  276. }
  277. //var_dump($listofobjectthirdparties);exit;
  278. }
  279. }
  280. }
  281. /*
  282. * View
  283. */
  284. $form = new Form($db);
  285. $formTicket = new FormTicket($db);
  286. $now = dol_now();
  287. $user_temp = new User($db);
  288. $socstatic = new Societe($db);
  289. $help_url = '';
  290. $title = $langs->trans('TicketList');
  291. // Build and execute select
  292. // --------------------------------------------------------------------
  293. $sql = 'SELECT ';
  294. foreach ($object->fields as $key => $val) {
  295. $sql .= 't.'.$key.', ';
  296. }
  297. // Add fields from extrafields
  298. if (!empty($extrafields->attributes[$object->table_element]['label'])) {
  299. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  300. $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.' as options_'.$key.', ' : '');
  301. }
  302. }
  303. // Add fields from hooks
  304. $parameters = array();
  305. $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook
  306. $sql .= $hookmanager->resPrint;
  307. $sql = preg_replace('/, $/', '', $sql);
  308. $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
  309. if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
  310. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
  311. }
  312. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON (t.fk_soc = s.rowid)";
  313. $sql .= " WHERE t.entity IN (".getEntity($object->element).")";
  314. if ($socid > 0) {
  315. $sql .= " AND t.fk_soc = ".((int) $socid);
  316. }
  317. foreach ($search as $key => $val) {
  318. if ($key == 'fk_statut' && !empty($search['fk_statut'])) {
  319. $newarrayofstatus = array();
  320. foreach ($search['fk_statut'] as $key2 => $val2) {
  321. if (in_array($val2, array('openall', 'closeall'))) {
  322. continue;
  323. }
  324. $newarrayofstatus[] = $val2;
  325. }
  326. if ($search['fk_statut'] == 'openall' || in_array('openall', $search['fk_statut'])) {
  327. $newarrayofstatus[] = Ticket::STATUS_NOT_READ;
  328. $newarrayofstatus[] = Ticket::STATUS_READ;
  329. $newarrayofstatus[] = Ticket::STATUS_ASSIGNED;
  330. $newarrayofstatus[] = Ticket::STATUS_IN_PROGRESS;
  331. $newarrayofstatus[] = Ticket::STATUS_NEED_MORE_INFO;
  332. $newarrayofstatus[] = Ticket::STATUS_WAITING;
  333. }
  334. if ($search['fk_statut'] == 'closeall' || in_array('closeall', $search['fk_statut'])) {
  335. $newarrayofstatus[] = Ticket::STATUS_CLOSED;
  336. $newarrayofstatus[] = Ticket::STATUS_CANCELED;
  337. }
  338. if (count($newarrayofstatus)) {
  339. $sql .= natural_search($key, join(',', $newarrayofstatus), 2);
  340. }
  341. continue;
  342. }
  343. if ($key == 'fk_user_assign' || $key == 'fk_user_create' || $key == 'fk_project') {
  344. if ($search[$key] > 0) {
  345. $sql .= natural_search($key, $search[$key], 2);
  346. }
  347. continue;
  348. }
  349. $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
  350. if ($search[$key] != '') {
  351. $sql .= natural_search($key, $search[$key], $mode_search);
  352. }
  353. }
  354. if ($search_all) {
  355. $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
  356. }
  357. if ($search_societe) {
  358. $sql .= natural_search('s.nom', $search_societe);
  359. }
  360. if ($search_fk_project > 0) {
  361. $sql .= natural_search('fk_project', $search_fk_project, 2);
  362. }
  363. if ($search_date_start) {
  364. $sql .= " AND t.datec >= '".$db->idate($search_date_start)."'";
  365. }
  366. if ($search_date_end) {
  367. $sql .= " AND t.datec <= '".$db->idate($search_date_end)."'";
  368. }
  369. if ($search_dateread_start) {
  370. $sql .= " AND t.date_read >= '".$db->idate($search_dateread_start)."'";
  371. }
  372. if ($search_dateread_end) {
  373. $sql .= " AND t.date_read <= '".$db->idate($search_dateread_end)."'";
  374. }
  375. if ($search_dateclose_start) {
  376. $sql .= " AND t.date_close >= '".$db->idate($search_dateclose_start)."'";
  377. }
  378. if ($search_dateclose_end) {
  379. $sql .= " AND t.date_close <= '".$db->idate($search_dateclose_end)."'";
  380. }
  381. if (!$user->socid && ($mode == "mine" || (!$user->admin && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY))) {
  382. $sql .= " AND (t.fk_user_assign = ".((int) $user->id);
  383. if (empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY)) {
  384. $sql .= " OR t.fk_user_create = ".((int) $user->id);
  385. }
  386. $sql .= ")";
  387. }
  388. // Add where from extra fields
  389. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
  390. // Add where from hooks
  391. $parameters = array();
  392. $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
  393. $sql .= $hookmanager->resPrint;
  394. $sql .= $db->order($sortfield, $sortorder);
  395. // Count total nb of records
  396. $nbtotalofrecords = '';
  397. if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
  398. $resql = $db->query($sql);
  399. $nbtotalofrecords = $db->num_rows($resql);
  400. if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
  401. $page = 0;
  402. $offset = 0;
  403. }
  404. }
  405. // if total of record found is smaller than limit, no need to do paging and to restart another select with limits set.
  406. if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) {
  407. $num = $nbtotalofrecords;
  408. } else {
  409. $sql .= $db->plimit($limit + 1, $offset);
  410. $resql = $db->query($sql);
  411. if (!$resql) {
  412. dol_print_error($db);
  413. exit;
  414. }
  415. $num = $db->num_rows($resql);
  416. }
  417. // Direct jump if only one record found
  418. if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all) {
  419. $obj = $db->fetch_object($resql);
  420. $id = $obj->rowid;
  421. header("Location: ".DOL_URL_ROOT.'/ticket/card.php?id='.$id);
  422. exit;
  423. }
  424. // Output page
  425. // --------------------------------------------------------------------
  426. llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs');
  427. if ($socid && !$projectid && !$project_ref && $user->rights->societe->lire) {
  428. $socstat = new Societe($db);
  429. $res = $socstat->fetch($socid);
  430. if ($res > 0) {
  431. $tmpobject = $object;
  432. $object = $socstat; // $object must be of type Societe when calling societe_prepare_head
  433. $head = societe_prepare_head($socstat);
  434. $object = $tmpobject;
  435. print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), -1, 'company');
  436. dol_banner_tab($socstat, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom');
  437. print '<div class="fichecenter">';
  438. print '<div class="underbanner clearboth"></div>';
  439. print '<table class="border centpercent tableforfield">';
  440. // Type Prospect/Customer/Supplier
  441. print '<tr><td class="titlefield">'.$langs->trans('NatureOfThirdParty').'</td><td>';
  442. print $socstat->getTypeUrl(1);
  443. print '</td></tr>';
  444. // Customer code
  445. if ($socstat->client && !empty($socstat->code_client)) {
  446. print '<tr><td class="titlefield">';
  447. print $langs->trans('CustomerCode').'</td><td>';
  448. print showValueWithClipboardCPButton(dol_escape_htmltag($socstat->code_client));
  449. $tmpcheck = $socstat->check_codeclient();
  450. if ($tmpcheck != 0 && $tmpcheck != -5) {
  451. print ' <font class="error">('.$langs->trans("WrongCustomerCode").')</font>';
  452. }
  453. print '</td>';
  454. print '</tr>';
  455. }
  456. // Supplier code
  457. if ($socstat->fournisseur && !empty($socstat->code_fournisseur)) {
  458. print '<tr><td class="titlefield">';
  459. print $langs->trans('SupplierCode').'</td><td>';
  460. print showValueWithClipboardCPButton(dol_escape_htmltag($socstat->code_fournisseur));
  461. $tmpcheck = $socstat->check_codefournisseur();
  462. if ($tmpcheck != 0 && $tmpcheck != -5) {
  463. print ' <font class="error">('.$langs->trans("WrongSupplierCode").')</font>';
  464. }
  465. print '</td>';
  466. print '</tr>';
  467. }
  468. print '</table>';
  469. print '</div>';
  470. print dol_get_fiche_end();
  471. }
  472. }
  473. if ($projectid > 0 || $project_ref) {
  474. $projectstat = new Project($db);
  475. if ($projectstat->fetch($projectid, $project_ref) > 0) {
  476. $projectid = $projectstat->id;
  477. $projectstat->fetch_thirdparty();
  478. $savobject = $object;
  479. $object = $projectstat;
  480. // To verify role of users
  481. //$userAccess = $object->restrictedProjectArea($user,'read');
  482. $userWrite = $projectstat->restrictedProjectArea($user, 'write');
  483. //$userDelete = $object->restrictedProjectArea($user,'delete');
  484. //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
  485. $head = project_prepare_head($projectstat);
  486. print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), -1, ($projectstat->public ? 'projectpub' : 'project'));
  487. // Project card
  488. $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
  489. $morehtmlref = '<div class="refidno">';
  490. // Title
  491. $morehtmlref .= $object->title;
  492. // Thirdparty
  493. if ($object->thirdparty->id > 0) {
  494. $morehtmlref .= '<br>'.$langs->trans('ThirdParty').' : '.$object->thirdparty->getNomUrl(1, 'project');
  495. }
  496. $morehtmlref .= '</div>';
  497. // Define a complementary filter for search of next/prev ref.
  498. if (!$user->rights->projet->all->lire) {
  499. $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
  500. $object->next_prev_filter = " rowid IN (".$db->sanitize(count($objectsListId) ? join(',', array_keys($objectsListId)) : '0').")";
  501. }
  502. dol_banner_tab($object, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
  503. print '<div class="fichecenter">';
  504. print '<div class="underbanner clearboth"></div>';
  505. print '<table class="border tableforfield" width="100%">';
  506. // Visibility
  507. print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
  508. if ($projectstat->public) {
  509. print $langs->trans('SharedProject');
  510. } else {
  511. print $langs->trans('PrivateProject');
  512. }
  513. print '</td></tr>';
  514. print "</table>";
  515. print '</div>';
  516. print dol_get_fiche_end();
  517. $object = $savobject;
  518. } else {
  519. print "ErrorRecordNotFound";
  520. }
  521. }
  522. $arrayofselected = is_array($toselect) ? $toselect : array();
  523. $param = '';
  524. if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
  525. $param .= '&contextpage='.urlencode($contextpage);
  526. }
  527. if ($limit > 0 && $limit != $conf->liste_limit) {
  528. $param .= '&limit='.urlencode($limit);
  529. }
  530. foreach ($search as $key => $val) {
  531. if (is_array($search[$key]) && count($search[$key])) {
  532. foreach ($search[$key] as $skey) {
  533. $param .= '&search_'.$key.'[]='.urlencode($skey);
  534. }
  535. } else {
  536. $param .= '&search_'.$key.'='.urlencode($search[$key]);
  537. }
  538. }
  539. if ($optioncss != '') {
  540. $param .= '&optioncss='.urlencode($optioncss);
  541. }
  542. // Add $param from extra fields
  543. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
  544. if ($socid > 0) {
  545. $param .= '&socid='.urlencode($socid);
  546. }
  547. if ($search_societe) {
  548. $param .= '&search_societe='.urlencode($search_societe);
  549. }
  550. if ($projectid > 0) {
  551. $param .= '&projectid='.urlencode($projectid);
  552. }
  553. if ($search_date_start) {
  554. $tmparray = dol_getdate($search_date_start);
  555. $param .= '&search_date_startday='.urlencode($tmparray['mday']);
  556. $param .= '&search_date_startmonth='.urlencode($tmparray['mon']);
  557. $param .= '&search_date_startyear='.urlencode($tmparray['year']);
  558. }
  559. if ($search_date_end) {
  560. $tmparray = dol_getdate($search_date_end);
  561. $param .= '&search_date_endday='.urlencode($tmparray['mday']);
  562. $param .= '&search_date_endmonth='.urlencode($tmparray['mon']);
  563. $param .= '&search_date_endyear='.urlencode($tmparray['year']);
  564. }
  565. if ($search_dateread_start) {
  566. $tmparray = dol_getdate($search_dateread_start);
  567. $param .= '&search_dateread_startday='.urlencode($tmparray['mday']);
  568. $param .= '&search_dateread_startmonth='.urlencode($tmparray['mon']);
  569. $param .= '&search_dateread_startyear='.urlencode($tmparray['year']);
  570. }
  571. if ($search_dateread_end) {
  572. $tmparray = dol_getdate($search_dateread_end);
  573. $param .= '&search_dateread_endday='.urlencode($tmparray['mday']);
  574. $param .= '&search_dateread_endmonth='.urlencode($tmparray['mon']);
  575. $param .= '&search_dateread_endyear='.urlencode($tmparray['year']);
  576. }
  577. if ($search_dateclose_start) {
  578. $tmparray = dol_getdate($search_dateclose_start);
  579. $param .= '&search_dateclose_startday='.urlencode($tmparray['mday']);
  580. $param .= '&search_dateclose_startmonth='.urlencode($tmparray['mon']);
  581. $param .= '&search_dateclose_startyear='.urlencode($tmparray['year']);
  582. }
  583. if ($search_dateclose_end) {
  584. $tmparray = dol_getdate($search_dateclose_end);
  585. $param .= '&search_date_endday='.urlencode($tmparray['mday']);
  586. $param .= '&search_date_endmonth='.urlencode($tmparray['mon']);
  587. $param .= '&search_date_endyear='.urlencode($tmparray['year']);
  588. }
  589. // List of mass actions available
  590. $arrayofmassactions = array(
  591. //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
  592. //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
  593. );
  594. if ($user->rights->ticket->write) {
  595. $arrayofmassactions['close'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Close");
  596. }
  597. if ($user->rights->ticket->write) {
  598. $arrayofmassactions['reopen'] = img_picto('', 'folder-open', 'class="pictofixedwidth"').$langs->trans("ReOpen");
  599. }
  600. if ($user->rights->ticket->delete) {
  601. $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
  602. }
  603. if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
  604. $arrayofmassactions = array();
  605. }
  606. $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
  607. print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
  608. if ($optioncss != '') {
  609. print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
  610. }
  611. print '<input type="hidden" name="token" value="'.newToken().'">';
  612. print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
  613. print '<input type="hidden" name="action" value="list">';
  614. print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
  615. print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
  616. print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
  617. print '<input type="hidden" name="mode" value="'.$mode.'" >';
  618. if ($socid) {
  619. print '<input type="hidden" name="socid" value="'.$socid.'" >';
  620. }
  621. if ($projectid) {
  622. print '<input type="hidden" name="projectid" value="'.$projectid.'" >';
  623. }
  624. $url = DOL_URL_ROOT.'/ticket/card.php?action=create'.($socid ? '&socid='.$socid : '').($projectid ? '&origin=projet_project&originid='.$projectid : '');
  625. if (!empty($socid)) {
  626. $url .= '&socid='.$socid;
  627. }
  628. $newcardbutton = dolGetButtonTitle($langs->trans('NewTicket'), '', 'fa fa-plus-circle', $url, '', $user->rights->ticket->write);
  629. $picto = 'ticket';
  630. if ($socid > 0) {
  631. $picto = '';
  632. }
  633. print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
  634. if ($mode == 'mine') {
  635. print '<div class="opacitymedium">'.$langs->trans('TicketAssignedToMeInfos').'</div><br>';
  636. }
  637. // Add code for pre mass action (confirmation or email presend form)
  638. $topicmail = "SendTicketRef";
  639. $modelmail = "ticket";
  640. $objecttmp = new Ticket($db);
  641. $trackid = 'tic'.$object->id;
  642. include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
  643. if ($search_all) {
  644. foreach ($fieldstosearchall as $key => $val) {
  645. $fieldstosearchall[$key] = $langs->trans($val);
  646. }
  647. print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>';
  648. }
  649. $moreforfilter = '';
  650. /*$moreforfilter.='<div class="divsearchfield">';
  651. $moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
  652. $moreforfilter.= '</div>';*/
  653. $parameters = array();
  654. $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
  655. if (empty($reshook)) {
  656. $moreforfilter .= $hookmanager->resPrint;
  657. } else {
  658. $moreforfilter = $hookmanager->resPrint;
  659. }
  660. if (!empty($moreforfilter)) {
  661. print '<div class="liste_titre liste_titre_bydiv centpercent">';
  662. print $moreforfilter;
  663. print '</div>';
  664. }
  665. $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
  666. $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
  667. $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
  668. print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
  669. print '<div class="div-table-responsive-inside">';
  670. print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
  671. // Fields title search
  672. // --------------------------------------------------------------------
  673. print '<tr class="liste_titre">';
  674. foreach ($object->fields as $key => $val) {
  675. $cssforfield = (empty($val['css']) ? '' : $val['css']);
  676. if ($key == 'fk_statut') {
  677. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  678. } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
  679. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  680. } elseif (in_array($val['type'], array('timestamp'))) {
  681. $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
  682. } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') {
  683. $cssforfield .= ($cssforfield ? ' ' : '').'right';
  684. }
  685. if (!empty($arrayfields['t.'.$key]['checked'])) {
  686. if ($key == 'type_code') {
  687. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
  688. $formTicket->selectTypesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, ($val['css'] ? $val['css'] : 'maxwidth150'));
  689. print '</td>';
  690. } elseif ($key == 'category_code') {
  691. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
  692. $formTicket->selectGroupTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, ($val['css'] ? $val['css'] : 'maxwidth150'));
  693. print '</td>';
  694. } elseif ($key == 'severity_code') {
  695. print '<td class="liste_titre center'.($cssforfield ? ' '.$cssforfield : '').'">';
  696. $formTicket->selectSeveritiesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, ($val['css'] ? $val['css'] : 'maxwidth150'));
  697. print '</td>';
  698. } elseif ($key == 'fk_user_assign' || $key == 'fk_user_create') {
  699. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
  700. print $form->select_dolusers((empty($search[$key]) ? '' : $search[$key]), 'search_'.$key, 1, null, 0, '', '', '0', 0, 0, '', 0, '', ($val['css'] ? $val['css'] : 'maxwidth125'));
  701. print '</td>';
  702. } elseif ($key == 'fk_statut') {
  703. $arrayofstatus = array();
  704. $arrayofstatus['openall'] = '-- '.$langs->trans('OpenAll').' --';
  705. foreach ($object->statuts_short as $key2 => $val2) {
  706. if ($key2 == Ticket::STATUS_CLOSED) {
  707. $arrayofstatus['closeall'] = '-- '.$langs->trans('ClosedAll').' --';
  708. }
  709. $arrayofstatus[$key2] = $val2;
  710. }
  711. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
  712. //var_dump($arrayofstatus);var_dump($search['fk_statut']);var_dump(array_values($search[$key]));
  713. $selectedarray = null;
  714. if (!empty($search[$key])) {
  715. $selectedarray = array_values($search[$key]);
  716. }
  717. print Form::multiselectarray('search_fk_statut', $arrayofstatus, $selectedarray, 0, 0, 'minwidth100imp maxwidth150', 1, 0, '', '', '');
  718. print '</td>';
  719. } elseif ($key == "fk_soc") {
  720. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'"><input type="text" class="flat maxwidth75" name="search_societe" value="'.dol_escape_htmltag($search_societe).'"></td>';
  721. } elseif ($key == "datec" || $key == 'date_read' || $key == 'date_close') {
  722. print '<td class="liste_titre center">';
  723. print '<div class="nowrap">';
  724. switch ($key) {
  725. case 'datec':
  726. print $form->selectDate($search_date_start ?: -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
  727. break;
  728. case 'date_read':
  729. print $form->selectDate($search_dateread_start ?: -1, 'search_dateread_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
  730. break;
  731. case 'date_close':
  732. print $form->selectDate($search_dateclose_start ?: -1, 'search_dateclose_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From"));
  733. }
  734. print '</div>';
  735. print '<div class="nowrap">';
  736. switch ($key) {
  737. case 'datec':
  738. print $form->selectDate($search_date_end ?: -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
  739. break;
  740. case 'date_read':
  741. print $form->selectDate($search_dateread_end ?: -1, 'search_dateread_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
  742. break;
  743. case 'date_close':
  744. print $form->selectDate($search_dateclose_end ?: -1, 'search_dateclose_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to"));
  745. }
  746. print '</div>';
  747. print '</td>';
  748. } else {
  749. print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').'">';
  750. if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
  751. print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1);
  752. } elseif (strpos($val['type'], 'integer:') === 0) {
  753. print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth150', 1);
  754. } elseif (!preg_match('/^(date|timestamp)/', $val['type'])) {
  755. print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]).'">';
  756. }
  757. print '</td>';
  758. }
  759. }
  760. }
  761. // Extra fields
  762. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
  763. // Fields from hook
  764. $parameters = array('arrayfields'=>$arrayfields);
  765. $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
  766. print $hookmanager->resPrint;
  767. // Action column
  768. print '<td class="liste_titre maxwidthsearch">';
  769. $searchpicto = $form->showFilterButtons();
  770. print $searchpicto;
  771. print '</td>';
  772. print '</tr>'."\n";
  773. // Fields title label
  774. // --------------------------------------------------------------------
  775. print '<tr class="liste_titre">';
  776. foreach ($object->fields as $key => $val) {
  777. $cssforfield = (empty($val['css']) ? '' : $val['css']);
  778. if ($key == 'fk_statut' || $key == 'severity_code') {
  779. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  780. } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
  781. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  782. } elseif (in_array($val['type'], array('timestamp'))) {
  783. $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
  784. } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') {
  785. $cssforfield .= ($cssforfield ? ' ' : '').'right';
  786. }
  787. if (!empty($arrayfields['t.'.$key]['checked'])) {
  788. print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, '', $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n";
  789. }
  790. }
  791. // Extra fields
  792. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
  793. // Hook fields
  794. $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
  795. $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
  796. print $hookmanager->resPrint;
  797. print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'maxwidthsearch center ')."\n";
  798. print '</tr>'."\n";
  799. // Detect if we need a fetch on each output line
  800. $needToFetchEachLine = 0;
  801. if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
  802. foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
  803. if (preg_match('/\$object/', $val)) {
  804. $needToFetchEachLine++; // There is at least one compute field that use $object
  805. }
  806. }
  807. }
  808. // Loop on record
  809. // --------------------------------------------------------------------
  810. $i = 0;
  811. $totalarray = array();
  812. $cacheofoutputfield = array();
  813. while ($i < min($num, $limit)) {
  814. $obj = $db->fetch_object($resql);
  815. if (empty($obj)) {
  816. break; // Should not happen
  817. }
  818. // Store properties in $object
  819. $object->id = $obj->rowid;
  820. foreach ($object->fields as $key => $val) {
  821. if (property_exists($obj, $key)) {
  822. $object->$key = $obj->$key;
  823. }
  824. }
  825. $langs->load("ticket");
  826. // Show here line of result
  827. print '<tr class="oddeven">';
  828. foreach ($object->fields as $key => $val) {
  829. $cssforfield = '';
  830. if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
  831. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  832. }
  833. if (in_array($val['type'], array('timestamp'))) {
  834. $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
  835. }
  836. if (in_array($key, array('ref', 'fk_project'))) {
  837. $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
  838. }
  839. if ($key == 'fk_statut' || $key == 'severity_code') {
  840. $cssforfield .= ($cssforfield ? ' ' : '').'center';
  841. }
  842. if (!empty($arrayfields['t.'.$key]['checked'])) {
  843. print '<td';
  844. if ($cssforfield || $val['css']) {
  845. print ' class="';
  846. }
  847. print $cssforfield;
  848. if ($cssforfield && $val['css']) {
  849. print ' ';
  850. }
  851. print $val['css'];
  852. if ($cssforfield || $val['css']) {
  853. print '"';
  854. }
  855. print '>';
  856. if ($key == 'fk_statut') {
  857. print $object->getLibStatut(5);
  858. } elseif ($key == 'subject') {
  859. $s = $obj->subject;
  860. print '<span title="'.dol_escape_htmltag($s).'">';
  861. print $s;
  862. print '</span>';
  863. } elseif ($key == 'type_code') {
  864. $s = $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
  865. print '<span title="'.dol_escape_htmltag($s).'">';
  866. print $s;
  867. print '</span>';
  868. } elseif ($key == 'category_code') {
  869. $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
  870. print '<span title="'.dol_escape_htmltag($s).'">';
  871. print $s;
  872. print '</span>';
  873. } elseif ($key == 'severity_code') {
  874. $s = $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
  875. print '<span title="'.dol_escape_htmltag($s).'">';
  876. print $s;
  877. print '</span>';
  878. } elseif ($key == 'tms') {
  879. print dol_print_date($db->jdate($obj->$key), 'dayhour', 'tzuser');
  880. } elseif ($key == 'fk_user_create') {
  881. if ($object->fk_user_create > 0) {
  882. if (isset($conf->cache['user'][$object->fk_user_create])) {
  883. $user_temp = $conf->cache['user'][$object->fk_user_create];
  884. } else {
  885. $user_temp = new User($db);
  886. $user_temp->fetch($object->fk_user_create);
  887. $conf->cache['user'][$object->fk_user_create] = $user_temp;
  888. }
  889. print $user_temp->getNomUrl(-1);
  890. }
  891. } elseif ($key == 'fk_user_assign') {
  892. if ($object->fk_user_assign > 0) {
  893. if (isset($conf->cache['user'][$object->fk_user_assign])) {
  894. $user_temp = $conf->cache['user'][$object->fk_user_assign];
  895. } else {
  896. $user_temp = new User($db);
  897. $user_temp->fetch($object->fk_user_assign);
  898. $conf->cache['user'][$object->fk_user_assign] = $user_temp;
  899. }
  900. print $user_temp->getNomUrl(-1);
  901. }
  902. } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
  903. print $object->showOutputField($val, $key, $db->jdate($obj->$key), '');
  904. } else { // Example: key=fk_soc, obj->key=123 val=array('type'=>'integer', ...
  905. $tmp = explode(':', $val['type']);
  906. if ($tmp[0] == 'integer' && !empty($tmp[1]) && class_exists($tmp[1])) {
  907. // It is a type of an foreign field. We will try to reduce the number of fetch that the showOutputField is making.
  908. //var_dump('eeee-'.$key.'-'.$obj->$key.'-'.$val['type']);
  909. if ($key && $obj->$key && $val['type'] && array_key_exists($key.'-'.$obj->$key.'-'.$val['type'], $cacheofoutputfield)) {
  910. $result = $cacheofoutputfield[$key.'-'.$obj->$key.'-'.$val['type']];
  911. } else {
  912. $result = $object->showOutputField($val, $key, $obj->$key, '');
  913. $cacheofoutputfield[$key.'-'.$obj->$key.'-'.$val['type']] = $result;
  914. }
  915. } else {
  916. $result = $object->showOutputField($val, $key, $obj->$key, '');
  917. }
  918. print $result;
  919. }
  920. print '</td>';
  921. if (!$i) {
  922. $totalarray['nbfield']++;
  923. }
  924. if (!empty($val['isameasure'])) {
  925. if (!$i) {
  926. $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
  927. }
  928. if (!isset($totalarray['val'])) {
  929. $totalarray['val'] = array();
  930. }
  931. if (!isset($totalarray['val']['t.'.$key])) {
  932. $totalarray['val']['t.'.$key] = 0;
  933. }
  934. $totalarray['val']['t.'.$key] += $obj->$key;
  935. }
  936. }
  937. }
  938. // Extra fields
  939. include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
  940. // Fields from hook
  941. $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
  942. $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
  943. print $hookmanager->resPrint;
  944. // Action column
  945. print '<td class="nowrap center">';
  946. if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
  947. $selected = 0;
  948. if (in_array($obj->rowid, $arrayofselected)) {
  949. $selected = 1;
  950. }
  951. print '<input id="cb'.$obj->rowid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->rowid.'"'.($selected ? ' checked="checked"' : '').'>';
  952. }
  953. print '</td>';
  954. if (!$i) {
  955. $totalarray['nbfield']++;
  956. }
  957. print '</tr>';
  958. $i++;
  959. }
  960. // Show total line
  961. include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
  962. // If no record found
  963. if ($num == 0) {
  964. $colspan = 1;
  965. foreach ($arrayfields as $key => $val) {
  966. if (!empty($val['checked'])) {
  967. $colspan++;
  968. }
  969. }
  970. print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
  971. }
  972. $db->free($resql);
  973. $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
  974. $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
  975. print $hookmanager->resPrint;
  976. print '</table>'."\n";
  977. print '</div>'."\n";
  978. print '</div>'."\n";
  979. print '</form>'."\n";
  980. if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
  981. $hidegeneratedfilelistifempty = 1;
  982. if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
  983. $hidegeneratedfilelistifempty = 0;
  984. }
  985. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
  986. $formfile = new FormFile($db);
  987. // Show list of available documents
  988. $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
  989. $urlsource .= str_replace('&amp;', '&', $param);
  990. $filedir = $diroutputmassaction;
  991. $genallowed = $user->rights->ticket->read;
  992. $delallowed = $user->rights->ticket->write;
  993. print $formfile->showdocuments('massfilesarea_ticket', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
  994. }
  995. // End of page
  996. llxFooter();
  997. $db->close();