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