dolibarr 20.0.0
html.formlistwebportal.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2023-2024 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2023-2024 Lionel Vessiller <lvessiller@easya.solutions>
4 * Copyright (C) 2023-2024 Patrice Andreani <pandreani@easya.solutions>
5 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22
29require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
30require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
31require_once DOL_DOCUMENT_ROOT . '/webportal/class/html.formwebportal.class.php';
32
39{
43 public $action = '';
44
48 public $db;
49
53 public $form;
54
58 public $object;
59
63 public $limit = -1;
64
68 public $page = 1;
69
73 public $sortfield = '';
74
78 public $sortorder = '';
79
83 public $titleKey = '';
84
88 public $titleDescKey = '';
89
93 public $contextpage = '';
94
98 public $search = array();
99
103 public $arrayfields = array();
104
108 public $companyStaticList = array();
109
110
116 public function __construct($db)
117 {
118 $this->db = $db;
119 $this->form = new FormWebPortal($this->db);
120 }
121
128 public function init($elementEn)
129 {
130 // keep compatibility
131 if ($elementEn == 'commande') {
132 $elementEn = 'order';
133 } elseif ($elementEn == 'facture') {
134 $elementEn = 'invoice';
135 }
136
137 // load module libraries
138 dol_include_once('/webportal/class/webportal' . $elementEn . '.class.php');
139
140 // Initialize technical objects
141 $objectclass = 'WebPortal' . ucfirst($elementEn);
142 $object = new $objectclass($this->db);
143
144 // set form list
145 $this->action = GETPOST('action', 'aZ09');
146 $this->object = $object;
147 $this->limit = GETPOSTISSET('limit') ? GETPOSTINT('limit') : -1;
148 $this->sortfield = GETPOST('sortfield', 'aZ09comma');
149 $this->sortorder = GETPOST('sortorder', 'aZ09comma');
150 $this->page = GETPOSTISSET('page') ? GETPOSTINT('page') : 1;
151 $this->titleKey = $objectclass . 'ListTitle';
152
153 // Initialize array of search criteria
154 //$search_all = GETPOST('search_all', 'alphanohtml');
155 $search = array();
156 foreach ($object->fields as $key => $val) {
157 if (GETPOST('search_' . $key, 'alpha') !== '') {
158 $search[$key] = GETPOST('search_' . $key, 'alpha');
159 }
160 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
161 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
162 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
163 // extract date YYYY-MM-DD for year, month and day
164 $dateStartArr = explode('-', $postDateStart);
165 $dateEndArr = explode('-', $postDateEnd);
166 if (count($dateStartArr) == 3) {
167 $dateStartYear = (int) $dateStartArr[0];
168 $dateStartMonth = (int) $dateStartArr[1];
169 $dateStartDay = (int) $dateStartArr[2];
170 $search[$key . '_dtstart'] = dol_mktime(0, 0, 0, $dateStartMonth, $dateStartDay, $dateStartYear);
171 }
172 if (count($dateEndArr) == 3) {
173 $dateEndYear = (int) $dateEndArr[0];
174 $dateEndMonth = (int) $dateEndArr[1];
175 $dateEndDay = (int) $dateEndArr[2];
176 $search[$key . '_dtend'] = dol_mktime(23, 59, 59, $dateEndMonth, $dateEndDay, $dateEndYear);
177 }
178 }
179 }
180 $this->search = $search;
181
182 // List of fields to search into when doing a "search in all"
183 //$fieldstosearchall = array();
184
185 // Definition of array of fields for columns
186 $arrayfields = array();
187 foreach ($object->fields as $key => $val) {
188 // If $val['visible']==0, then we never show the field
189 if (!empty($val['visible'])) {
190 $visible = (int) dol_eval($val['visible'], 1);
191 $arrayfields['t.' . $key] = array(
192 'label' => $val['label'],
193 'checked' => (($visible < 0) ? 0 : 1),
194 'enabled' => (abs($visible) != 3 && (bool) dol_eval($val['enabled'], 1)),
195 'position' => $val['position'],
196 'help' => isset($val['help']) ? $val['help'] : ''
197 );
198 }
199 }
200 if ($elementEn == 'invoice') {
201 $arrayfields['remain_to_pay'] = array('type' => 'price', 'label' => 'RemainderToPay', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10000, 'help' => '',);
202 }
203 $arrayfields['download_link'] = array('label' => 'File', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10001, 'help' => '',);
204
205 $object->fields = dol_sort_array($object->fields, 'position');
206 //$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
207 $arrayfields = dol_sort_array($arrayfields, 'position');
208
209 $this->arrayfields = $arrayfields;
210 }
211
217 public function doActions()
218 {
219 $object = $this->object;
220 $search = $this->search;
221
222 // Purge search criteria
223 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
224 foreach ($object->fields as $key => $val) {
225 $search[$key] = '';
226 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
227 $search[$key . '_dtstart'] = '';
228 $search[$key . '_dtend'] = '';
229 }
230 }
231 $this->search = $search;
232 }
233 }
234
241 public function elementList($context)
242 {
243 global $conf, $hookmanager, $langs;
244
245 $html = '';
246
247 // initialize
248 $action = $this->action;
249 $object = $this->object;
250 $limit = $this->limit;
251 $page = $this->page;
252 $sortfield = $this->sortfield;
253 $sortorder = $this->sortorder;
254 $titleKey = $this->titleKey;
255 $contextpage = $this->contextpage;
256 $search = $this->search;
257 $arrayfields = $this->arrayfields;
258 $elementEn = $object->element;
259 if ($object->element == 'commande') {
260 $elementEn = 'order';
261 } elseif ($object->element == 'facture') {
262 $elementEn = 'invoice';
263 }
264
265 // specific for invoice and remain to pay
266 $discount = null;
267 if ($elementEn == 'invoice') {
268 $discount = new DiscountAbsolute($this->db);
269 }
270
271 // empty value for select
272 $emptyValueKey = ($elementEn == 'order' ? -5 : -1);
273
274 if ($limit < 0) {
275 $limit = $conf->liste_limit;
276 }
277 if ($page <= 0) {
278 $page = 1;
279 }
280 $offset = $limit * ($page - 1);
281 if (!$sortfield) {
282 reset($object->fields); // Reset is required to avoid key() to return null.
283 $sortfield = 't.' . key($object->fields); // Set here default search field. By default 1st field in definition.
284 }
285 if (!$sortorder) {
286 $sortorder = 'DESC';
287 }
288
289 $socid = (int) $context->logged_thirdparty->id;
290
291 // Build and execute select
292 // --------------------------------------------------------------------
293 $sql = "SELECT ";
294 $sql .= $object->getFieldList('t');
295 $sql .= ", t.entity as element_entity";
296 // Add fields from hooks
297 $parameters = array();
298 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
299 $sql .= $hookmanager->resPrint;
300 $sql = preg_replace('/,\s*$/', '', $sql);
301
302 $sqlfields = $sql; // $sql fields to remove for count total
303
304 $sql .= " FROM " . $this->db->prefix() . $object->table_element . " as t";
305 // Add table from hooks
306 $parameters = array();
307 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
308 $sql .= $hookmanager->resPrint;
309 if ($object->ismultientitymanaged == 1) {
310 $sql .= " WHERE t.entity IN (" . getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)) . ")";
311 } else {
312 $sql .= " WHERE 1 = 1";
313 }
314 // filter on logged third-party
315 $sql .= " AND t.fk_soc = " . ((int) $socid);
316 // discard record with status draft
317 $sql .= " AND t.fk_statut <> 0";
318
319 foreach ($search as $key => $val) {
320 if (array_key_exists($key, $object->fields)) {
321 if (($key == 'status' || $key == 'fk_statut') && $search[$key] == $emptyValueKey) {
322 continue;
323 }
324 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
325 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
326 if ($search[$key] == "$emptyValueKey" || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
327 $search[$key] = '';
328 }
329 $mode_search = 2;
330 }
331 if ($search[$key] != '') {
332 $sql .= natural_search("t." . $this->db->escape($key), $search[$key], (($key == 'status' || $key == 'fk_statut') ? ($search[$key] < 0 ? 1 : 2) : $mode_search));
333 }
334 } else {
335 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
336 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
337 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
338 if (preg_match('/_dtstart$/', $key)) {
339 $sql .= " AND t." . $this->db->escape($columnName) . " >= '" . $this->db->idate($search[$key]) . "'";
340 }
341 if (preg_match('/_dtend$/', $key)) {
342 $sql .= " AND t." . $this->db->escape($columnName) . " <= '" . $this->db->idate($search[$key]) . "'";
343 }
344 }
345 }
346 }
347 }
348 //if ($search_all) {
349 // $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
350 //}
351 // Add where from hooks
352 $parameters = array();
353 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
354 $sql .= $hookmanager->resPrint;
355
356 // Count total nb of records
357 $nbtotalofrecords = 0;
358 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
359 /* The fast and low memory method to get and count full list converts the sql into a sql count */
360 $sqlforcount = preg_replace('/^' . preg_quote($sqlfields, '/') . '/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
361 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
362 $resql = $this->db->query($sqlforcount);
363 if ($resql) {
364 $objforcount = $this->db->fetch_object($resql);
365 $nbtotalofrecords = (int) $objforcount->nbtotalofrecords;
366 } else {
367 dol_print_error($this->db);
368 }
369
370 if ($offset > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 1
371 $page = 1;
372 $offset = 0;
373 }
374
375 $this->db->free($resql);
376 }
377
378 // Complete request and execute it with limit
379 $sql .= $this->db->order($sortfield, $sortorder);
380 if ($limit) {
381 $sql .= $this->db->plimit($limit, $offset);
382 }
383
384 $resql = $this->db->query($sql);
385 if (!$resql) {
386 dol_print_error($this->db);
387 return '';
388 }
389
390 $num = $this->db->num_rows($resql);
391 if ($limit > 0) {
392 $nbpages = ceil($nbtotalofrecords / $limit);
393 }
394 if ($nbpages <= 0) {
395 $nbpages = 1;
396 }
397
398 // make array[sort field => sort order] for this list
399 $sortList = array();
400 $sortFieldList = explode(",", $sortfield);
401 $sortOrderList = explode(",", $sortorder);
402 $sortFieldIndex = 0;
403 if (!empty($sortFieldList)) {
404 foreach ($sortFieldList as $sortField) {
405 if (isset($sortOrderList[$sortFieldIndex])) {
406 $sortList[$sortField] = $sortOrderList[$sortFieldIndex];
407 }
408 $sortFieldIndex++;
409 }
410 }
411
412 $param = '';
413 $param .= '&contextpage=' . urlencode($contextpage);
414 $param .= '&limit=' . $limit;
415 foreach ($search as $key => $val) {
416 if (is_array($search[$key])) {
417 foreach ($search[$key] as $skey) {
418 if ($skey != '') {
419 $param .= '&search_' . $key . '[]=' . urlencode($skey);
420 }
421 }
422 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
423 $param .= '&search_' . $key . 'month=' . (GETPOSTINT('search_' . $key . 'month'));
424 $param .= '&search_' . $key . 'day=' . (GETPOSTINT('search_' . $key . 'day'));
425 $param .= '&search_' . $key . 'year=' . (GETPOSTINT('search_' . $key . 'year'));
426 } elseif ($search[$key] != '') {
427 $param .= '&search_' . $key . '=' . urlencode($search[$key]);
428 }
429 }
430 // Add $param from hooks
431 $parameters = array();
432 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
433 $param .= $hookmanager->resPrint;
434
435 $url_file = $context->getControllerUrl($context->controller);
436 $html .= '<form method="POST" id="searchFormList" action="' . $url_file . '">' . "\n";
437 $html .= $context->getFormToken();
438 $html .= '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
439 $html .= '<input type="hidden" name="action" value="list">';
440 $html .= '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
441 $html .= '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
442 $html .= '<input type="hidden" name="page" value="' . $page . '">';
443 $html .= '<input type="hidden" name="contextpage" value="' . $contextpage . '">';
444
445 // pagination
446 $pagination_param = $param . '&sortfield=' . $sortfield . '&sortorder=' . $sortorder;
447 $html .= '<nav id="webportal-' . $elementEn . '-pagination">';
448 $html .= '<ul>';
449 $html .= '<li><strong>' . $langs->trans($titleKey) . '</strong> (' . $nbtotalofrecords . ')</li>';
450 $html .= '</ul>';
451
452 /* Generate pagination list */
453 $html .= static::generatePageListNav($url_file . $pagination_param, $nbpages, $page);
454
455 $html .= '</nav>';
456
457 // table with search filters and column titles
458 $html .= '<table id="webportal-' . $elementEn . '-list" responsive="scroll" role="grid">';
459 // title and desc for table
460 //if ($titleKey != '') {
461 // $html .= '<caption id="table-collapse-responsive">';
462 // $html .= $langs->trans($titleKey) . '<br/>';
463 // if ($titleDescKey != '') {
464 // $html .= '<small>' . $langs->trans($titleDescKey) . '</small>';
465 // }
466 // $html .= '</caption>';
467 //}
468
469 $html .= '<thead>';
470
471 // Fields title search
472 // --------------------------------------------------------------------
473 $html .= '<tr role="search-row">';
474 // Action column
475 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
476 $html .= '<td data-col="row-checkbox" >';
477 $html .= ' <button class="btn-filter-icon btn-search-filters-icon" type="submit" name="button_search_x" value="x" aria-label="'.dol_escape_htmltag($langs->trans('Search')).'" ></button>';
478 $html .= ' <button class="btn-filter-icon btn-remove-search-filters-icon" type="submit" name="button_removefilter_x" value="x" aria-label="'.dol_escape_htmltag($langs->trans('RemoveSearchFilters')).'"></button>';
479 $html .= '</td>';
480 // }
481 foreach ($object->fields as $key => $val) {
482 if (!empty($arrayfields['t.' . $key]['checked'])) {
483 $html .= '<td data-label="' . $arrayfields['t.' . $key]['label'] . '" data-col="'.dol_escape_htmltag($key).'" >';
484 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
485 $html .= $this->form->selectarray('search_' . $key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', '');
486 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
487 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
488 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
489
490 $html .= '<div class="grid">';
491 $html .= $this->form->inputDate('search_' . $key . '_dtstart', $postDateStart ? $postDateStart : '', $langs->trans('From'));
492 $html .= '</div>';
493 $html .= '<div class="grid">';
494 $html .= $this->form->inputDate('search_' . $key . '_dtend', $postDateEnd ? $postDateEnd : '', $langs->trans('to'));
495 $html .= '</div>';
496 } else {
497 $html .= '<input type="text" name="search_' . $key . '" value="' . dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '') . '">';
498 }
499 $html .= '</td>';
500 }
501 }
502 // Fields from hook
503 $parameters = array('arrayfields' => $arrayfields);
504 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
505 $html .= $hookmanager->resPrint;
506 // Remain to pay
507 if (!empty($arrayfields['remain_to_pay']['checked'])) {
508 $html .= '<td data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
509 $html .= '</td>';
510 }
511 // Download link
512 if (!empty($arrayfields['download_link']['checked'])) {
513 $html .= '<td data-label="' . $arrayfields['download_link']['label'] . '">';
514 $html .= '</td>';
515 }
516 $html .= '</tr>';
517
518
519 $totalarray = array();
520 $totalarray['nbfield'] = 0;
521
522 // Fields title label
523 // --------------------------------------------------------------------
524 $html .= '<tr>';
525 // Action column
526 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
527 $html .= '<th data-col="row-checkbox" ></th>';
528 $totalarray['nbfield']++;
529 // }
530 foreach ($object->fields as $key => $val) {
531 $tableKey = 't.' . $key;
532 if (!empty($arrayfields[$tableKey]['checked'])) {
533 $tableOrder = '';
534 if (array_key_exists($tableKey, $sortList)) {
535 $tableOrder = strtolower($sortList[$tableKey]);
536 }
537 $url_param = $url_file . '&sortfield=' . $tableKey . '&sortorder=' . ($tableOrder == 'desc' ? 'asc' : 'desc') . $param;
538 $html .= '<th data-col="'.dol_escape_htmltag($key).'" scope="col"' . ($tableOrder != '' ? ' table-order="' . $tableOrder . '"' : '') . '>';
539 $html .= '<a href="' . $url_param . '">';
540 $html .= $langs->trans($arrayfields['t.' . $key]['label']);
541 $html .= '</a>';
542 $html .= '</th>';
543 $totalarray['nbfield']++;
544 }
545 }
546 // Remain to pay
547 if (!empty($arrayfields['remain_to_pay']['checked'])) {
548 $html .= '<th scope="col">';
549 $html .= $langs->trans($arrayfields['remain_to_pay']['label']);
550 $html .= '</th>';
551 $totalarray['nbfield']++;
552 }
553 // Download link
554 if (!empty($arrayfields['download_link']['checked'])) {
555 $html .= '<th scope="col">';
556 $html .= $langs->trans($arrayfields['download_link']['label']);
557 $html .= '</th>';
558 $totalarray['nbfield']++;
559 }
560
561 // Hook fields
562 $parameters = array('arrayfields' => $arrayfields, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
563 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
564 $html .= $hookmanager->resPrint;
565 $html .= '</tr>';
566
567 $html .= '</thead>';
568
569 $html .= '<tbody>';
570
571 // Store company
572 $idCompany = (int) $socid;
573 if (!isset($this->companyStaticList[$socid])) {
574 $companyStatic = new Societe($this->db);
575 $companyStatic->fetch($idCompany);
576 $this->companyStaticList[$idCompany] = $companyStatic;
577 }
578 $companyStatic = $this->companyStaticList[$socid];
579
580 // Loop on record
581 // --------------------------------------------------------------------
582 $i = 0;
583 $totalarray = [
584 'nbfield' => 0,
585 'totalizable' => [],
586 ];
587 $imaxinloop = ($limit ? min($num, $limit) : $num);
588 while ($i < $imaxinloop) {
589 $obj = $this->db->fetch_object($resql);
590 if (empty($obj)) {
591 break; // Should not happen
592 }
593
594 // Store properties in $object
595 $object->setVarsFromFetchObj($obj);
596
597 // specific to get invoice status (depends on payment)
598 $payment = -1;
599 if ($elementEn == 'invoice') {
600 // paid sum
601 $payment = $object->getSommePaiement();
602 $totalcreditnotes = $object->getSumCreditNotesUsed();
603 $totaldeposits = $object->getSumDepositsUsed();
604
605 // remain to pay
606 $totalpay = $payment + $totalcreditnotes + $totaldeposits;
607 $remaintopay = price2num($object->total_ttc - $totalpay);
608 if ($object->status == Facture::STATUS_CLOSED && $object->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment
609 $remaintopay = 0;
610 }
611 if ($object->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1 && $discount) {
612 $remaincreditnote = $discount->getAvailableDiscounts($companyStatic, '', 'rc.fk_facture_source=' . $object->id);
613 $remaintopay = -$remaincreditnote;
614 }
615 }
616
617 // Show line of result
618 $html .= '<tr data-rowid="' . $object->id . '">';
619 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
620 $html .= '<td class="nowraponall">';
621 $html .= '</td>';
622 if (!$i) {
623 $totalarray['nbfield']++;
624 }
625 // }
626 foreach ($object->fields as $key => $val) {
627 if (!empty($arrayfields['t.' . $key]['checked'])) {
628 $html .= '<td class="nowraponall" data-label="' . $arrayfields['t.' . $key]['label'] . '">';
629 if ($key == 'status' || $key == 'fk_statut') {
630 if ($elementEn == 'invoice') {
631 // specific to get invoice status (depends on payment)
632 $html .= $object->getLibStatut(5, $payment);
633 } else {
634 $html .= $object->getLibStatut(5);
635 }
636 } elseif ($key == 'rowid') {
637 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->id, '');
638 } else {
639 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->$key, '');
640 }
641 $html .= '</td>';
642
643
644 if (!$i) {
645 $totalarray['nbfield']++;
646 }
647 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
648 if (!$i) {
649 $totalarray['pos'][$totalarray['nbfield']] = 't.' . $key;
650 }
651 if (!isset($totalarray['val'])) {
652 $totalarray['val'] = array();
653 }
654 if (!isset($totalarray['val']['t.' . $key])) {
655 $totalarray['val']['t.' . $key] = 0;
656 }
657 $totalarray['val']['t.' . $key] += $object->$key;
658 }
659 }
660 }
661 // Remain to pay
662 if (!empty($arrayfields['remain_to_pay']['checked'])) {
663 $html .= '<td class="nowraponall" data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
664 $html .= $this->form->showOutputFieldForObject($object, $arrayfields['remain_to_pay'], 'remain_to_pay', $remaintopay, '');
665 //$html .= price($remaintopay);
666 $html .= '</td>';
667 if (!$i) {
668 $totalarray['nbfield']++;
669 }
670 }
671 // Download link
672 if (!empty($arrayfields['download_link']['checked'])) {
673 $element = $object->element;
674 $html .= '<td class="nowraponall" data-label="' . $arrayfields['download_link']['label'] . '">';
675 $filename = dol_sanitizeFileName($obj->ref);
676 $filedir = $conf->{$element}->multidir_output[$obj->element_entity] . '/' . dol_sanitizeFileName($obj->ref);
677 $html .= $this->form->getDocumentsLink($element, $filename, $filedir);
678 $html .= '</td>';
679 if (!$i) {
680 $totalarray['nbfield']++;
681 }
682 }
683 // Fields from hook
684 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
685 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
686 $html .= $hookmanager->resPrint;
687
688
689 $html .= '</tr>';
690
691 $i++;
692 }
693
694 // Move fields of totalizable into the common array pos and val
695 if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
696 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
697 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
698 $totalarray['val'][$keytotalizable] = isset($valtotalizable['total']) ? $valtotalizable['total'] : 0;
699 }
700 }
701 // Show total line
702 if (isset($totalarray['pos'])) {
703 $html .= '<tr>';
704 $i = 0;
705 while ($i < $totalarray['nbfield']) {
706 $i++;
707 if (!empty($totalarray['pos'][$i])) {
708 $html .= '<td class="nowraponall essai">';
709 $html .= price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
710 $html .= '</td>';
711 } else {
712 if ($i == 1) {
713 $html .= '<td>' . $langs->trans("Total") . '</td>';
714 } else {
715 $html .= '<td></td>';
716 }
717 }
718 }
719 $html .= '</tr>';
720 }
721
722 // If no record found
723 if ($num == 0) {
724 $colspan = 1;
725 foreach ($arrayfields as $key => $val) {
726 if (!empty($val['checked'])) {
727 $colspan++;
728 }
729 }
730 $html .= '<tr><td colspan="' . $colspan . '"><span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span></td></tr>';
731 }
732
733 $html .= '</tbody>';
734
735 $this->db->free($resql);
736
737 $parameters = array('arrayfields' => $arrayfields, 'sql' => $sql);
738 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
739 $html .= $hookmanager->resPrint;
740
741 $html .= '</table>';
742
743 $html .= '</form>';
744
745 return $html;
746 }
747
756 public static function generatePageListNav(string $url, int $nbPages, int $currentPage)
757 {
758 global $langs;
759
760 // Return nothing (no navigation bar), if there is only 1 page.
761 if ($nbPages <= 1) {
762 return '';
763 }
764
765 $pSep = strpos($url, '?') === false ? '?' : '&amp;';
766
767 $html = '<ul class="pages-nav-list">';
768
769 if ($currentPage > 1) {
770 $html .= '<li><a class="pages-nav-list__icon --prev" aria-label="' . dol_escape_htmltag($langs->trans('AriaPrevPage')) . '" href="' . $url . $pSep . 'page=' . ($currentPage - 1) . '" ' . ($currentPage <= 1 ? ' disabled' : '') . '></a></li>';
771 }
772
773 $maxPaginItem = min($nbPages, 5);
774 $minPageNum = max(1, $currentPage - 3);
775 $maxPageNum = min($nbPages, $currentPage + 3);
776
777 if ($minPageNum > 1) {
778 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage == 1 ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', 1)) . '" href="' . $url . $pSep . 'page=1" >1</a></li>';
779 $html .= '<li>&hellip;</li>';
780 }
781
782 for ($p = $minPageNum; $p <= $maxPageNum; $p++) {
783 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage === $p ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', $p)) . '" href="' . $url . $pSep . 'page=' . $p . '">' . $p . '</a></li>';
784 }
785
786 if ($maxPaginItem < $nbPages) {
787 $html .= '<li>&hellip;</li>';
788 $html .= '<li><a class="pages-nav-list__link ' . ($currentPage == $nbPages ? '--active' : '') . '" aria-label="' . dol_escape_htmltag($langs->trans('AriaPageX', $nbPages)) . '" href="' . $url . $pSep . 'page=' . $nbPages . '">' . $nbPages . '</a></li>';
789 }
790
791 if ($currentPage < $nbPages) {
792 $html .= '<li><a class="pages-nav-list__icon --next" aria-label="' . dol_escape_htmltag($langs->trans('AriaNextPage')) . '" href="' . $url . $pSep . 'page=' . ($currentPage + 1) . '" ' . ($currentPage >= $nbPages ? ' disabled' : '') . '></a></li>';
793 }
794
795 $html .= '</ul>';
796
797 return $html;
798 }
799}
Class to manage absolute discounts.
const TYPE_CREDIT_NOTE
Credit note invoice.
const STATUS_CLOSED
Classified paid.
Class to manage generation of HTML components Only common components for WebPortal must be here.
static generatePageListNav(string $url, int $nbPages, int $currentPage)
Generate with pagination navigaion.
elementList($context)
List for an element in the page context.
Class to manage generation of HTML components Only common components for WebPortal must be here.
Class to manage third parties objects (customers, suppliers, prospects...)
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...
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
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...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
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...
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
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...