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