dolibarr 23.0.3
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 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 if ($field_spec === null) {
270 continue;
271 }
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 {
347 dol_print_error($db);
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) {
365 dol_print_error($db);
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 export.php:1216
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
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.
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.
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.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
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...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.