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