dolibarr 21.0.0-alpha
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 a 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 /* Fix: this is not compatible with multilangage date format, replaced with dolibarr method
162 $postDateStart = GETPOST('search_' . $key . '_dtstart', 'alphanohtml');
163 $postDateEnd = GETPOST('search_' . $key . '_dtend', 'alphanohtml');
164 // extract date YYYY-MM-DD for year, month and day
165 $dateStartArr = explode('-', $postDateStart);
166 $dateEndArr = explode('-', $postDateEnd);
167 if (count($dateStartArr) == 3) {
168 $dateStartYear = (int) $dateStartArr[0];
169 $dateStartMonth = (int) $dateStartArr[1];
170 $dateStartDay = (int) $dateStartArr[2];
171 $search[$key . '_dtstart'] = dol_mktime(0, 0, 0, $dateStartMonth, $dateStartDay, $dateStartYear);
172 }
173 if (count($dateEndArr) == 3) {
174 $dateEndYear = (int) $dateEndArr[0];
175 $dateEndMonth = (int) $dateEndArr[1];
176 $dateEndDay = (int) $dateEndArr[2];
177 $search[$key . '_dtend'] = dol_mktime(23, 59, 59, $dateEndMonth, $dateEndDay, $dateEndYear);
178 }
179 */
180 $search[$key . '_dtstartmonth'] = GETPOSTINT('search_' . $key . '_dtstartmonth');
181 $search[$key . '_dtstartday'] = GETPOSTINT('search_' . $key . '_dtstartday');
182 $search[$key . '_dtstartyear'] = GETPOSTINT('search_' . $key . '_dtstartyear');
183 $search[$key . '_dtendmonth'] = GETPOSTINT('search_' . $key . '_dtendmonth');
184 $search[$key . '_dtendday'] = GETPOSTINT('search_' . $key . '_dtendday');
185 $search[$key . '_dtendyear'] = GETPOSTINT('search_' . $key . '_dtendyear');
186 }
187 }
188 $this->search = $search;
189
190 // List of fields to search into when doing a "search in all"
191 //$fieldstosearchall = array();
192
193 // Definition of array of fields for columns
194 $arrayfields = array();
195 foreach ($object->fields as $key => $val) {
196 // If $val['visible']==0, then we never show the field
197 if (!empty($val['visible'])) {
198 $visible = (int) dol_eval((string) $val['visible'], 1);
199 $arrayfields['t.' . $key] = array(
200 'label' => $val['label'],
201 'checked' => (($visible < 0) ? 0 : 1),
202 'enabled' => (abs($visible) != 3 && (bool) dol_eval($val['enabled'], 1)),
203 'position' => $val['position'],
204 'help' => isset($val['help']) ? $val['help'] : ''
205 );
206 }
207 }
208 if ($elementEn == 'invoice') {
209 $arrayfields['remain_to_pay'] = array('type' => 'price', 'label' => 'RemainderToPay', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10000, 'help' => '',);
210 }
211 $arrayfields['download_link'] = array('label' => 'File', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10001, 'help' => '',);
212 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
213 $arrayfields['signature_link'] = array('label' => 'Signature', 'checked' => 1, 'enabled' => 1, 'visible' => 1, 'position' => 10002, 'help' => '',);
214 }
215
216 $object->fields = dol_sort_array($object->fields, 'position');
217 //$arrayfields['anotherfield'] = array('type'=>'integer', 'label'=>'AnotherField', 'checked'=>1, 'enabled'=>1, 'position'=>90, 'csslist'=>'right');
218 $arrayfields = dol_sort_array($arrayfields, 'position');
219
220 $this->arrayfields = $arrayfields;
221 }
222
228 public function doActions()
229 {
230 $object = $this->object;
231 $search = $this->search;
232
233 // Purge search criteria
234 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
235 foreach ($object->fields as $key => $val) {
236 $search[$key] = '';
237 if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
238 //$search[$key . '_dtstart'] = '';
239 //$search[$key . '_dtend'] = '';
240 $search[$key . '_dtstartmonth'] = '';
241 $search[$key . '_dtendmonth'] = '';
242 $search[$key . '_dtstartday'] = '';
243 $search[$key . '_dtendday'] = '';
244 $search[$key . '_dtstartyear'] = '';
245 $search[$key . '_dtendyear'] = '';
246 }
247 }
248 $this->search = $search;
249 }
250 }
251
258 public function elementList($context)
259 {
260 global $conf, $hookmanager, $langs;
261
262 $html = '';
263
264 // initialize
265 $action = $this->action;
266 $object = $this->object;
267 $limit = $this->limit;
268 $page = $this->page;
269 $sortfield = $this->sortfield;
270 $sortorder = $this->sortorder;
271 $titleKey = $this->titleKey;
272 $contextpage = $this->contextpage;
273 $search = $this->search;
274 $arrayfields = $this->arrayfields;
275 $elementEn = $object->element;
276 if ($object->element == 'commande') {
277 $elementEn = 'order';
278 } elseif ($object->element == 'facture') {
279 $elementEn = 'invoice';
280 }
281
282 // specific for invoice and remain to pay
283 $discount = null;
284 if ($elementEn == 'invoice') {
285 $discount = new DiscountAbsolute($this->db);
286 }
287
288 // empty value for select
289 $emptyValueKey = ($elementEn == 'order' ? -5 : -1);
290
291 if ($limit < 0) {
292 $limit = $conf->liste_limit;
293 }
294 if ($page <= 0) {
295 $page = 1;
296 }
297 $offset = $limit * ($page - 1);
298 if (!$sortfield) {
299 reset($object->fields); // Reset is required to avoid key() to return null.
300 $sortfield = 't.' . key($object->fields); // Set here default search field. By default 1st field in definition.
301 }
302 if (!$sortorder) {
303 $sortorder = 'DESC';
304 }
305
306 $socid = (int) $context->logged_thirdparty->id;
307
308 // Build and execute select
309 // --------------------------------------------------------------------
310 $sql = "SELECT ";
311 $sql .= $object->getFieldList('t');
312 $sql .= ", t.entity as element_entity";
313 // Add fields from hooks
314 $parameters = array();
315 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
316 $sql .= $hookmanager->resPrint;
317 $sql = preg_replace('/,\s*$/', '', $sql);
318
319 $sqlfields = $sql; // $sql fields to remove for count total
320
321 $sql .= " FROM " . $this->db->prefix() . $object->table_element . " as t";
322 // Add table from hooks
323 $parameters = array();
324 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
325 $sql .= $hookmanager->resPrint;
326 if ($object->ismultientitymanaged == 1) {
327 $sql .= " WHERE t.entity IN (" . getEntity($object->element, (GETPOSTINT('search_current_entity') ? 0 : 1)) . ")";
328 } else {
329 $sql .= " WHERE 1 = 1";
330 }
331 // filter on logged third-party
332 $sql .= " AND t.fk_soc = " . ((int) $socid);
333 // discard record with status draft
334 $sql .= " AND t.fk_statut <> 0";
335
336 foreach ($search as $key => $val) {
337 if (array_key_exists($key, $object->fields)) {
338 if (($key == 'status' || $key == 'fk_statut') && $search[$key] == $emptyValueKey) {
339 continue;
340 }
341 $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0);
342 if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) {
343 if ($search[$key] == "$emptyValueKey" || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) {
344 $search[$key] = '';
345 }
346 $mode_search = 2;
347 }
348 if ($search[$key] != '') {
349 $sql .= natural_search("t." . $this->db->escape($key), $search[$key], (($key == 'status' || $key == 'fk_statut') ? ($search[$key] < 0 ? 1 : 2) : $mode_search));
350 }
351 } else {
352 if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
353 $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
354 if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
355 if (preg_match('/_dtstart$/', $key)) {
356 $sql .= " AND t." . $this->db->escape($columnName) . " >= '" . $this->db->idate($search[$key]) . "'";
357 }
358 if (preg_match('/_dtend$/', $key)) {
359 $sql .= " AND t." . $this->db->escape($columnName) . " <= '" . $this->db->idate($search[$key]) . "'";
360 }
361 }
362 }
363 }
364 }
365 //if ($search_all) {
366 // $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
367 //}
368 // Add where from hooks
369 $parameters = array();
370 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
371 $sql .= $hookmanager->resPrint;
372
373 // Count total nb of records
374 $nbtotalofrecords = 0;
375 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
376 /* The fast and low memory method to get and count full list converts the sql into a sql count */
377 $sqlforcount = preg_replace('/^' . preg_quote($sqlfields, '/') . '/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
378 $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
379 $resql = $this->db->query($sqlforcount);
380 if ($resql) {
381 $objforcount = $this->db->fetch_object($resql);
382 $nbtotalofrecords = (int) $objforcount->nbtotalofrecords;
383 } else {
384 dol_print_error($this->db);
385 }
386
387 if ($offset > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 1
388 $page = 1;
389 $offset = 0;
390 }
391
392 $this->db->free($resql);
393 }
394
395 // Complete request and execute it with limit
396 $sql .= $this->db->order($sortfield, $sortorder);
397 if ($limit) {
398 $sql .= $this->db->plimit($limit, $offset);
399 }
400
401 $resql = $this->db->query($sql);
402 if (!$resql) {
403 dol_print_error($this->db);
404 return '';
405 }
406
407 $num = $this->db->num_rows($resql);
408 if ($limit > 0) {
409 $nbpages = ceil($nbtotalofrecords / $limit);
410 }
411 if ($nbpages <= 0) {
412 $nbpages = 1;
413 }
414
415 // make array[sort field => sort order] for this list
416 $sortList = array();
417 $sortFieldList = explode(",", $sortfield);
418 $sortOrderList = explode(",", $sortorder);
419 $sortFieldIndex = 0;
420 if (!empty($sortFieldList)) {
421 foreach ($sortFieldList as $sortField) {
422 if (isset($sortOrderList[$sortFieldIndex])) {
423 $sortList[$sortField] = $sortOrderList[$sortFieldIndex];
424 }
425 $sortFieldIndex++;
426 }
427 }
428
429 $param = '';
430 $param .= '&contextpage=' . urlencode($contextpage);
431 $param .= '&limit=' . $limit;
432 foreach ($search as $key => $val) {
433 if (is_array($search[$key])) {
434 foreach ($search[$key] as $skey) {
435 if ($skey != '') {
436 $param .= '&search_' . $key . '[]=' . urlencode($skey);
437 }
438 }
439 } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) {
440 $param .= '&search_' . $key . 'month=' . (GETPOSTINT('search_' . $key . 'month'));
441 $param .= '&search_' . $key . 'day=' . (GETPOSTINT('search_' . $key . 'day'));
442 $param .= '&search_' . $key . 'year=' . (GETPOSTINT('search_' . $key . 'year'));
443 } elseif ($search[$key] != '') {
444 $param .= '&search_' . $key . '=' . urlencode($search[$key]);
445 }
446 }
447 // Add $param from hooks
448 $parameters = array();
449 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
450 $param .= $hookmanager->resPrint;
451
452 $url_file = $context->getControllerUrl($context->controller);
453 $html .= '<form method="POST" id="searchFormList" action="' . $url_file . '">' . "\n";
454 $html .= $context->getFormToken();
455 $html .= '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
456 $html .= '<input type="hidden" name="action" value="list">';
457 $html .= '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
458 $html .= '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
459 $html .= '<input type="hidden" name="page" value="' . $page . '">';
460 $html .= '<input type="hidden" name="contextpage" value="' . $contextpage . '">';
461
462 // pagination
463 $pagination_param = $param . '&sortfield=' . $sortfield . '&sortorder=' . $sortorder;
464 $html .= '<nav id="webportal-' . $elementEn . '-pagination">';
465 $html .= '<ul>';
466 $html .= '<li><strong>' . $langs->trans($titleKey) . '</strong> (' . $nbtotalofrecords . ')</li>';
467 $html .= '</ul>';
468
469 /* Generate pagination list */
470 $html .= static::generatePageListNav($url_file . $pagination_param, $nbpages, $page);
471
472 $html .= '</nav>';
473
474 // table with search filters and column titles
475 $html .= '<table id="webportal-' . $elementEn . '-list" responsive="scroll" role="grid">';
476 // title and desc for table
477 //if ($titleKey != '') {
478 // $html .= '<caption id="table-collapse-responsive">';
479 // $html .= $langs->trans($titleKey) . '<br/>';
480 // if ($titleDescKey != '') {
481 // $html .= '<small>' . $langs->trans($titleDescKey) . '</small>';
482 // }
483 // $html .= '</caption>';
484 //}
485
486 $html .= '<thead>';
487
488 // Fields title search
489 // --------------------------------------------------------------------
490 $html .= '<tr role="search-row">';
491 // Action column
492 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
493 $html .= '<td data-col="row-checkbox" >';
494 $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>';
495 $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>';
496 $html .= '</td>';
497 // }
498 foreach ($object->fields as $key => $val) {
499 if (!empty($arrayfields['t.' . $key]['checked'])) {
500 $html .= '<td data-label="' . $arrayfields['t.' . $key]['label'] . '" data-col="'.dol_escape_htmltag($key).'" >';
501 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
502 $html .= $this->form->selectarray('search_' . $key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', '');
503 } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) {
504 $postDateStart = dol_mktime(0, 0, 0, $search[$key . '_dtstartmonth'], $search[$key . '_dtstartday'], $search[$key . '_dtstartyear']);
505 $postDateEnd = dol_mktime(0, 0, 0, $search[$key . '_dtendmonth'], $search[$key . '_dtendday'], $search[$key . '_dtendyear']);
506
507 $html .= '<div class="grid width150">';
508 $html .= $this->form->inputDate('search_' . $key . '_dtstart', $postDateStart ? $postDateStart : '', $langs->trans('From'));
509 $html .= '</div>';
510 $html .= '<div class="grid width150">';
511 $html .= $this->form->inputDate('search_' . $key . '_dtend', $postDateEnd ? $postDateEnd : '', $langs->trans('to'));
512 $html .= '</div>';
513 } else {
514 $html .= '<input type="text" name="search_' . $key . '" value="' . dol_escape_htmltag(isset($search[$key]) ? $search[$key] : '') . '">';
515 }
516 $html .= '</td>';
517 }
518 }
519 // Fields from hook
520 $parameters = array('arrayfields' => $arrayfields);
521 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
522 $html .= $hookmanager->resPrint;
523 // Remain to pay
524 if (!empty($arrayfields['remain_to_pay']['checked'])) {
525 $html .= '<td data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
526 $html .= '</td>';
527 }
528 // Download link
529 if (!empty($arrayfields['download_link']['checked'])) {
530 $html .= '<td data-label="' . $arrayfields['download_link']['label'] . '">';
531 $html .= '</td>';
532 }
533 // Signature link
534 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
535 if (!empty($arrayfields['signature_link']['checked'])) {
536 $html .= '<td data-label="' . $arrayfields['signature_link']['label'] . '">';
537 $html .= '</td>';
538 }
539 }
540 $html .= '</tr>';
541
542 $totalarray = array();
543 $totalarray['nbfield'] = 0;
544
545 // Fields title label
546 // --------------------------------------------------------------------
547 $html .= '<tr>';
548 // Action column
549 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
550 $html .= '<th data-col="row-checkbox" ></th>';
551 $totalarray['nbfield']++;
552 // }
553 foreach ($object->fields as $key => $val) {
554 $tableKey = 't.' . $key;
555 if (!empty($arrayfields[$tableKey]['checked'])) {
556 $tableOrder = '';
557 if (array_key_exists($tableKey, $sortList)) {
558 $tableOrder = strtolower($sortList[$tableKey]);
559 }
560 $url_param = $url_file . '&sortfield=' . $tableKey . '&sortorder=' . ($tableOrder == 'desc' ? 'asc' : 'desc') . $param;
561 $html .= '<th data-col="'.dol_escape_htmltag($key).'" scope="col"' . ($tableOrder != '' ? ' table-order="' . $tableOrder . '"' : '') . '>';
562 $html .= '<a href="' . $url_param . '">';
563 $html .= $langs->trans($arrayfields['t.' . $key]['label']);
564 $html .= '</a>';
565 $html .= '</th>';
566 $totalarray['nbfield']++;
567 }
568 }
569 // Remain to pay
570 if (!empty($arrayfields['remain_to_pay']['checked'])) {
571 $html .= '<th scope="col">';
572 $html .= $langs->trans($arrayfields['remain_to_pay']['label']);
573 $html .= '</th>';
574 $totalarray['nbfield']++;
575 }
576 // Download link
577 if (!empty($arrayfields['download_link']['checked'])) {
578 $html .= '<th scope="col">';
579 $html .= $langs->trans($arrayfields['download_link']['label']);
580 $html .= '</th>';
581 $totalarray['nbfield']++;
582 }
583 // Signature link
584 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
585 if (!empty($arrayfields['signature_link']['checked'])) {
586 $html .= '<th scope="col">';
587 $html .= $langs->trans($arrayfields['signature_link']['label']);
588 $html .= '</th>';
589 $totalarray['nbfield']++;
590 }
591 }
592
593 // Hook fields
594 $parameters = array('arrayfields' => $arrayfields, 'sortfield' => $sortfield, 'sortorder' => $sortorder, 'totalarray' => &$totalarray);
595 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
596 $html .= $hookmanager->resPrint;
597 $html .= '</tr>';
598
599 $html .= '</thead>';
600
601 $html .= '<tbody>';
602
603 // Store company
604 $idCompany = (int) $socid;
605 if (!isset($this->companyStaticList[$socid])) {
606 $companyStatic = new Societe($this->db);
607 $companyStatic->fetch($idCompany);
608 $this->companyStaticList[$idCompany] = $companyStatic;
609 }
610 $companyStatic = $this->companyStaticList[$socid];
611
612 // Loop on record
613 // --------------------------------------------------------------------
614 $i = 0;
615 $totalarray = [
616 'nbfield' => 0,
617 'totalizable' => [],
618 ];
619 $imaxinloop = ($limit ? min($num, $limit) : $num);
620 while ($i < $imaxinloop) {
621 $obj = $this->db->fetch_object($resql);
622 if (empty($obj)) {
623 break; // Should not happen
624 }
625
626 // Store properties in $object
627 $object->setVarsFromFetchObj($obj);
628
629 // specific to get invoice status (depends on payment)
630 $payment = -1;
631 if ($elementEn == 'invoice') {
632 // paid sum
633 $payment = $object->getSommePaiement();
634 $totalcreditnotes = $object->getSumCreditNotesUsed();
635 $totaldeposits = $object->getSumDepositsUsed();
636
637 // remain to pay
638 $totalpay = $payment + $totalcreditnotes + $totaldeposits;
639 $remaintopay = price2num($object->total_ttc - $totalpay);
640 if ($object->status == Facture::STATUS_CLOSED && $object->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment
641 $remaintopay = 0;
642 }
643 if ($object->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1 && $discount) {
644 $remaincreditnote = $discount->getAvailableDiscounts($companyStatic, '', 'rc.fk_facture_source=' . $object->id);
645 $remaintopay = -$remaincreditnote;
646 }
647 }
648
649 // Show line of result
650 $html .= '<tr data-rowid="' . $object->id . '">';
651 // if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
652 $html .= '<td class="nowraponall">';
653 $html .= '</td>';
654 if (!$i) {
655 $totalarray['nbfield']++;
656 }
657 // }
658 foreach ($object->fields as $key => $val) {
659 if (!empty($arrayfields['t.' . $key]['checked'])) {
660 $html .= '<td class="nowraponall" data-label="' . $arrayfields['t.' . $key]['label'] . '">';
661 if ($key == 'status' || $key == 'fk_statut') {
662 if ($elementEn == 'invoice') {
663 // specific to get invoice status (depends on payment)
664 $html .= $object->getLibStatut(5, $payment);
665 } else {
666 $html .= $object->getLibStatut(5);
667 }
668 } elseif ($key == 'rowid') {
669 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->id, '');
670 } else {
671 $html .= $this->form->showOutputFieldForObject($object, $val, $key, $object->$key, '');
672 }
673 $html .= '</td>';
674
675
676 if (!$i) {
677 $totalarray['nbfield']++;
678 }
679 if (!empty($val['isameasure']) && $val['isameasure'] == 1) {
680 if (!$i) {
681 $totalarray['pos'][$totalarray['nbfield']] = 't.' . $key;
682 }
683 if (!isset($totalarray['val'])) {
684 $totalarray['val'] = array();
685 }
686 if (!isset($totalarray['val']['t.' . $key])) {
687 $totalarray['val']['t.' . $key] = 0;
688 }
689 $totalarray['val']['t.' . $key] += $object->$key;
690 }
691 }
692 }
693 // Remain to pay
694 if (!empty($arrayfields['remain_to_pay']['checked'])) {
695 $html .= '<td class="nowraponall" data-label="' . $arrayfields['remain_to_pay']['label'] . '">';
696 $html .= $this->form->showOutputFieldForObject($object, $arrayfields['remain_to_pay'], 'remain_to_pay', $remaintopay, '');
697 //$html .= price($remaintopay);
698 $html .= '</td>';
699 if (!$i) {
700 $totalarray['nbfield']++;
701 }
702 }
703 // Download link
704 if (!empty($arrayfields['download_link']['checked'])) {
705 $element = $object->element;
706 $html .= '<td class="nowraponall" data-label="' . $arrayfields['download_link']['label'] . '">';
707 $filename = dol_sanitizeFileName($obj->ref);
708 $filedir = $conf->{$element}->multidir_output[$obj->element_entity] . '/' . dol_sanitizeFileName($obj->ref);
709 $html .= $this->form->getDocumentsLink($element, $filename, $filedir);
710 $html .= '</td>';
711 if (!$i) {
712 $totalarray['nbfield']++;
713 }
714 }
715 // Signature link
716 if ($elementEn == "propal" && getDolGlobalString("PROPOSAL_ALLOW_ONLINESIGN") != 0) {
717 if (!empty($arrayfields['signature_link']['checked'])) {
718 $html .= '<td class="nowraponall" data-label="' . $arrayfields['signature_link']['label'] . '">';
719 if ($object->fk_statut == Propal::STATUS_VALIDATED) {
720 $html .= $this->form->getSignatureLink('proposal', $object);
721 }
722 $html .= '</td>';
723 if (!$i) {
724 $totalarray['nbfield']++;
725 }
726 }
727 }
728 // Fields from hook
729 $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray);
730 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
731 $html .= $hookmanager->resPrint;
732
733 $html .= '</tr>';
734
735 $i++;
736 }
737
738 // Move fields of totalizable into the common array pos and val
739 if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
740 foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
741 $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
742 $totalarray['val'][$keytotalizable] = isset($valtotalizable['total']) ? $valtotalizable['total'] : 0;
743 }
744 }
745 // Show total line
746 if (isset($totalarray['pos'])) {
747 $html .= '<tr>';
748 $i = 0;
749 while ($i < $totalarray['nbfield']) {
750 $i++;
751 if (!empty($totalarray['pos'][$i])) {
752 $html .= '<td class="nowraponall essai">';
753 $html .= price(!empty($totalarray['val'][$totalarray['pos'][$i]]) ? $totalarray['val'][$totalarray['pos'][$i]] : 0);
754 $html .= '</td>';
755 } else {
756 if ($i == 1) {
757 $html .= '<td>' . $langs->trans("Total") . '</td>';
758 } else {
759 $html .= '<td></td>';
760 }
761 }
762 }
763 $html .= '</tr>';
764 }
765
766 // If no record found
767 if ($num == 0) {
768 $colspan = 1;
769 foreach ($arrayfields as $key => $val) {
770 if (!empty($val['checked'])) {
771 $colspan++;
772 }
773 }
774 $html .= '<tr><td colspan="' . $colspan . '"><span class="opacitymedium">' . $langs->trans("NoRecordFound") . '</span></td></tr>';
775 }
776
777 $html .= '</tbody>';
778
779 $this->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
783 $html .= $hookmanager->resPrint;
784
785 $html .= '</table>';
786
787 $html .= '</form>';
788
789 return $html;
790 }
791
800 public static function generatePageListNav(string $url, int $nbPages, int $currentPage)
801 {
802 global $langs;
803
804 // Return nothing (no navigation bar), if there is only 1 page.
805 if ($nbPages <= 1) {
806 return '';
807 }
808
809 $pSep = strpos($url, '?') === false ? '?' : '&amp;';
810
811 $html = '<ul class="pages-nav-list">';
812
813 if ($currentPage > 1) {
814 $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>';
815 }
816
817 $maxPaginItem = min($nbPages, 5);
818 $minPageNum = max(1, $currentPage - 3);
819 $maxPageNum = min($nbPages, $currentPage + 3);
820
821 if ($minPageNum > 1) {
822 $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>';
823 $html .= '<li>&hellip;</li>';
824 }
825
826 for ($p = $minPageNum; $p <= $maxPageNum; $p++) {
827 $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>';
828 }
829
830 if ($maxPaginItem < $nbPages) {
831 $html .= '<li>&hellip;</li>';
832 $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>';
833 }
834
835 if ($currentPage < $nbPages) {
836 $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>';
837 }
838
839 $html .= '</ul>';
840
841 return $html;
842 }
843}
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.
const STATUS_VALIDATED
Validated status.
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...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
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...
$context
@method int call_trigger(string $triggerName, User $user)
Definition logout.php:42