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