dolibarr 21.0.0-alpha
bom_list.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 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 a 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// Add table from hooks
314$parameters = array();
315$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
316$sql .= $hookmanager->resPrint;
317if ($object->ismultientitymanaged == 1) {
318 $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
319} else {
320 $sql .= " WHERE 1 = 1";
321}
322foreach ($search as $key => $val) {
323 if (array_key_exists($key, $object->fields)) {
324 if ($key == 'status' && $search[$key] == -1) {
325 continue;
326 }
327 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
328 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
329 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
330 $search[$key] = '';
331 }
332 $mode_search = 2;
333 }
334 if ($search[$key] != '') {
335 $sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
336 }
337 } else {
338 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
339 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
340 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
341 if (preg_match('/_dtstart$/', $key)) {
342 $sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
343 }
344 if (preg_match('/_dtend$/', $key)) {
345 $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
346 }
347 }
348 }
349 }
350}
351
352if ($search_all) {
353 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
354}
355//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
356// Add where from extra fields
357include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
358// Add where from hooks
359$parameters = array();
360$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
361$sql .= $hookmanager->resPrint;
362
363/* If a group by is required
364$sql.= " GROUP BY ";
365foreach($object->fields as $key => $val) {
366 $sql .= "t.".$db->escape($key).", ";
367}
368// Add fields from extrafields
369if (!empty($extrafields->attributes[$object->table_element]['label'])) {
370 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
371 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
372 }
373}
374// Add groupby from hooks
375$parameters=array();
376$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
377$sql.=$hookmanager->resPrint;
378$sql=preg_replace('/,\s*$/','', $sql);
379*/
380
381// Count total nb of records
382$nbtotalofrecords = '';
383if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
384 /* The fast and low memory method to get and count full list converts the sql into a sql count */
385 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
386 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
387 $resql = $db->query($sqlforcount);
388 if ($resql) {
389 $objforcount = $db->fetch_object($resql);
390 $nbtotalofrecords = $objforcount->nbtotalofrecords;
391 } else {
392 dol_print_error($db);
393 }
394
395 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
396 $page = 0;
397 $offset = 0;
398 }
399 $db->free($resql);
400}
401
402// Complete request and execute it with limit
403$sql .= $db->order($sortfield, $sortorder);
404if ($limit) {
405 $sql .= $db->plimit($limit + 1, $offset);
406}
407
408$resql = $db->query($sql);
409if (!$resql) {
410 dol_print_error($db);
411 exit;
412}
413
414$num = $db->num_rows($resql);
415
416// Direct jump if only one record found
417if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
418 $obj = $db->fetch_object($resql);
419 $id = $obj->rowid;
420 header("Location: ".DOL_URL_ROOT.'/bom/bom_card.php?id='.((int) $id));
421 exit;
422}
423
424
425// Output page
426// --------------------------------------------------------------------
427
428llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'mod-bom page-list bodyforlist');
429
430$arrayofselected = is_array($toselect) ? $toselect : array();
431
432$param = '';
433if (!empty($mode)) {
434 $param .= '&mode='.urlencode($mode);
435}
436if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
437 $param .= '&contextpage='.urlencode($contextpage);
438}
439if ($limit > 0 && $limit != $conf->liste_limit) {
440 $param .= '&limit='.((int) $limit);
441}
442if ($optioncss != '') {
443 $param .= '&optioncss='.urlencode($optioncss);
444}
445foreach ($search as $key => $val) {
446 if (is_array($search[$key])) {
447 foreach ($search[$key] as $skey) {
448 if ($skey != '') {
449 $param .= '&search_'.$key.'[]='.urlencode($skey);
450 }
451 }
452 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
453 $param .= '&search_'.$key.'month='.(GETPOSTINT('search_'.$key.'month'));
454 $param .= '&search_'.$key.'day='.(GETPOSTINT('search_'.$key.'day'));
455 $param .= '&search_'.$key.'year='.(GETPOSTINT('search_'.$key.'year'));
456 } elseif ($search[$key] != '') {
457 $param .= '&search_'.$key.'='.urlencode($search[$key]);
458 }
459}
460// Add $param from extra fields
461include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
462// Add $param from hooks
463$parameters = array('param' => &$param);
464$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
465$param .= $hookmanager->resPrint;
466
467// List of mass actions available
468$arrayofmassactions = array(
469 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
470 'enable' => img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Enable"),
471 'disable' => img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Disable"),
472);
473if (!empty($permissiontodelete)) {
474 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
475}
476if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
477 $arrayofmassactions = array();
478}
479$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
480
481print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
482if ($optioncss != '') {
483 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
484}
485print '<input type="hidden" name="token" value="'.newToken().'">';
486print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
487print '<input type="hidden" name="action" value="list">';
488print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
489print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
490print '<input type="hidden" name="page" value="'.$page.'">';
491print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
492print '<input type="hidden" name="page_y" value="">';
493print '<input type="hidden" name="mode" value="'.$mode.'">';
494
495$newcardbutton = '';
496$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'));
497$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'));
498$newcardbutton .= dolGetButtonTitleSeparator();
499$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'));
500
501print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
502
503// Add code for pre mass action (confirmation or email presend form)
504$topicmail = "SendBillOfMaterialsRef";
505$modelmail = "bom";
506$objecttmp = new BOM($db);
507$trackid = 'bom'.$object->id;
508include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
509
510if ($search_all) {
511 $setupstring = '';
512 foreach ($fieldstosearchall as $key => $val) {
513 $fieldstosearchall[$key] = $langs->trans($val);
514 $setupstring .= $key."=".$val.";";
515 }
516 print '<!-- Search done like if BOM_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
517 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>'."\n";
518}
519
520$moreforfilter = '';
521/*$moreforfilter.='<div class="divsearchfield">';
522$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
523$moreforfilter.= '</div>';*/
524
525$parameters = array();
526$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
527if (empty($reshook)) {
528 $moreforfilter .= $hookmanager->resPrint;
529} else {
530 $moreforfilter = $hookmanager->resPrint;
531}
532
533if (!empty($moreforfilter)) {
534 print '<div class="liste_titre liste_titre_bydiv centpercent">';
535 print $moreforfilter;
536 $parameters = array();
537 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
538 print $hookmanager->resPrint;
539 print '</div>';
540}
541
542$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
543$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields with user setup
544$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
545$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
546
547print '<div class="div-table-responsive">';
548print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
549
550
551// Fields title search
552// --------------------------------------------------------------------
553print '<tr class="liste_titre_filter">';
554
555// Action column
556if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
557 print '<td class="liste_titre center maxwidthsearch">';
558 $searchpicto = $form->showFilterButtons('left');
559 print $searchpicto;
560 print '</td>';
561}
562
563foreach ($object->fields as $key => $val) {
564 $searchkey = empty($search[$key]) ? '' : $search[$key];
565 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
566 if ($key == 'status') {
567 $cssforfield .= ($cssforfield ? ' ' : '').'center';
568 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
569 $cssforfield .= ($cssforfield ? ' ' : '').'center';
570 } elseif (in_array($val['type'], array('timestamp'))) {
571 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
572 } 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'])) {
573 $cssforfield .= ($cssforfield ? ' ' : '').'right';
574 }
575 if (!empty($arrayfields['t.'.$key]['checked'])) {
576 print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
577 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
578 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);
579 } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
580 print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
581 } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
582 print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
583 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
584 print '<div class="nowrap">';
585 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
586 print '</div>';
587 print '<div class="nowrap">';
588 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
589 print '</div>';
590 } elseif ($key == 'lang') {
591 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
592 $formadmin = new FormAdmin($db);
593 print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth100imp maxwidth125', 2);
594 } else {
595 print '<input type="text" class="flat maxwidth75" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
596 }
597 print '</td>';
598 }
599}
600// Extra fields
601include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
602
603// Fields from hook
604$parameters = array('arrayfields' => $arrayfields);
605$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
606print $hookmanager->resPrint;
607// Action column
608if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
609 print '<td class="liste_titre center maxwidthsearch">';
610 $searchpicto = $form->showFilterButtons();
611 print $searchpicto;
612 print '</td>';
613}
614print '</tr>'."\n";
615
616$totalarray = array();
617$totalarray['nbfield'] = 0;
618
619// Fields title label
620// --------------------------------------------------------------------
621print '<tr class="liste_titre">';
622// Action column
623if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
624 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
625 $totalarray['nbfield']++;
626}
627foreach ($object->fields as $key => $val) {
628 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
629 if ($key == 'status') {
630 $cssforfield .= ($cssforfield ? ' ' : '').'center';
631 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
632 $cssforfield .= ($cssforfield ? ' ' : '').'center';
633 } elseif (in_array($val['type'], array('timestamp'))) {
634 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
635 } 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'])) {
636 $cssforfield .= ($cssforfield ? ' ' : '').'right';
637 }
638 $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label
639 if (!empty($arrayfields['t.'.$key]['checked'])) {
640 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";
641 $totalarray['nbfield']++;
642 }
643}
644// Extra fields
645include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
646// Hook fields
647$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
648$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
649print $hookmanager->resPrint;
650// Action column
651if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
652 print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
653 $totalarray['nbfield']++;
654}
655print '</tr>'."\n";
656
657
658// Detect if we need a fetch on each output line
659$needToFetchEachLine = 0;
660if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
661 foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
662 if (!is_null($val) && preg_match('/\$object/', $val)) {
663 $needToFetchEachLine++; // There is at least one compute field that use $object
664 }
665 }
666}
667
668
669// Loop on record
670// --------------------------------------------------------------------
671$i = 0;
672$savnbfield = $totalarray['nbfield'];
673$totalarray = array();
674$totalarray['nbfield'] = 0;
675$imaxinloop = ($limit ? min($num, $limit) : $num);
676while ($i < $imaxinloop) {
677 $obj = $db->fetch_object($resql);
678 if (empty($obj)) {
679 break; // Should not happen
680 }
681
682 // Store properties in $object
683 $object->setVarsFromFetchObj($obj);
684
685 // mode view kanban
686 if ($mode == 'kanban') {
687 if ($i == 0) {
688 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
689 print '<div class="box-flex-container kanban">';
690 }
691
692 // TODO Use a cache for product
693 if (!empty($obj->fk_product)) {
694 $prod = new Product($db);
695 $prod->fetch($obj->fk_product);
696 } else {
697 $prod = null;
698 }
699
700 // Output Kanban
701 $selected = -1;
702 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
703 $selected = 0;
704 if (in_array($object->id, $arrayofselected)) {
705 $selected = 1;
706 }
707 }
708 print $object->getKanbanView('', array('prod' => $prod, 'selected' => $selected));
709 if ($i == ($imaxinloop - 1)) {
710 print '</div>';
711 print '</td></tr>';
712 }
713 } else {
714 // Show line of result
715 $j = 0;
716 print '<tr data-rowid="'.$object->id.'" class="oddeven">';
717 // Action column
718 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
719 print '<td class="nowrap center">';
720 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
721 $selected = 0;
722 if (in_array($object->id, $arrayofselected)) {
723 $selected = 1;
724 }
725 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
726 }
727 print '</td>';
728 if (!$i) {
729 $totalarray['nbfield']++;
730 }
731 }
732 foreach ($object->fields as $key => $val) {
733 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
734 if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
735 $cssforfield .= ($cssforfield ? ' ' : '').'center';
736 } elseif ($key == 'status') {
737 $cssforfield .= ($cssforfield ? ' ' : '').'center';
738 }
739
740 if (in_array($val['type'], array('timestamp'))) {
741 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
742 } elseif ($key == 'ref') {
743 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
744 }
745
746 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'])) {
747 $cssforfield .= ($cssforfield ? ' ' : '').'right';
748 }
749
750 if (!empty($arrayfields['t.'.$key]['checked'])) {
751 print '<td'.($cssforfield ? ' class="'.$cssforfield.(preg_match('/tdoverflow/', $cssforfield) ? ' classfortooltip' : '').'"' : '');
752 if (preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key)) {
753 print ' title="'.dol_escape_htmltag($object->$key).'"';
754 }
755 print '>';
756 if ($key == 'status') {
757 print $object->getLibStatut(5);
758 } elseif ($key == 'rowid') {
759 print $object->showOutputField($val, $key, $object->id, '');
760 } else {
761 print $object->showOutputField($val, $key, $object->$key, '');
762 }
763 print '</td>';
764 if (!$i) {
765 $totalarray['nbfield']++;
766 }
767 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
768 if (!$i) {
769 $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
770 }
771 if (!isset($totalarray['val'])) {
772 $totalarray['val'] = array();
773 }
774 if (!isset($totalarray['val']['t.'.$key])) {
775 $totalarray['val']['t.'.$key] = 0;
776 }
777 $totalarray['val']['t.'.$key] += $object->$key;
778 }
779 }
780 }
781 // Extra fields
782 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
783 // Fields from hook
784 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
785 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
786 print $hookmanager->resPrint;
787 // Action column
788 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
789 print '<td class="nowrap center">';
790 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
791 $selected = 0;
792 if (in_array($object->id, $arrayofselected)) {
793 $selected = 1;
794 }
795 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
796 }
797 print '</td>';
798 if (!$i) {
799 $totalarray['nbfield']++;
800 }
801 }
802
803 print '</tr>'."\n";
804 }
805
806 $i++;
807}
808
809// Show total line
810include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
811
812
813// If no record found
814if ($num == 0) {
815 $colspan = 1;
816 foreach ($arrayfields as $key => $val) {
817 if (!empty($val['checked'])) {
818 $colspan++;
819 }
820 }
821 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
822}
823
824
825$db->free($resql);
826
827$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
828$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
829print $hookmanager->resPrint;
830
831print '</table>'."\n";
832print '</div>'."\n";
833
834print '</form>'."\n";
835
836
837if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
838 $hidegeneratedfilelistifempty = 1;
839 if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
840 $hidegeneratedfilelistifempty = 0;
841 }
842
843 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
844 $formfile = new FormFile($db);
845
846 // Show list of available documents
847 $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
848 $urlsource .= str_replace('&amp;', '&', $param);
849
850 $filedir = $diroutputmassaction;
851 $genallowed = $permissiontoread;
852 $delallowed = $permissiontoadd;
853
854 print $formfile->showdocuments('massfilesarea_bom', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
855}
856
857// End of page
858llxFooter();
859$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($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:70
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.
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...
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.