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