dolibarr 25.0.0-alpha
job_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 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2025-2026 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';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
36// load hrm libraries
37require_once __DIR__.'/class/job.class.php';
38
47// Load translation files required by the page
48$langs->loadLangs(array('hrm', 'other'));
49
50// Get parameters
51$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'create'/'add', 'edit'/'update', 'view', ...
52$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
53$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
54$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
55$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
56$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
57$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
58$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
59$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
60$mode = GETPOST('mode', 'aZ'); // The display mode ('list', 'kanban', 'hierarchy', 'calendar', 'gantt', ...)
61$groupby = GETPOST('groupby', 'aZ');
62
63$id = GETPOSTINT('id');
64
65// Load variable for pagination
66$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
67$sortfield = GETPOST('sortfield', 'aZ09comma');
68$sortorder = GETPOST('sortorder', 'aZ09comma');
69$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
70if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
71 // If $page is not defined, or '' or -1 or if we click on clear filters
72 $page = 0;
73}
74$offset = $limit * $page;
75$pageprev = $page - 1;
76$pagenext = $page + 1;
77
78// Initialize a technical objects
79$object = new Job($db);
80$extrafields = new ExtraFields($db);
81$diroutputmassaction = $conf->hrm->dir_output.'/temp/massgeneration/'.$user->id;
82$hookmanager->initHooks(array('joblist')); // Note that conf->hooks_modules contains array
83
84// Fetch optionals attributes and labels
85$extrafields->fetch_name_optionals_label($object->table_element);
86//$extrafields->fetch_name_optionals_label($object->table_element_line);
87
88$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
89
90// Default sort order (if not yet defined by previous GETPOST)
91if (!$sortfield) {
92 reset($object->fields); // Reset is required to avoid key() to return null.
93 $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
94}
95if (!$sortorder) {
96 $sortorder = "ASC";
97}
98
99// Initialize array of search criteria
100$search_all = trim(GETPOST('search_all', 'alphanohtml'));
101$search = array();
102foreach ($object->fields as $key => $val) {
103 if (GETPOST('search_'.$key, 'alpha') !== '') {
104 $search[$key] = GETPOST('search_'.$key, 'alpha');
105 }
106 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
107 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOSTINT('search_'.$key.'_dtstartmonth'), GETPOSTINT('search_'.$key.'_dtstartday'), GETPOSTINT('search_'.$key.'_dtstartyear'));
108 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOSTINT('search_'.$key.'_dtendmonth'), GETPOSTINT('search_'.$key.'_dtendday'), GETPOSTINT('search_'.$key.'_dtendyear'));
109 }
110}
111
112$fieldstosearchall = array();
113// List of fields to search into when doing a "search in all"
114foreach ($object->fields as $key => $val) {
115 if (!empty($val['searchall'])) {
116 $fieldstosearchall['t.'.$key] = $val['label'];
117 }
118}
119
120// Definition of array of fields for columns
121$tableprefix = 't';
122$arrayfields = array();
123foreach ($object->fields as $key => $val) {
124 // If $val['visible']==0, then we never show the field
125 if (!empty($val['visible'])) {
126 $visible = (int) dol_eval((string) $val['visible'], 1);
127 $arrayfields[$tableprefix.'.'.$key] = array(
128 'label' => $val['label'],
129 'checked' => (($visible < 0) ? 0 : 1),
130 'enabled' => (abs($visible) != 3 && (bool) dol_eval((string) $val['enabled'], 1)),
131 'position' => $val['position'],
132 'help' => isset($val['help']) ? $val['help'] : ''
133 );
134 }
135}
136// Extra fields
137include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
138// Add hook to complete $arrayfield
139$parameters = array('arrayfields' => &$arrayfields);
140$reshook = $hookmanager->executeHooks('completeArrayFields', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
141
142$object->fields = dol_sort_array($object->fields, 'position');
143$arrayfields = dol_sort_array($arrayfields, 'position');
144
145// Permissions
146$permissiontoread = $user->hasRight('hrm', 'all', 'read');
147$permissiontoadd = $user->hasRight('hrm', 'all', 'write');
148$permissiontodelete = $user->hasRight('hrm', 'all', 'delete');
149
150// Security check (enable the most restrictive one)
151if ($user->socid > 0) {
153}
154//if ($user->socid > 0) accessforbidden();
155//$socid = 0; if ($user->socid > 0) $socid = $user->socid;
156//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
157//restrictedArea($user, $object->module, 0, $object->table_element, $object->element, 'fk_soc', 'rowid', $isdraft);
158if (!isModEnabled('hrm')) {
159 accessforbidden('Module hrm not enabled');
160}
161if (!$permissiontoread) {
163}
164
165
166
167/*
168 * Actions
169 */
170
171if (GETPOST('cancel', 'alpha')) {
172 $action = 'list';
173 $massaction = '';
174}
175if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
176 $massaction = '';
177}
178
179$parameters = array('arrayfields' => &$arrayfields);
180$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
181if ($reshook < 0) {
182 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
183}
184
185if (empty($reshook)) {
186 // Selection of new fields
187 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
188
189 // Purge search criteria
190 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
191 foreach ($object->fields as $key => $val) {
192 $search[$key] = '';
193 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
194 $search[$key.'_dtstart'] = '';
195 $search[$key.'_dtend'] = '';
196 }
197 }
198 $search_all = '';
199 $toselect = array();
200 $search_array_options = array();
201 }
202 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
203 || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
204 $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
205 }
206
207 // Mass actions
208 $objectclass = 'Job';
209 $objectlabel = 'Job';
210 $uploaddir = $conf->hrm->dir_output;
211
212 global $error;
213 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
214}
215
216
217
218/*
219 * View
220 */
221
222$form = new Form($db);
223
224$now = dol_now();
225
226$title = $langs->trans("JobsProfiles");
227//$help_url="EN:Module_Job|FR:Module_Job_FR|ES:Módulo_Job";
228$help_url = '';
229$morejs = array();
230$morecss = array();
231
232
233// Build and execute select
234// --------------------------------------------------------------------
235$sql = "SELECT";
236$sql .= " ".$object->getFieldList('t');
237// Add fields from extrafields
238if (!empty($extrafields->attributes[$object->table_element]['label'])) {
239 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
240 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : "");
241 }
242}
243// Add fields from hooks
244$parameters = array();
245$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
246$sql .= $hookmanager->resPrint;
247$sql = preg_replace('/,\s*$/', '', $sql);
248
249$sqlfields = $sql; // $sql fields to remove for count total
250
251$sql .= ", COUNT(ju.rowid) as nbofskills";
252$sql .= " FROM ".$db->prefix().$object->table_element." as t";
253if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
254 $sql .= " LEFT JOIN ".$db->prefix().$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
255}
256$sql .= " LEFT JOIN ".$db->prefix()."hrm_job_user as ju ON ju.fk_job = t.rowid";
257// Add table from hooks
258$parameters = array();
259$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
260$sql .= $hookmanager->resPrint;
261if ($object->ismultientitymanaged == 1) {
262 $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
263} else {
264 $sql .= " WHERE 1 = 1";
265}
266foreach ($search as $key => $val) {
267 if (array_key_exists($key, $object->fields)) {
268 if ($key == 'status' && $search[$key] == -1) {
269 continue;
270 }
271 $field_spec = $object->fields[$key];
272 $mode_search = (($object->isInt($field_spec) || $object->isFloat($field_spec)) ? 1 : 0);
273 if ((strpos($field_spec['type'], 'integer:') === 0) || (strpos($field_spec['type'], 'sellist:') === 0) || !empty($field_spec['arrayofkeyval'])) {
274 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($field_spec['arrayofkeyval']) || !array_key_exists('0', $field_spec['arrayofkeyval'])))) {
275 $search[$key] = '';
276 }
277 $mode_search = 2;
278 }
279 if ($field_spec['type'] === 'boolean') {
280 $mode_search = 1;
281 if ($search[$key] == '-1') {
282 $search[$key] = '';
283 }
284 }
285 if (empty($field_spec['searchmulti'])) {
286 if (!is_array($search[$key]) && $search[$key] != '') {
287 $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
288 }
289 } else {
290 if (is_array($search[$key]) && !empty($search[$key])) {
291 $sql .= natural_search("t.".$db->escape($key), implode(',', $search[$key]), (($key == 'status') ? 2 : $mode_search));
292 }
293 }
294 } else {
295 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
296 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
297 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
298 if (preg_match('/_dtstart$/', $key)) {
299 $sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
300 }
301 if (preg_match('/_dtend$/', $key)) {
302 $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
303 }
304 }
305 }
306 }
307}
308if ($search_all) {
309 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
310}
311//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
312// Add where from extra fields
313include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
314// Add where from hooks
315$parameters = array();
316$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
317$sql .= $hookmanager->resPrint;
318
319$sql .= " GROUP BY ";
320foreach ($object->fields as $key => $val) {
321 $sql .= "t.".$db->sanitize($key).", ";
322}
323// Add fields from extrafields
324if (!empty($extrafields->attributes[$object->table_element]['label'])) {
325 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
326 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
327 }
328}
329// Add groupby from hooks
330$parameters = array();
331$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
332$sql .= $hookmanager->resPrint;
333$sql = preg_replace('/,\s*$/', '', $sql);
334
335// Count total nb of records
336$nbtotalofrecords = '';
337if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
338 /* The fast and low memory method to get and count full list converts the sql into a sql count */
339 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
340 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
341
342 $resql = $db->query($sqlforcount);
343 if ($resql) {
344 $objforcount = $db->fetch_object($resql);
345 $nbtotalofrecords = $objforcount->nbtotalofrecords;
346 } else {
348 }
349
350 if (($page * $limit) > (int) $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
351 $page = 0;
352 $offset = 0;
353 }
354 $db->free($resql);
355}
356
357// Complete request and execute it with limit
358$sql .= $db->order($sortfield, $sortorder);
359if ($limit) {
360 $sql .= $db->plimit($limit + 1, $offset);
361}
362
363$resql = $db->query($sql);
364if (!$resql) {
366 exit;
367}
368
369$num = $db->num_rows($resql);
370
371
372// Direct jump if only one record found
373if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
374 $obj = $db->fetch_object($resql);
375 $id = $obj->rowid;
376 header("Location: ".dol_buildpath('/hrm/job_card.php', 1).'?id='.((int) $id));
377 exit;
378}
379
380
381// Output page
382// --------------------------------------------------------------------
383
384llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'mod-hrm page-list bodyforlist');
385
386// Example : Adding jquery code
387// print '<script type="text/javascript">
388// jQuery(document).ready(function() {
389// function init_myfunc()
390// {
391// jQuery("#myid").removeAttr(\'disabled\');
392// jQuery("#myid").attr(\'disabled\',\'disabled\');
393// }
394// init_myfunc();
395// jQuery("#mybutton").click(function() {
396// init_myfunc();
397// });
398// });
399// </script>';
400
401$arrayofselected = is_array($toselect) ? $toselect : array();
402
403$param = '';
404if (!empty($mode)) {
405 $param .= '&mode='.urlencode($mode);
406}
407if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
408 $param .= '&contextpage='.urlencode($contextpage);
409}
410if ($limit > 0 && $limit != $conf->liste_limit) {
411 $param .= '&limit='.((int) $limit);
412}
413if ($optioncss != '') {
414 $param .= '&optioncss='.urlencode($optioncss);
415}
416if ($groupby != '') {
417 $param .= '&groupby='.urlencode($groupby);
418}
419foreach ($search as $key => $val) {
420 if (is_array($search[$key])) {
421 foreach ($search[$key] as $skey) {
422 if ($skey != '') {
423 $param .= '&search_'.$key.'[]='.urlencode($skey);
424 }
425 }
426 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
427 $param .= '&search_'.$key.'month='.GETPOSTINT('search_'.$key.'month');
428 $param .= '&search_'.$key.'day='.GETPOSTINT('search_'.$key.'day');
429 $param .= '&search_'.$key.'year='.GETPOSTINT('search_'.$key.'year');
430 } elseif ($search[$key] != '') {
431 $param .= '&search_'.$key.'='.urlencode($search[$key]);
432 }
433}
434// Add $param from extra fields
435include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
436// Add $param from hooks
437$parameters = array('param' => &$param);
438$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
439$param .= $hookmanager->resPrint;
440
441// List of mass actions available
442$arrayofmassactions = array(
443 //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
444 //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
445 //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
446 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
447);
448if (!empty($permissiontodelete)) {
449 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
450}
451if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
452 $arrayofmassactions = array();
453}
454$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
455
456print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
457if ($optioncss != '') {
458 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
459}
460print '<input type="hidden" name="token" value="'.newToken().'">';
461print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
462print '<input type="hidden" name="action" value="list">';
463print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
464print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
465print '<input type="hidden" name="page" value="'.$page.'">';
466print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
467print '<input type="hidden" name="mode" value="'.$mode.'">';
468
469
470$newcardbutton = '';
471$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'));
472$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'));
473$newcardbutton .= dolGetButtonTitleSeparator();
474$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/job_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
475
476print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
477
478// Add code for pre mass action (confirmation or email presend form)
479$topicmail = "SendJobRef";
480$modelmail = "job";
481$objecttmp = new Job($db);
482$trackid = 'xxxx'.$object->id;
483include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
484
485if ($search_all) {
486 $setupstring = '';
487 // @phan-suppress-next-line PhanEmptyForeach
488 foreach ($fieldstosearchall as $key => $val) {
489 $fieldstosearchall[$key] = $langs->trans($val);
490 $setupstring .= $key."=".$val.";";
491 }
492 print '<!-- Search done like if JOBPOSITION_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
493 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>';
494}
495
496$moreforfilter = '';
497/*$moreforfilter.='<div class="divsearchfield">';
498$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
499$moreforfilter.= '</div>';*/
500
501$parameters = array();
502$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
503if (empty($reshook)) {
504 $moreforfilter .= $hookmanager->resPrint;
505} else {
506 $moreforfilter = $hookmanager->resPrint;
507}
508$parameters = array(
509 'arrayfields' => &$arrayfields,
510);
511
512if (!empty($moreforfilter)) {
513 print '<div class="liste_titre liste_titre_bydiv centpercent">';
514 print $moreforfilter;
515 print '</div>';
516}
517
518$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
519$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column); // This also change content of $arrayfields with user setup
520$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
521$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
522
523print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
524print '<table class="tagtable nobottomiftotal noborder liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
525
526
527// Fields title search
528// --------------------------------------------------------------------
529print '<tr class="liste_titre_filter">';
530// Action column
531if ($conf->main_checkbox_left_column) {
532 print '<td class="liste_titre center maxwidthsearch">';
533 $searchpicto = $form->showFilterButtons('left');
534 print $searchpicto;
535 print '</td>';
536}
537foreach ($object->fields as $key => $val) {
538 //$searchkey = empty($search[$key]) ? '' : $search[$key];
539 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
540 if ($key == 'status') {
541 $cssforfield .= ($cssforfield ? ' ' : '').'center';
542 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
543 $cssforfield .= ($cssforfield ? ' ' : '').'center';
544 } elseif (in_array($val['type'], array('timestamp'))) {
545 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
546 } 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'])) {
547 $cssforfield .= ($cssforfield ? ' ' : '').'right';
548 }
549 if (!empty($arrayfields['t.'.$key]['checked'])) {
550 print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
551 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
552 if (empty($val['searchmulti'])) {
553 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);
554 } else {
555 print $form->multiselectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 0, 0, 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
556 }
557 } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
558 print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
559 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
560 print '<div class="nowrap">';
561 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
562 print '</div>';
563 print '<div class="nowrap">';
564 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
565 print '</div>';
566 } elseif ($key == 'lang') {
567 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
568 $formadmin = new FormAdmin($db);
569 print $formadmin->select_language((isset($search[$key]) ? $search[$key] : ''), 'search_lang', 0, array(), 1, 0, 0, 'minwidth100imp maxwidth125', 2);
570 } elseif ($val['type'] === 'boolean') {
571 print $form->selectyesno('search_' . $key, $search[$key] ?? '', 1, false, 1);
572 } else {
573 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] : '').'">';
574 }
575 print '</td>';
576 }
577}
578// Extra fields
579include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
580// Fields from hook
581$parameters = array('arrayfields' => $arrayfields);
582$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
583print $hookmanager->resPrint;
584
585print '<td class="liste_titre"></td>';
586
587// Action column
588if (!$conf->main_checkbox_left_column) {
589 print '<td class="liste_titre center maxwidthsearch">';
590 $searchpicto = $form->showFilterButtons();
591 print $searchpicto;
592 print '</td>';
593}
594print '</tr>'."\n";
595
596$totalarray = array();
597$totalarray['nbfield'] = 0;
598
599// Fields title label
600// --------------------------------------------------------------------
601print '<tr class="liste_titre">';
602// Action column
603if ($conf->main_checkbox_left_column) {
604 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
605 $totalarray['nbfield']++;
606}
607foreach ($object->fields as $key => $val) {
608 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
609 if ($key == 'status') {
610 $cssforfield .= ($cssforfield ? ' ' : '').'center';
611 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
612 $cssforfield .= ($cssforfield ? ' ' : '').'center';
613 } elseif (in_array($val['type'], array('timestamp'))) {
614 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
615 } 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'])) {
616 $cssforfield .= ($cssforfield ? ' ' : '').'right';
617 }
618 $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label
619 if (!empty($arrayfields['t.'.$key]['checked'])) {
620 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";
621 $totalarray['nbfield']++;
622 }
623}
624// Extra fields
625include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
626// Hook fields
627$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
628$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
629print $hookmanager->resPrint;
630
631print '<th class="liste_titre right">'.$langs->trans("NbOfExpectedSkills").'</th>';
632$totalarray['nbfield']++;
633
634// Action column
635if (!$conf->main_checkbox_left_column) {
636 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
637 $totalarray['nbfield']++;
638}
639print '</tr>'."\n";
640
641
642// Detect if we need a fetch on each output line
643$needToFetchEachLine = 0;
644if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
645 foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
646 if (!is_null($val) && preg_match('/\$object/', $val)) {
647 $needToFetchEachLine++; // There is at least one compute field that use $object
648 }
649 }
650}
651
652
653// Loop on record
654// --------------------------------------------------------------------
655$i = 0;
656$savnbfield = $totalarray['nbfield'];
657$totalarray = array();
658$totalarray['nbfield'] = 0;
659$imaxinloop = ($limit ? min($num, $limit) : $num);
660while ($i < $imaxinloop) {
661 $obj = $db->fetch_object($resql);
662 if (empty($obj)) {
663 break; // Should not happen
664 }
665
666 // Store properties in $object
667 $object->setVarsFromFetchObj($obj);
668
669 if ($mode == 'kanban') {
670 $object->deplacement = $obj->deplacement;
671 $object->description = $obj->description;
672
673 if ($i == 0) {
674 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
675 print '<div class="box-flex-container kanban">';
676 }
677 // Output Kanban
678 $selected = -1;
679 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
680 $selected = 0;
681 if (in_array($object->id, $arrayofselected)) {
682 $selected = 1;
683 }
684 }
685 print $object->getKanbanView('', array('selected' => $selected));
686 if ($i == ($imaxinloop - 1)) {
687 print '</div>';
688 print '</td></tr>';
689 }
690 } else {
691 // Show line of result
692 $j = 0;
693 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
694 // Action column
695 if ($conf->main_checkbox_left_column) {
696 print '<td class="nowrap center">';
697 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
698 $selected = 0;
699 if (in_array($object->id, $arrayofselected)) {
700 $selected = 1;
701 }
702 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
703 }
704 print '</td>';
705 if (!$i) {
706 $totalarray['nbfield']++;
707 }
708 }
709 // Fields
710 foreach ($object->fields as $key => $val) {
711 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
712 if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
713 $cssforfield .= ($cssforfield ? ' ' : '').'center';
714 } elseif ($key == 'status') {
715 $cssforfield .= ($cssforfield ? ' ' : '').'center';
716 }
717
718 if (in_array($val['type'], array('timestamp'))) {
719 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
720 } elseif ($key == 'ref') {
721 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
722 }
723
724 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'])) {
725 $cssforfield .= ($cssforfield ? ' ' : '').'right';
726 }
727 //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100';
728
729 if (!empty($arrayfields['t.'.$key]['checked'])) {
730 print '<td'.($cssforfield ? ' class="'.$cssforfield.((preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key)) ? ' classfortooltip' : '').'"' : '');
731 if (preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key) && !in_array($key, array('ref'))) {
732 print ' title="'.dol_escape_htmltag((string) $object->$key).'"';
733 }
734 print '>';
735 if ($key == 'status') {
736 print $object->getLibStatut(5);
737 } elseif ($key == 'rowid') {
738 print $object->showOutputField($val, $key, (string) $object->id, '');
739 } elseif ($key == 'label') {
740 print $object->getNomUrl(1);
741 } else {
742 print $object->showOutputField($val, $key, (string) $object->$key, '');
743 }
744 print '</td>';
745 if (!$i) {
746 $totalarray['nbfield']++;
747 }
748 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
749 if (!$i) {
750 $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
751 }
752 if (!isset($totalarray['val'])) {
753 $totalarray['val'] = array();
754 }
755 if (!isset($totalarray['val']['t.'.$key])) {
756 $totalarray['val']['t.'.$key] = 0;
757 }
758 $totalarray['val']['t.'.$key] += $object->$key;
759 }
760 }
761 }
762 // Extra fields
763 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
764 // Fields from hook
765 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
766 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
767 print $hookmanager->resPrint;
768
769 /*if (!empty($arrayfields['anotherfield']['checked'])) {
770 print '<td class="right">'.$obj->anotherfield.'</td>';
771 }*/
772 print '<td class="right">'.$obj->nbofskills.'</td>';
773
774 // Action column
775 if (empty($conf->main_checkbox_left_column)) {
776 print '<td class="nowrap center">';
777 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
778 $selected = 0;
779 if (in_array($object->id, $arrayofselected)) {
780 $selected = 1;
781 }
782 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
783 }
784 print '</td>';
785 if (!$i) {
786 $totalarray['nbfield']++;
787 }
788 }
789
790 print '</tr>'."\n";
791 }
792
793 $i++;
794}
795
796// Show total line
797include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
798
799// If no record found
800if ($num == 0) {
801 $colspan = 1;
802 foreach ($arrayfields as $key => $val) {
803 if (!empty($val['checked'])) {
804 $colspan++;
805 }
806 }
807 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
808}
809
810
811$db->free($resql);
812
813$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
814$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
815print $hookmanager->resPrint;
816
817print '</table>'."\n";
818print '</div>'."\n";
819
820print '</form>'."\n";
821
822if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
823 $hidegeneratedfilelistifempty = 1;
824 if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
825 $hidegeneratedfilelistifempty = 0;
826 }
827
828 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
829 $formfile = new FormFile($db);
830
831 // Show list of available documents
832 $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
833 $urlsource .= str_replace('&amp;', '&', $param);
834
835 $filedir = $diroutputmassaction;
836 $genallowed = $permissiontoread;
837 $delallowed = $permissiontoadd;
838
839 print $formfile->showdocuments('massfilesarea_hrm', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
840}
841
842// End of page
843llxFooter();
844$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
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.