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