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