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