dolibarr 25.0.0-alpha
position_list.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
4 * Copyright (C) 2021 Greg Rastklan <greg.rastklan@atm-consulting.fr>
5 * Copyright (C) 2021 Jean-Pascal BOUDET <jean-pascal.boudet@atm-consulting.fr>
6 * Copyright (C) 2021 Grégory BLEMAND <gregory.blemand@atm-consulting.fr>
7 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
31// Load Dolibarr environment
32require '../main.inc.php';
33
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
37require_once DOL_DOCUMENT_ROOT.'/hrm/class/job.class.php';
38require_once DOL_DOCUMENT_ROOT.'/hrm/class/position.class.php';
39
48// Load translation files required by the page
49$langs->loadLangs(array('hrm', 'other'));
50
51// Get parameters
52$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
53$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
54$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
55$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
56$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
57$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
58$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'positionlist'; // To manage different context of search
59$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
60$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
61$mode = GETPOST('mode', 'aZ');
62
63$id = GETPOSTINT('id');
64$ref = GETPOST('ref', 'alpha');
65
66// Load variable for pagination
67$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
68$sortfield = GETPOST('sortfield', 'aZ09comma');
69$sortorder = GETPOST('sortorder', 'aZ09comma');
70$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
71if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
72 // If $page is not defined, or '' or -1 or if we click on clear filters
73 $page = 0;
74}
75$offset = $limit * $page;
76$pageprev = $page - 1;
77$pagenext = $page + 1;
78
79// Initialize a technical objects
80$object = new Position($db);
81$extrafields = new ExtraFields($db);
82$userstatic = new User($db);
83$diroutputmassaction = $conf->hrm->dir_output.'/temp/massgeneration/'.$user->id;
84$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array
85
86// Fetch optionals attributes and labels
87$extrafields->fetch_name_optionals_label($object->table_element);
88//$extrafields->fetch_name_optionals_label($object->table_element_line);
89
90$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
91
92// Default sort order (if not yet defined by previous GETPOST)
93if (!$sortfield) {
94 reset($object->fields); // Reset is required to avoid key() to return null.
95 $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
96}
97if (!$sortorder) {
98 $sortorder = "ASC";
99}
100
101// Initialize array of search criteria
102$search_all = trim(GETPOST('search_all', 'alphanohtml'));
103$search = array();
104foreach ($object->fields as $key => $val) {
105 if (GETPOST('search_'.$key, 'alpha') !== '') {
106 $search[$key] = GETPOST('search_'.$key, 'alpha');
107 }
108 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
109 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOSTINT('search_'.$key.'_dtstartmonth'), GETPOSTINT('search_'.$key.'_dtstartday'), GETPOSTINT('search_'.$key.'_dtstartyear'));
110 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOSTINT('search_'.$key.'_dtendmonth'), GETPOSTINT('search_'.$key.'_dtendday'), GETPOSTINT('search_'.$key.'_dtendyear'));
111 }
112}
113
114// List of fields to search into when doing a "search in all"
115$fieldstosearchall = array();
116foreach ($object->fields as $key => $val) {
117 if (!empty($val['searchall'])) {
118 $fieldstosearchall['t.'.$key] = $val['label'];
119 }
120}
121
122// Definition of array of fields for columns
123$tableprefix = 't';
124$arrayfields = array();
125foreach ($object->fields as $key => $val) {
126 // If $val['visible']==0, then we never show the field
127 if (!empty($val['visible'])) {
128 $visible = (int) dol_eval((string) $val['visible'], 1);
129 $arrayfields[$tableprefix.'.'.$key] = array(
130 'label' => $val['label'],
131 'checked' => (($visible < 0) ? 0 : 1),
132 'enabled' => (abs($visible) != 3 && (bool) dol_eval((string) $val['enabled'], 1)),
133 'position' => $val['position'],
134 'help' => isset($val['help']) ? $val['help'] : ''
135 );
136 }
137}
138// Extra fields
139include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
140// Add hook to complete $arrayfield
141$parameters = array('arrayfields' => &$arrayfields);
142$reshook = $hookmanager->executeHooks('completeArrayFields', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
143
144$object->fields = dol_sort_array($object->fields, 'position');
145$arrayfields = dol_sort_array($arrayfields, 'position');
146
147// Permissions
148$permissiontoread = $user->hasRight('hrm', 'all', 'read');
149$permissiontoadd = $user->hasRight('hrm', 'all', 'write');
150$permissiontodelete = $user->hasRight('hrm', 'all', 'delete');
151
152// Security check (enable the most restrictive one)
153if ($user->socid > 0) {
155}
156//if ($user->socid > 0) accessforbidden();
157//$socid = 0; if ($user->socid > 0) $socid = $user->socid;
158//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
159//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
160if (!isModEnabled('hrm')) {
161 accessforbidden('Module hrm not enabled');
162}
163if (!$permissiontoread) {
165}
166
167// Force the type of field fk_user to remove the filter on active user.
168// Note: Another fix would be to be able to filter on a freetet on firstname/lastname.
169//var_dump($object->fields['fk_user']);
170$object->fields['fk_user']['type'] = 'integer:User:user/class/user.class.php:0';
171
172
173/*
174 * Actions
175 */
176
177if (GETPOST('cancel', 'alpha')) {
178 $action = 'list';
179 $massaction = '';
180}
181if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
182 $massaction = '';
183}
184
185$parameters = array('arrayfields' => &$arrayfields);
186$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
187if ($reshook < 0) {
188 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
189}
190
191if (empty($reshook)) {
192 // Selection of new fields
193 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
194
195 // Purge search criteria
196 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
197 foreach ($object->fields as $key => $val) {
198 $search[$key] = '';
199 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
200 $search[$key.'_dtstart'] = '';
201 $search[$key.'_dtend'] = '';
202 }
203 }
204 $search_all = '';
205 $toselect = array();
206 $search_array_options = array();
207 }
208 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
209 || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
210 $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
211 }
212
213 // Mass actions
214 $objectclass = 'Position';
215 $objectlabel = 'Position';
216 $uploaddir = $conf->hrm->dir_output;
217 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
218}
219
220
221
222/*
223 * View
224 */
225
226$form = new Form($db);
227$jobstatic = new Job($db);
228
229$now = dol_now();
230
231$title = $langs->trans('EmployeePositions');
232//$help_url="EN:Module_Position|FR:Module_Position_FR|ES:Módulo_Position";
233$help_url = '';
234$morejs = array();
235$morecss = array();
236
237
238// Build and execute select
239// --------------------------------------------------------------------
240$sql = 'SELECT ';
241$sql .= $object->getFieldList('t');
242$sql .= ',';
243$sql .= $userstatic->getFieldList('u', array('rowid'));
244$sql .= ', u.email, u.statut, u.photo, u.login'; // Add more field not yet into the user->fields
245$sql .= ', j.rowid as job_id, j.label as job_label';
246// Add fields from extrafields
247if (!empty($extrafields->attributes[$object->table_element]['label'])) {
248 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
249 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : "");
250 }
251}
252// Add fields from hooks
253$parameters = array();
254$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
255$sql .= $hookmanager->resPrint;
256$sql = preg_replace('/,\s*$/', '', $sql);
257
258$sqlfields = $sql; // $sql fields to remove for count total
259
260$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t LEFT JOIN ".MAIN_DB_PREFIX.$userstatic->table_element." as u on t.fk_user = u.rowid, ".MAIN_DB_PREFIX."hrm_job as j";
261
262//$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."anothertable as rc ON rc.parent = t.rowid";
263if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
264 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
265}
266// Add table from hooks
267$parameters = array();
268$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
269$sql .= $hookmanager->resPrint;
270if ($object->ismultientitymanaged == 1) {
271 $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
272} else {
273 $sql .= " WHERE 1 = 1";
274}
275$sql .= " AND t.fk_job = j.rowid";
276foreach ($search as $key => $val) {
277 if (array_key_exists($key, $object->fields)) {
278 if ($key == 'status' && $search[$key] == -1) {
279 continue;
280 }
281 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
282 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
283 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
284 $search[$key] = '';
285 }
286 $mode_search = 2;
287 }
288 if (empty($object->fields[$key]['searchmulti'])) {
289 if (!is_array($search[$key]) && $search[$key] != '') {
290 $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
291 }
292 } else {
293 if (is_array($search[$key]) && !empty($search[$key])) {
294 $sql .= natural_search("t.".$db->escape($key), implode(',', $search[$key]), (($key == 'status') ? 2 : $mode_search));
295 }
296 }
297 } else {
298 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
299 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
300 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
301 if (preg_match('/_dtstart$/', $key)) {
302 $sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
303 }
304 if (preg_match('/_dtend$/', $key)) {
305 $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
306 }
307 }
308 }
309 }
310}
311$vacant = GETPOST('search_fk_uservacant', 'alphanohtml') === 'on';
312if ($vacant) {
313 $sql .= ' AND t.fk_user = 0';
314}
315if ($search_all) {
316 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
317}
318//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
319// Add where from extra fields
320include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
321// Add where from hooks
322$parameters = array();
323$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
324$sql .= $hookmanager->resPrint;
325
326/* If a group by is required
327$sql .= " GROUP BY ";
328foreach($object->fields as $key => $val) {
329 $sql .= "t.".$db->sanitize($key).", ";
330}
331// Add fields from extrafields
332if (!empty($extrafields->attributes[$object->table_element]['label'])) {
333 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
334 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
335 }
336}
337// Add groupby from hooks
338$parameters = array();
339$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
340$sql .= $hookmanager->resPrint;
341$sql = preg_replace('/,\s*$/', '', $sql);
342*/
343
344// Count total nb of records
345$nbtotalofrecords = '';
346if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
347 /* The fast and low memory method to get and count full list converts the sql into a sql count */
348 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
349 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
350
351 $resql = $db->query($sqlforcount);
352 if ($resql) {
353 $objforcount = $db->fetch_object($resql);
354 $nbtotalofrecords = $objforcount->nbtotalofrecords;
355 } else {
357 }
358
359 if (($page * $limit) > (int) $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
360 $page = 0;
361 $offset = 0;
362 }
363 $db->free($resql);
364}
365
366// Complete request and execute it with limit
367$sql .= $db->order($sortfield, $sortorder);
368if ($limit) {
369 $sql .= $db->plimit($limit + 1, $offset);
370}
371
372$resql = $db->query($sql);
373if (!$resql) {
375 exit;
376}
377
378$num = $db->num_rows($resql);
379
380
381// Direct jump if only one record found
382if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
383 $obj = $db->fetch_object($resql);
384 $id = $obj->rowid;
385 header("Location: ".dol_buildpath('/hrm/position.php', 1).'?id='.$id);
386 exit;
387}
388
389
390// Output page
391// --------------------------------------------------------------------
392
393llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist');
394
395// Example : Adding jquery code
396// print '<script type="text/javascript">
397// jQuery(document).ready(function() {
398// function init_myfunc()
399// {
400// jQuery("#myid").removeAttr(\'disabled\');
401// jQuery("#myid").attr(\'disabled\',\'disabled\');
402// }
403// init_myfunc();
404// jQuery("#mybutton").click(function() {
405// init_myfunc();
406// });
407// });
408// </script>';
409
410$arrayofselected = is_array($toselect) ? $toselect : array();
411
412$param = '';
413if (!empty($mode)) {
414 $param .= '&mode='.urlencode($mode);
415}
416if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
417 $param .= '&contextpage='.urlencode($contextpage);
418}
419if ($limit > 0 && $limit != $conf->liste_limit) {
420 $param .= '&limit='.((int) $limit);
421}
422if ($optioncss != '') {
423 $param .= '&optioncss='.urlencode($optioncss);
424}
425
426foreach ($search as $key => $val) {
427 if (is_array($search[$key])) {
428 foreach ($search[$key] as $skey) {
429 if ($skey != '') {
430 $param .= '&search_'.$key.'[]='.urlencode($skey);
431 }
432 }
433 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
434 $param .= '&search_'.$key.'month='.GETPOSTINT('search_'.$key.'month');
435 $param .= '&search_'.$key.'day='.GETPOSTINT('search_'.$key.'day');
436 $param .= '&search_'.$key.'year='.GETPOSTINT('search_'.$key.'year');
437 } elseif ($search[$key] != '') {
438 $param .= '&search_'.$key.'='.urlencode($search[$key]);
439 }
440}
441// Add $param from extra fields
442include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
443// Add $param from hooks
444$parameters = array('param' => &$param);
445$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
446$param .= $hookmanager->resPrint;
447
448// List of mass actions available
449$arrayofmassactions = array(
450 //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
451 //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
452 //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
453 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
454);
455if (!empty($permissiontodelete)) {
456 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
457}
458if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
459 $arrayofmassactions = array();
460}
461$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
462
463print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
464if ($optioncss != '') {
465 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
466}
467print '<input type="hidden" name="token" value="'.newToken().'">';
468print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
469print '<input type="hidden" name="action" value="list">';
470print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
471print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
472print '<input type="hidden" name="page" value="'.$page.'">';
473print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
474print '<input type="hidden" name="page_y" value="">';
475print '<input type="hidden" name="mode" value="'.$mode.'">';
476
477$newcardbutton = '';
478$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
479$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
480$newcardbutton .= dolGetButtonTitleSeparator();
481$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/position.php', 1).'?action=create', '', $permissiontoadd);
482
483print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
484
485// Add code for pre mass action (confirmation or email presend form)
486$topicmail = "SendPositionRef";
487$modelmail = "position";
488$objecttmp = new Position($db);
489$trackid = 'xxxx'.$object->id;
490include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
491
492if ($search_all) {
493 $setupstring = '';
494 // @phan-suppress-next-line PhanEmptyForeach
495 foreach ($fieldstosearchall as $key => $val) {
496 $fieldstosearchall[$key] = $langs->trans($val);
497 $setupstring .= $key."=".$val.";";
498 }
499 print '<!-- Search done like if JOBPOSITION_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
500 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>';
501}
502
503$moreforfilter = '';
504/*$moreforfilter.='<div class="divsearchfield">';
505$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
506$moreforfilter.= '</div>';*/
507
508$parameters = array();
509$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
510if (empty($reshook)) {
511 $moreforfilter .= $hookmanager->resPrint;
512} else {
513 $moreforfilter = $hookmanager->resPrint;
514}
515
516if (!empty($moreforfilter)) {
517 print '<div class="liste_titre liste_titre_bydiv centpercent">';
518 print $moreforfilter;
519 print '</div>';
520}
521
522$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
523$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column ? 'left' : ''); // This also change content of $arrayfields with user setup
524$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
525$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
526
527print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
528print '<table class="tagtable nobottomiftotal noborder liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
529
530
531$totalarray = array();
532$totalarray['nbfield'] = 0;
533
534// Fields title search
535// --------------------------------------------------------------------
536print '<tr class="liste_titre_filter">';
537// Action column
538if ($conf->main_checkbox_left_column) {
539 print '<td class="liste_titre center maxwidthsearch">';
540 $searchpicto = $form->showFilterButtons('left');
541 print $searchpicto;
542 print '</td>';
543}
544foreach ($object->fields as $key => $val) {
545 //$searchkey = empty($search[$key]) ? '' : $search[$key];
546 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
547 if ($key == 'status') {
548 $cssforfield .= ($cssforfield ? ' ' : '').'center';
549 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
550 $cssforfield .= ($cssforfield ? ' ' : '').'center';
551 } elseif (in_array($val['type'], array('timestamp'))) {
552 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
553 } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
554 $cssforfield .= ($cssforfield ? ' ' : '').'right';
555 }
556 if (!empty($arrayfields['t.'.$key]['checked'])) {
557 print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
558 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
559 if (empty($val['searchmulti'])) {
560 print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 1, 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
561 } else {
562 print $form->multiselectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 0, 0, 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
563 }
564 } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
565 print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
566 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
567 print '<div class="nowrap">';
568 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
569 print '</div>';
570 print '<div class="nowrap">';
571 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
572 print '</div>';
573 } elseif ($key == 'lang') {
574 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
575 $formadmin = new FormAdmin($db);
576 print $formadmin->select_language((isset($search[$key]) ? $search[$key] : ''), 'search_lang', 0, array(), 1, 0, 0, 'minwidth100imp maxwidth125', 2);
577 } else {
578 print '<input type="text" class="flat maxwidth'.(in_array($val['type'], array('integer', 'price')) ? '50' : '75').'" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
579 }
580 print '</td>';
581 }
582}
583// Extra fields
584include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
585
586// Fields from hook
587$parameters = array('arrayfields' => $arrayfields);
588$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
589print $hookmanager->resPrint;
590// Action column
591if (!$conf->main_checkbox_left_column) {
592 print '<td class="liste_titre center maxwidthsearch">';
593 $searchpicto = $form->showFilterButtons();
594 print $searchpicto;
595 print '</td>';
596}
597print '</tr>'."\n";
598
599$totalarray = array();
600$totalarray['nbfield'] = 0;
601
602// Fields title label
603// --------------------------------------------------------------------
604print '<tr class="liste_titre">';
605// Action column
606if ($conf->main_checkbox_left_column) {
607 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
608 $totalarray['nbfield']++;
609}
610foreach ($object->fields as $key => $val) {
611 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
612 if ($key == 'status') {
613 $cssforfield .= ($cssforfield ? ' ' : '').'center';
614 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
615 $cssforfield .= ($cssforfield ? ' ' : '').'center';
616 } elseif (in_array($val['type'], array('timestamp'))) {
617 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
618 } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) {
619 $cssforfield .= ($cssforfield ? ' ' : '').'right';
620 }
621 $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label
622 if (!empty($arrayfields['t.'.$key]['checked'])) {
623 print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n";
624 $totalarray['nbfield']++;
625 }
626}
627// Extra fields
628include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
629// Hook fields
630$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
631$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
632print $hookmanager->resPrint;
633/*if (!empty($arrayfields['anotherfield']['checked'])) {
634 print '<th class="liste_titre right">'.$langs->trans("AnotherField").'</th>';
635 $totalarray['nbfield']++;
636 }*/
637// Action column
638if (!$conf->main_checkbox_left_column) {
639 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
640 $totalarray['nbfield']++;
641}
642print '</tr>'."\n";
643
644
645// Detect if we need a fetch on each output line
646$needToFetchEachLine = 0;
647if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
648 foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
649 if (!is_null($val) && preg_match('/\$object/', $val)) {
650 $needToFetchEachLine++; // There is at least one compute field that use $object
651 }
652 }
653}
654
655
656// Loop on record
657// --------------------------------------------------------------------
658$i = 0;
659$savnbfield = $totalarray['nbfield'];
660$totalarray = array();
661$totalarray['nbfield'] = 0;
662$imaxinloop = ($limit ? min($num, $limit) : $num);
663while ($i < $imaxinloop) {
664 $obj = $db->fetch_object($resql);
665 if (empty($obj)) {
666 break; // Should not happen
667 }
668
669 // Store properties in $object
670 $object->setVarsFromFetchObj($obj);
671
672 if ($mode == 'kanban') {
673 if ($i == 0) {
674 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
675 print '<div class="box-flex-container kanban">';
676 }
677 // get info needed
678 $object->date_start = $obj->date_start;
679 $object->date_end = $obj->date_end;
680 $object->fk_job = $obj->job_id;
681
682 $jobstatic->id = $obj->job_id;
683 $jobstatic->label = $obj->job_label;
684 $jobstatic->status = $obj->job_status;
685
686 $userstatic->id = $obj->fk_user;
687 $userstatic->ref = (string) $obj->fk_user;
688 $userstatic->firstname = $obj->firstname;
689 $userstatic->lastname = $obj->lastname;
690 $userstatic->email = $obj->email;
691 $userstatic->statut = (int) $obj->statut; // deprecated
692 $userstatic->status = (int) $obj->statut;
693 $userstatic->login = $obj->login;
694 $userstatic->photo = $obj->photo;
695
696 // Output Kanban
697 $selected = -1;
698 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
699 $selected = 0;
700 if (in_array($object->id, $arrayofselected)) {
701 $selected = 1;
702 }
703 }
704 print $object->getKanbanView('', array('user' => $userstatic->getNomUrl(-1), 'job' => $jobstatic->getNomUrl(1), 'selected' => $selected));
705 if ($i == ($imaxinloop - 1)) {
706 print '</div>';
707 print '</td></tr>';
708 }
709 } else {
710 // Show line of result
711 $j = 0;
712 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
713 // Action column
714 if ($conf->main_checkbox_left_column) {
715 print '<td class="nowrap center">';
716 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
717 $selected = 0;
718 if (in_array($object->id, $arrayofselected)) {
719 $selected = 1;
720 }
721 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
722 }
723 print '</td>';
724 if (!$i) {
725 $totalarray['nbfield']++;
726 }
727 }
728 foreach ($object->fields as $key => $val) {
729 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
730 if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
731 $cssforfield .= ($cssforfield ? ' ' : '').'center';
732 } elseif ($key == 'status') {
733 $cssforfield .= ($cssforfield ? ' ' : '').'center';
734 }
735
736 if (in_array($val['type'], array('timestamp'))) {
737 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
738 } elseif ($key == 'ref') {
739 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
740 }
741
742 if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('id', 'rowid', 'ref', 'status')) && empty($val['arrayofkeyval'])) {
743 $cssforfield .= ($cssforfield ? ' ' : '').'right';
744 }
745 //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100';
746
747 if (!empty($arrayfields['t.'.$key]['checked'])) {
748 print '<td'.($cssforfield ? ' class="'.$cssforfield.((preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key)) ? ' classfortooltip' : '').'"' : '');
749 if (preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key) && !in_array($key, array('ref'))) {
750 print ' title="'.dolPrintHTMLForAttribute((string) $object->$key).'"';
751 }
752 print '>';
753 if ($key == 'status') {
754 print $object->getLibStatut(5);
755 } elseif ($key == 'rowid') {
756 print $object->showOutputField($val, $key, (string) $object->id, '');
757 } else {
758 print $object->showOutputField($val, $key, $object->$key, '');
759 }
760 print '</td>';
761 if (!$i) {
762 $totalarray['nbfield']++;
763 }
764 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
765 if (!$i) {
766 $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
767 }
768 if (!isset($totalarray['val'])) {
769 $totalarray['val'] = array();
770 }
771 if (!isset($totalarray['val']['t.'.$key])) {
772 $totalarray['val']['t.'.$key] = 0;
773 }
774 $totalarray['val']['t.'.$key] += $object->$key;
775 }
776 }
777 }
778 // Extra fields
779 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
780 // Fields from hook
781 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
782 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
783 print $hookmanager->resPrint;
784 // Action column
785 if (empty($conf->main_checkbox_left_column)) {
786 print '<td class="nowrap center">';
787 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
788 $selected = 0;
789 if (in_array($object->id, $arrayofselected)) {
790 $selected = 1;
791 }
792 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
793 }
794 print '</td>';
795 if (!$i) {
796 $totalarray['nbfield']++;
797 }
798 }
799
800 print '</tr>'."\n";
801 }
802
803 $i++;
804}
805
806// Show total line
807include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
808
809// If no record found
810if ($num == 0) {
811 $colspan = 1;
812 foreach ($arrayfields as $key => $val) {
813 if (!empty($val['checked'])) {
814 $colspan++;
815 }
816 }
817 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
818}
819
820
821$db->free($resql);
822
823$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
824$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
825print $hookmanager->resPrint;
826
827print '</table>'."\n";
828print '</div>'."\n";
829
830print '</form>'."\n";
831
832if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
833 $hidegeneratedfilelistifempty = 1;
834 if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
835 $hidegeneratedfilelistifempty = 0;
836 }
837
838 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
839 $formfile = new FormFile($db);
840
841 // Show list of available documents
842 $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
843 $urlsource .= str_replace('&amp;', '&', $param);
844
845 $filedir = $diroutputmassaction;
846 $genallowed = $permissiontoread;
847 $delallowed = $permissiontoadd;
848
849 print $formfile->showdocuments('massfilesarea_hrm', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
850}
851
852// End of page
853llxFooter();
854$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$totalarray
Definition list.php:501
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage standard extra fields.
Class to generate html code for admin pages.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class for Job.
Definition job.class.php:38
Class for Position.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
natural_search($fields, $value, $mode=0, $nofirstand=0, $sqltoadd='')
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
isModEnabled($module)
Is Dolibarr module enabled.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.