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