dolibarr 25.0.0-alpha
myobject_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-2026 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) ---Replace with your own copyright and developer email---
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// General defined Options
27//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET
28//if (! defined('MAIN_AUTHENTICATION_MODE')) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler
29//if (! defined('MAIN_LANG_DEFAULT')) define('MAIN_LANG_DEFAULT', 'auto'); // Force LANG (language) to a particular value
30//if (! defined('MAIN_SECURITY_FORCECSP')) define('MAIN_SECURITY_FORCECSP', 'none'); // Disable all Content Security Policies
31//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification
32//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
33//if (! defined('NOLOGIN')) define('NOLOGIN', '1'); // Do not use login - if this page is public (can be called outside logged session). This includes the NOIPCHECK too.
34//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
35//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db
36//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // Do not load html.form.class.php
37//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // Do not load and show top and left menu
38//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc
39//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs
40//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user
41//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters
42//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters
43//if (! defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions
44//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data
45//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on)
46
47
48// Load Dolibarr environment
49$res = 0;
50// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
51if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
52 $res = @include str_replace("..", "", $_SERVER["CONTEXT_DOCUMENT_ROOT"])."/main.inc.php";
53}
54// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
55$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
56$tmp2 = realpath(__FILE__);
57$i = strlen($tmp) - 1; // @phan-suppress-current-line DolibarrForbiddenFunctionPlugin
58$j = strlen($tmp2) - 1; // @phan-suppress-current-line DolibarrForbiddenFunctionPlugin
59while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
60 $i--;
61 $j--;
62}
63if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
64 $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
65}
66if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
67 $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
68}
69// Try main.inc.php using relative path
70if (!$res && file_exists("../main.inc.php")) {
71 $res = @include "../main.inc.php";
72}
73if (!$res && file_exists("../../main.inc.php")) {
74 $res = @include "../../main.inc.php";
75}
76if (!$res && file_exists("../../../main.inc.php")) {
77 $res = @include "../../../main.inc.php";
78}
79if (!$res) {
80 die("Include of main fails");
81}
90require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php';
91include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
92include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
93include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
94// load module libraries
95include_once __DIR__.'/class/myobject.class.php';
96// for other modules
97//dol_include_once('/othermodule/class/otherobject.class.php');
98
99// Load translation files required by the page
100$langs->loadLangs(array("mymodule@mymodule", "other"));
101
102// Get parameters
103$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'create'/'add', 'edit'/'update', 'view', ...
104$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
105$show_files = GETPOSTINT('show_files'); // Show files area generated by bulk actions ?
106$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
107$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button
108$toselect = GETPOST('toselect', 'array:int'); // Array of ids of elements selected into a list
109$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : getDolDefaultContextPage(__FILE__); // To manage different context of search
110$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
111$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
112$mode = GETPOST('mode', 'aZ'); // The display mode ('list', 'kanban', 'hierarchy', 'calendar', 'gantt', ...)
113$groupby = GETPOST('groupby', 'aZ09'); // Example: $groupby = 'p.fk_opp_status' or $groupby = 'p.fk_statut'
114
115$id = GETPOSTINT('id');
116$ref = GETPOST('ref', 'alpha');
117
118// Load variable for pagination
119$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
120$sortfield = GETPOST('sortfield', 'aZ09comma');
121$sortorder = GETPOST('sortorder', 'aZ09comma');
122$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
123if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
124 // If $page is not defined, or '' or -1 or if we click on clear filters
125 $page = 0;
126}
127$offset = $limit * $page;
128$pageprev = $page - 1;
129$pagenext = $page + 1;
130
131// Initialize technical objects
132$object = new MyObject($db);
133$extrafields = new ExtraFields($db);
134$diroutputmassaction = $conf->mymodule->dir_output.'/temp/massgeneration/'.$user->id;
135$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes
136
137// Fetch optionals attributes and labels
138$extrafields->fetch_name_optionals_label($object->table_element);
139//$extrafields->fetch_name_optionals_label($object->table_element_line);
140
141$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
142
143// Default sort order (if not yet defined by previous GETPOST)
144if (!$sortfield) {
145 reset($object->fields); // Reset is required to avoid key() to return null.
146 $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition.
147}
148if (!$sortorder) {
149 $sortorder = "ASC";
150}
151
152// Initialize array of search criteria
153$search_all = trim(GETPOST('search_all', 'alphanohtml'));
154$search = array();
155foreach ($object->fields as $key => $val) {
156 if (GETPOST('search_'.$key, 'alpha') !== '') {
157 $search[$key] = GETPOST('search_'.$key, 'alpha');
158 }
159 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
160 $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOSTINT('search_'.$key.'_dtstartmonth'), GETPOSTINT('search_'.$key.'_dtstartday'), GETPOSTINT('search_'.$key.'_dtstartyear'));
161 $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOSTINT('search_'.$key.'_dtendmonth'), GETPOSTINT('search_'.$key.'_dtendday'), GETPOSTINT('search_'.$key.'_dtendyear'));
162 }
163}
164
165// List of fields to search into when doing a "search in all"
166$fieldstosearchall = array();
167// foreach ($object->fields as $key => $val) {
168// if (!empty($val['searchall'])) {
169// $fieldstosearchall['t.'.$key] = $val['label'];
170// }
171// }
172// $parameters = array('fieldstosearchall'=>$fieldstosearchall);
173// $reshook = $hookmanager->executeHooks('completeFieldsToSearchAll', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
174// if ($reshook > 0) {
175// $fieldstosearchall = empty($hookmanager->resArray['fieldstosearchall']) ? array() : $hookmanager->resArray['fieldstosearchall'];
176// } elseif ($reshook == 0) {
177// $fieldstosearchall = array_merge($fieldstosearchall, empty($hookmanager->resArray['fieldstosearchall']) ? array() : $hookmanager->resArray['fieldstosearchall']);
178// }
179
180// Definition of array of fields for columns from ->fields
181$tableprefix = 't';
182$arrayfields = array();
183foreach ($object->fields as $key => $val) {
184 // If $val['visible']==0, then we never show the field
185 if (!empty($val['visible'])) {
186 $visible = (int) dol_eval((string) $val['visible'], 1);
187 $arrayfields[$tableprefix.'.'.$key] = array(
188 'label' => $val['label'],
189 'checked' => (($visible < 0) ? '0' : '1'),
190 'enabled' => (string) (int) (abs($visible) != 3 && (bool) dol_eval((string) $val['enabled'], 1)),
191 'position' => $val['position'],
192 'help' => isset($val['help']) ? $val['help'] : ''
193 );
194 }
195}
196
197// Extra fields
198include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
199// Add hook to complete $arrayfield
200$parameters = array('arrayfields' => &$arrayfields);
201$reshook = $hookmanager->executeHooks('completeArrayFields', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
202
203// Complete arrayfields with special fields
204/*$arrayfields = array_merge($arrayfields, array(
205 'anotherfield' => array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>'1', 'enabled'=>'1', 'position'=>'90', 'csslist'=>'right'),
206));*/
207
208// Change position of fields in arrayfield and object
209include DOL_DOCUMENT_ROOT.'/core/tpl/arrayfield_object_position_fields.tpl.php';
210
211$object->fields = dol_sort_array($object->fields, 'position');
212$arrayfields = dol_sort_array($arrayfields, 'position');
213
214// There is several ways to check permission.
215// Set $enablepermissioncheck to 1 to enable a minimum low level of checks
216$enablepermissioncheck = getDolGlobalInt('MYMODULE_ENABLE_PERMISSION_CHECK');
217if ($enablepermissioncheck) {
218 $permissiontoread = $user->hasRight('mymodule', 'myobject', 'read');
219 $permissiontoadd = $user->hasRight('mymodule', 'myobject', 'write');
220 $permissiontodelete = $user->hasRight('mymodule', 'myobject', 'delete');
221} else {
222 $permissiontoread = 1;
223 $permissiontoadd = 1;
224 $permissiontodelete = 1;
225}
226
227// Security check (enable the most restrictive one)
228if ($user->socid > 0) {
230}
231//if ($user->socid > 0) accessforbidden();
232//$socid = 0; if ($user->socid > 0) $socid = $user->socid;
233//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
234//restrictedArea($user, $object->module, 0, $object->table_element, $object->element, 'fk_soc', 'rowid', $isdraft);
235if (!isModEnabled("mymodule")) {
236 accessforbidden('Module mymodule not enabled');
237}
238if (!$permissiontoread) {
240}
241
242
243/*
244 * Actions
245 */
246
247if (GETPOST('cancel', 'alpha')) {
248 $action = 'list';
249 $massaction = '';
250}
251if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
252 $massaction = '';
253}
254
255$parameters = array('arrayfields' => &$arrayfields);
256$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
257if ($reshook < 0) {
258 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
259}
260
261if (empty($reshook)) {
262 // Selection of new fields
263 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
264
265 // Purge search criteria
266 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
267 foreach ($object->fields as $key => $val) {
268 $search[$key] = '';
269 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
270 $search[$key.'_dtstart'] = '';
271 $search[$key.'_dtend'] = '';
272 }
273 }
274 $search_all = '';
275 $toselect = array();
276 $search_array_options = array();
277 }
278 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
279 || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
280 $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
281 }
282
283 // Mass actions
284 $objectclass = 'MyObject';
285 $objectlabel = 'MyObject';
286 $uploaddir = $conf->mymodule->dir_output;
287
288 global $error;
289 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
290
291 // You can add more action here
292 // if ($action == 'xxx' && $permissiontoxxx) ...
293}
294
295
296
297/*
298 * View
299 */
300
301$form = new Form($db);
302
303$now = dol_now();
304
305$title = $langs->trans("MyObjects");
306//$help_url = "EN:Module_MyObject|FR:Module_MyObject_FR|ES:Módulo_MyObject";
307$help_url = '';
308$morejs = array();
309$morecss = array();
310
311
312// Build and execute select
313// --------------------------------------------------------------------
314$sql = "SELECT";
315$sql .= " ".$object->getFieldList('t');
316// Add fields from extrafields
317if (!empty($extrafields->attributes[$object->table_element]['label'])) {
318 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
319 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : "");
320 }
321}
322// Add fields from hooks
323$parameters = array();
324$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
325$sql .= $hookmanager->resPrint;
326$sql = preg_replace('/,\s*$/', '', $sql);
327
328$sqlfields = $sql; // $sql fields to remove for count total
329
330$sql .= " FROM ".$db->prefix().$object->table_element." as t";
331//$sql .= " LEFT JOIN ".$db->prefix()."anothertable as rc ON rc.parent = t.rowid";
332if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
333 $sql .= " LEFT JOIN ".$db->prefix().$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
334}
335// Add table from hooks
336$parameters = array();
337$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
338$sql .= $hookmanager->resPrint;
339
340if (!empty($object->ismultientitymanaged) && (int) $object->ismultientitymanaged == 1) {
341 $sql .= " WHERE t.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
342} elseif (preg_match('/^\w+@\w+$/', (string) $object->ismultientitymanaged)) {
343 $tmparray = explode('@', (string) $object->ismultientitymanaged);
344 $sql .= " LEFT JOIN ".$object->db->prefix().$db->sanitize($tmparray[1])." as pt ON t.".$db->sanitize($tmparray[0])." = pt.rowid";
345 $sql .= " WHERE pt.entity IN (".getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)).")";
346} else {
347 $sql .= " WHERE 1 = 1";
348}
349foreach ($search as $key => $val) {
350 if (array_key_exists($key, $object->fields)) {
351 if ($key == 'status' && $search[$key] == -1) {
352 continue;
353 }
354 $field_spec = $object->fields[$key];
355 // Ignore false positive @phan-suppress-next-line PhanTypeMismatchArgumentNullable
356 $mode_search = (($object->isInt($field_spec) || $object->isFloat($field_spec)) ? 1 : 0);
357 if ((strpos($field_spec['type'], 'integer:') === 0) || (strpos($field_spec['type'], 'sellist:') === 0) || !empty($field_spec['arrayofkeyval'])) {
358 if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($field_spec['arrayofkeyval']) || !array_key_exists('0', $field_spec['arrayofkeyval'])))) {
359 $search[$key] = '';
360 }
361 $mode_search = 2;
362 }
363 if ($field_spec['type'] === 'boolean') {
364 $mode_search = 1;
365 if ($search[$key] == '-1') {
366 $search[$key] = '';
367 }
368 }
369 if (empty($field_spec['searchmulti'])) {
370 if (!is_array($search[$key]) && $search[$key] != '') {
371 $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
372 }
373 } else {
374 if (is_array($search[$key]) && !empty($search[$key])) {
375 $sql .= natural_search("t.".$db->escape($key), implode(',', $search[$key]), (($key == 'status') ? 2 : $mode_search));
376 }
377 }
378 } else {
379 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
380 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
381 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
382 if (preg_match('/_dtstart$/', $key)) {
383 $sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
384 }
385 if (preg_match('/_dtend$/', $key)) {
386 $sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
387 }
388 }
389 }
390 }
391}
392if ($search_all) {
393 $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
394}
395/*
396// If the internal user must only see his customers, force searching by him
397$search_sale = 0;
398if (!$user->hasRight('societe', 'client', 'voir')) {
399 $search_sale = $user->id;
400}
401// Search on sale representative
402if ($search_sale && $search_sale != '-1') {
403 if ($search_sale == -2) {
404 $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".$db->prefix()."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
405 } elseif ($search_sale > 0) {
406 $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".$db->prefix()."societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = ".((int) $search_sale).")";
407 }
408}
409// Search on socid
410if ($socid) {
411 $sql .= " AND t.fk_soc = ".((int) $socid);
412}
413*/
414//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear);
415// Add where from extra fields
416include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
417// Add where from hooks
418$parameters = array();
419$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
420$sql .= $hookmanager->resPrint;
421
422/* If a group by is required
423$sql .= " GROUP BY ";
424foreach($object->fields as $key => $val) {
425 $sql .= "t.".$db->sanitize($key).", ";
426}
427// Add fields from extrafields
428if (!empty($extrafields->attributes[$object->table_element]['label'])) {
429 foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
430 $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : '');
431 }
432}
433// Add groupby from hooks
434$parameters = array();
435$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
436if (empty($reshook)) {
437 $sql .= $hookmanager->resPrint;
438} else {
439 $sql = $hookmanager->resPrint;
440}
441
442$sql = preg_replace('/,\s*$/', '', $sql);
443*/
444
445// Add HAVING from hooks
446/*
447$parameters = array();
448$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
449if (empty($reshook)) {
450 $sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
451} else {
452 $sql = $hookmanager->resPrint;
453}
454*/
455
456// Count total nb of records
457$nbtotalofrecords = '';
458if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
459 /* The fast and low memory method to get and count full list converts the sql into a sql count */
460 $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
461 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
462
463 $resql = $db->query($sqlforcount);
464 if ($resql) {
465 $objforcount = $db->fetch_object($resql);
466 $nbtotalofrecords = $objforcount->nbtotalofrecords;
467 } else {
468 dol_print_error($db);
469 }
470
471 if (($page * $limit) > (int) $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
472 $page = 0;
473 $offset = 0;
474 }
475 $db->free($resql);
476}
477
478// Complete request and execute it with limit
479$sql .= $db->order($sortfield, $sortorder);
480if ($limit) {
481 $sql .= $db->plimit($limit + 1, $offset);
482}
483
484$resql = $db->query($sql);
485if (!$resql) {
486 dol_print_error($db);
487 exit;
488}
489
490$num = $db->num_rows($resql);
491
492
493// Direct jump if only one record found
494if ($num == 1 && getDolGlobalInt('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $search_all && !$page) {
495 $obj = $db->fetch_object($resql);
496 $id = $obj->rowid;
497 header("Location: ".dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.((int) $id));
498 exit;
499}
500
501
502// Example : Adding jquery code
503// print '<script type="text/javascript">
504// jQuery(document).ready(function() {
505// function init_myfunc()
506// {
507// jQuery("#myid").removeAttr(\'disabled\');
508// jQuery("#myid").attr(\'disabled\',\'disabled\');
509// }
510// init_myfunc();
511// jQuery("#mybutton").click(function() {
512// init_myfunc();
513// });
514// });
515// </script>';
516
517$arrayofselected = is_array($toselect) ? $toselect : array();
518
519$param = '';
520if (!empty($mode)) {
521 $param .= '&mode='.urlencode($mode);
522}
523if (!empty($contextpage) && $contextpage != getDolDefaultContextPage(__FILE__)) {
524 $param .= '&contextpage='.urlencode($contextpage);
525}
526if ($limit > 0 && $limit != $conf->liste_limit) {
527 $param .= '&limit='.((int) $limit);
528}
529if ($optioncss != '') {
530 $param .= '&optioncss='.urlencode($optioncss);
531}
532if ($groupby != '') {
533 $param .= '&groupby='.urlencode($groupby);
534}
535if ($search_all != '') {
536 $param .= '&search_all='.urlencode($search_all);
537}
538foreach ($search as $key => $val) {
539 if (is_array($search[$key])) {
540 foreach ($search[$key] as $skey) {
541 if ($skey != '') {
542 $param .= '&search_'.$key.'[]='.urlencode($skey);
543 }
544 }
545 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
546 $param .= '&search_'.$key.'month='.GETPOSTINT('search_'.$key.'month');
547 $param .= '&search_'.$key.'day='.GETPOSTINT('search_'.$key.'day');
548 $param .= '&search_'.$key.'year='.GETPOSTINT('search_'.$key.'year');
549 } elseif ($search[$key] != '') {
550 $param .= '&search_'.$key.'='.urlencode((string) $search[$key]);
551 }
552}
553// Add $param from extra fields
554include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
555// Add $param from hooks
556$parameters = array('param' => &$param);
557$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
558$param .= $hookmanager->resPrint;
559
560// Use Post/Redirect/Get for filter submissions so browser history contains a
561// reconstructible GET request instead of a POST that requires confirmation.
562$filterSearchSubmitted = GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha');
563$filterResetSubmitted = GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha');
564if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($filterSearchSubmitted || $filterResetSubmitted)) {
565 $redirectUrl = dolBuildUrl($_SERVER['PHP_SELF'], array(
566 'formfilteraction' => 'list',
567 'sortfield' => $sortfield,
568 'sortorder' => $sortorder,
569 ));
570 $redirectUrl .= $param;
571 header('Location: '.$redirectUrl, true, 303);
572 exit;
573}
574
575// Output page
576// --------------------------------------------------------------------
577
578llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'mod-mymodule page-list bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for a horizontal scroll in the table instead of page
579
580// List of mass actions available
581$arrayofmassactions = array(
582 //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"),
583 //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
584 //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
585 //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
586);
587if (!empty($permissiontodelete)) {
588 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
589}
590if (GETPOSTINT('nomassaction') || in_array($massaction, array('presend', 'predelete'))) {
591 $arrayofmassactions = array();
592}
593$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
594
595print '<form method="POST" id="searchFormList" spellcheck="false" action="'.$_SERVER["PHP_SELF"].'">'."\n";
596if ($optioncss != '') {
597 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
598}
599print '<input type="hidden" name="token" value="'.newToken().'">';
600print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
601print '<input type="hidden" name="action" value="list">';
602print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
603print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
604print '<input type="hidden" name="page" value="'.$page.'">';
605print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
606print '<input type="hidden" name="page_y" value="">';
607print '<input type="hidden" name="mode" value="'.$mode.'">';
608
609
610$newcardbutton = '';
611$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
612$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
613//$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanbanGroupBy'), '', 'fa fa-grip-vertical imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanbangroupby&groupby=p.fk_opp_status'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', ($mode == 'kanbangroupby' ? 2 : 1), array('morecss' => 'reposition'));
614//$newcardbutton .= dolGetButtonTitle($langs->trans('HierarchicView'), '', 'fa fa-stream paddingleft imgforviewmode', $_SERVER["PHP_SELF"].'?mode=hierarchy'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', (($mode == 'hierarchy') ? 2 : 1), array('morecss' => 'reposition'));
615$newcardbutton .= dolGetButtonTitle($langs->trans('Statistics'), '', 'fa fa-chart-bar imgforviewmode', dol_buildpath('/mymodule/stats/myobject_index.php', 1).'?mode=statistics&objecttype=myobject@mymodule'.preg_replace('/(&|\?)*(mode|groupby)=[^&]+/', '', $param), '', ($mode == 'statistics' ? 2 : 1), array('morecss' => 'reposition'));
616$newcardbutton .= dolGetButtonTitleSeparator();
617$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/mymodule/myobject_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
618
619print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1);
620
621// Add code for pre mass action (confirmation or email presend form)
622$topicmail = "SendMyObjectRef";
623$modelmail = "myobject";
624$objecttmp = new MyObject($db);
625$trackid = 'myobject'.$object->id;
626include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
627
628if ($search_all) {
629 $setupstring = '';
630 // @phan-suppress-next-line PhanEmptyForeach
631 foreach ($fieldstosearchall as $key => $val) {
632 $fieldstosearchall[$key] = $langs->trans($val);
633 $setupstring .= $key."=".$val.";";
634 }
635 print '<!-- Search done like if MYOBJECT_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
636 print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).implode(', ', $fieldstosearchall).'</div>'."\n";
637}
638
639$moreforfilter = '';
640/*$moreforfilter.='<div class="divsearchfield">';
641$moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
642$moreforfilter.= '</div>';*/
643
644$parameters = array();
645$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
646if (empty($reshook)) {
647 $moreforfilter .= $hookmanager->resPrint;
648} else {
649 $moreforfilter = $hookmanager->resPrint;
650}
651$parameters = array(
652 'arrayfields' => &$arrayfields,
653);
654
655if (!empty($moreforfilter)) {
656 print '<div class="liste_titre liste_titre_bydiv centpercent">';
657 print $moreforfilter;
658 print '</div>';
659}
660
661$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
662$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column, 1); // This also change content of $arrayfields with user setup
663$selectedfields = (($mode != 'kanban' && $mode != 'kanbangroupby') ? $htmlofselectarray : '');
664$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
665
666print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
667print '<table class="tagtable nobottomiftotal noborder liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
668
669// Fields title search
670// --------------------------------------------------------------------
671print '<tr class="liste_titre_filter">';
672// Action column
673if ($conf->main_checkbox_left_column) {
674 print '<td class="liste_titre center maxwidthsearch">';
675 $searchpicto = $form->showFilterButtons('left');
676 print $searchpicto;
677 print '</td>';
678}
679foreach ($object->fields as $key => $val) {
680 //$searchkey = empty($search[$key]) ? '' : $search[$key];
681 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
682 if ($key == 'status') {
683 $cssforfield .= ($cssforfield ? ' ' : '').'center';
684 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
685 $cssforfield .= ($cssforfield ? ' ' : '').'center';
686 } elseif (in_array($val['type'], array('timestamp'))) {
687 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
688 } 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'])) {
689 $cssforfield .= ($cssforfield ? ' ' : '').'right';
690 }
691 if (!empty($arrayfields['t.'.$key]['checked'])) {
692 print '<td class="liste_titre'.($cssforfield ? ' '.$cssforfield : '').($key == 'status' ? ' parentonrightofpage' : '').'">';
693 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
694 if (empty($val['searchmulti'])) {
695 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);
696 } else {
697 print $form->multiselectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), 0, 0, 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1);
698 }
699 } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) {
700 print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1);
701 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
702 print '<div class="nowrap">';
703 print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
704 print '</div>';
705 print '<div class="nowrap">';
706 print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
707 print '</div>';
708 } elseif ($key == 'lang') {
709 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
710 $formadmin = new FormAdmin($db);
711 print $formadmin->select_language((isset($search[$key]) ? $search[$key] : ''), 'search_lang', 0, array(), 1, 0, 0, 'minwidth100imp maxwidth125', 2);
712 } elseif ($val['type'] === 'boolean') {
713 print $form->selectyesno('search_' . $key, $search[$key] ?? '', 1, false, 1);
714 } else {
715 print '<input type="text" class="flat maxwidth'.(in_array($val['type'], array('integer', 'price')) ? '50' : '75').'" name="search_'.$key.'" value="'.dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '').'">';
716 }
717 print '</td>';
718 }
719}
720// Extra fields
721include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
722
723// Fields from hook
724$parameters = array('arrayfields' => $arrayfields);
725$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
726print $hookmanager->resPrint;
727/*if (!empty($arrayfields['anotherfield']['checked'])) {
728 print '<td class="liste_titre"></td>';
729}*/
730// Action column
731if (!$conf->main_checkbox_left_column) {
732 print '<td class="liste_titre center maxwidthsearch">';
733 $searchpicto = $form->showFilterButtons();
734 print $searchpicto;
735 print '</td>';
736}
737print '</tr>'."\n";
738
739$totalarray = array();
740$totalarray['nbfield'] = 0;
741
742// Fields title label
743// --------------------------------------------------------------------
744print '<tr class="liste_titre">';
745// Action column
746if ($conf->main_checkbox_left_column) {
747 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
748 $totalarray['nbfield']++;
749}
750foreach ($object->fields as $key => $val) {
751 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
752 if ($key == 'status') {
753 $cssforfield .= ($cssforfield ? ' ' : '').'center';
754 } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
755 $cssforfield .= ($cssforfield ? ' ' : '').'center';
756 } elseif (in_array($val['type'], array('timestamp'))) {
757 $cssforfield .= ($cssforfield ? ' ' : '').'nowrap';
758 } 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'])) {
759 $cssforfield .= ($cssforfield ? ' ' : '').'right';
760 }
761 $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label
762 if (!empty($arrayfields['t.'.$key]['checked'])) {
763 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";
764 $totalarray['nbfield']++;
765 }
766}
767// Extra fields
768include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
769// Hook fields
770$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
771$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
772print $hookmanager->resPrint;
773/*if (!empty($arrayfields['anotherfield']['checked'])) {
774 print '<th class="liste_titre">'.$langs->trans("AnotherField").'</th>';
775 $totalarray['nbfield']++;
776}*/
777// Action column
778if (!$conf->main_checkbox_left_column) {
779 print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
780 $totalarray['nbfield']++;
781}
782print '</tr>'."\n";
783
784// Detect if we need a fetch on each output line
785$needToFetchEachLine = 0;
786if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) {
787 foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) {
788 if (!is_null($val) && preg_match('/\$object/', $val)) {
789 $needToFetchEachLine++; // There is at least one compute field that use $object
790 }
791 }
792}
793
794
795// Loop on record
796// --------------------------------------------------------------------
797$i = 0;
798$savnbfield = $totalarray['nbfield'];
799$totalarray = array();
800$totalarray['nbfield'] = 0;
801$imaxinloop = ($limit ? min($num, $limit) : $num);
802while ($i < $imaxinloop) {
803 $obj = $db->fetch_object($resql);
804 if (empty($obj)) {
805 break; // Should not happen
806 }
807
808 // Store properties in $object
809 $object->setVarsFromFetchObj($obj);
810
811 /*
812 $object->thirdparty = null;
813 if ($obj->fk_soc > 0) {
814 if (!empty($conf->cache['thirdparty'][$obj->fk_soc])) {
815 $companyobj = $conf->cache['thirdparty'][$obj->fk_soc];
816 } else {
817 $companyobj = new Societe($db);
818 $companyobj->fetch($obj->fk_soc);
819 $conf->cache['thirdparty'][$obj->fk_soc] = $companyobj;
820 }
821
822 $object->thirdparty = $companyobj;
823 }*/
824
825 if ($mode == 'kanban' || $mode == 'kanbangroupby') {
826 if ($i == 0) {
827 print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
828 print '<div class="box-flex-container kanban">';
829 }
830 // Output Kanban
831 $selected = -1;
832 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
833 $selected = 0;
834 if (in_array($object->id, $arrayofselected)) {
835 $selected = 1;
836 }
837 }
838 //print $object->getKanbanView('', array('thirdparty'=>$object->thirdparty, 'selected' => $selected));
839 print $object->getKanbanView('', array('selected' => $selected));
840 if ($i == ($imaxinloop - 1)) {
841 print '</div>';
842 print '</td></tr>';
843 }
844 } else {
845 // Show line of result
846 $j = 0;
847 print '<tr data-rowid="'.$object->id.'" class="oddeven row-with-select">';
848
849 // Action column
850 if ($conf->main_checkbox_left_column) {
851 print '<td class="nowrap center">';
852 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
853 $selected = 0;
854 if (in_array($object->id, $arrayofselected)) {
855 $selected = 1;
856 }
857 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
858 }
859 print '</td>';
860 if (!$i) {
861 $totalarray['nbfield']++;
862 }
863 }
864 // Fields
865 foreach ($object->fields as $key => $val) {
866 $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']);
867 if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) {
868 $cssforfield .= ($cssforfield ? ' ' : '').'center';
869 } elseif ($key == 'status') {
870 $cssforfield .= ($cssforfield ? ' ' : '').'center';
871 }
872
873 if (in_array($val['type'], array('timestamp'))) {
874 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
875 } elseif ($key == 'ref') {
876 $cssforfield .= ($cssforfield ? ' ' : '').'nowraponall';
877 }
878
879 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'])) {
880 $cssforfield .= ($cssforfield ? ' ' : '').'right';
881 }
882 //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100';
883
884 if (!empty($arrayfields['t.'.$key]['checked'])) {
885 print '<td'.($cssforfield ? ' class="'.$cssforfield.((preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key)) ? ' classfortooltip' : '').'"' : '');
886 if (preg_match('/tdoverflow/', $cssforfield) && !in_array($val['type'], array('ip', 'url')) && !is_numeric($object->$key) && !in_array($key, array('ref'))) {
887 print ' title="'.dol_escape_htmltag((string) $object->$key).'"';
888 }
889 print '>';
890 if ($key == 'status') {
891 print $object->getLibStatut(5);
892 } elseif ($key == 'rowid') {
893 print $object->showOutputField($val, $key, (string) $object->id, '');
894 } else {
895 if ($val['type'] == 'html') {
896 print '<div class="small lineheightsmall twolinesmax-normallineheight">';
897 }
898 print $object->showOutputField($val, $key, (string) $object->$key, '');
899 if ($val['type'] == 'html') {
900 print '</div>';
901 }
902 }
903 print '</td>';
904 if (!$i) {
905 $totalarray['nbfield']++;
906 }
907 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
908 if (!$i) {
909 $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key;
910 }
911 if (!isset($totalarray['val'])) {
912 $totalarray['val'] = array();
913 }
914 if (!isset($totalarray['val']['t.'.$key])) {
915 $totalarray['val']['t.'.$key] = 0;
916 }
917 $totalarray['val']['t.'.$key] += $object->$key;
918 }
919 }
920 }
921 // Extra fields
922 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
923 // Fields from hook
924 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
925 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
926 print $hookmanager->resPrint;
927
928 /*if (!empty($arrayfields['anotherfield']['checked'])) {
929 print '<td class="right">'.$obj->anotherfield.'</td>';
930 }*/
931
932 // Action column
933 if (empty($conf->main_checkbox_left_column)) {
934 print '<td class="nowrap center">';
935 if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
936 $selected = 0;
937 if (in_array($object->id, $arrayofselected)) {
938 $selected = 1;
939 }
940 print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
941 }
942 print '</td>';
943 if (!$i) {
944 $totalarray['nbfield']++;
945 }
946 }
947
948 print '</tr>'."\n";
949 }
950
951 $i++;
952}
953
954// Show total line
955include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
956
957// If no record found
958if ($num == 0) {
959 $colspan = 1;
960 foreach ($arrayfields as $key => $val) {
961 if (!empty($val['checked'])) {
962 $colspan++;
963 }
964 }
965 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
966}
967
968
969$db->free($resql);
970
971$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
972$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
973print $hookmanager->resPrint;
974
975print '</table>'."\n";
976print '</div>'."\n";
977
978print '</form>'."\n";
979
980if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
981 $hidegeneratedfilelistifempty = 1;
982 if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
983 $hidegeneratedfilelistifempty = 0;
984 }
985
986 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
987 $formfile = new FormFile($db);
988
989 // Show list of available documents
990 $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
991 $urlsource .= str_replace('&amp;', '&', $param);
992
993 $filedir = $diroutputmassaction;
994 $genallowed = $permissiontoread;
995 $delallowed = $permissiontoadd;
996
997 print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, $genallowed, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
998}
999
1000// End of page
1001llxFooter();
1002$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class 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 for MyObject.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_now($mode='gmt')
Return date for now.
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...
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
natural_search($fields, $value, $mode=0, $nofirstand=0, $sqltoadd='')
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
getDolDefaultContextPage($s)
Return the default context page string.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
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.
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.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.